devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
2,099 lines • 90.8 kB
JavaScript
/**
* DevExtreme (ui/scheduler/workspaces/ui.scheduler.work_space.js)
* Version: 20.1.7
* Build date: Tue Aug 25 2020
*
* Copyright (c) 2012 - 2020 Developer Express Inc. ALL RIGHTS RESERVED
* Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
*/
"use strict";
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function")
}
}
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) {
descriptor.writable = true
}
Object.defineProperty(target, descriptor.key, descriptor)
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) {
_defineProperties(Constructor.prototype, protoProps)
}
if (staticProps) {
_defineProperties(Constructor, staticProps)
}
return Constructor
}
var $ = require("../../../core/renderer");
var domAdapter = require("../../../core/dom_adapter");
var eventsEngine = require("../../../events/core/events_engine");
var dataUtils = require("../../../core/element_data");
var dateUtils = require("../../../core/utils/date");
var typeUtils = require("../../../core/utils/type");
var windowUtils = require("../../../core/utils/window");
var getPublicElement = require("../../../core/utils/dom").getPublicElement;
var extend = require("../../../core/utils/extend").extend;
var each = require("../../../core/utils/iterator").each;
var getBoundingRect = require("../../../core/utils/position").getBoundingRect;
var messageLocalization = require("../../../localization/message");
var dateLocalization = require("../../../localization/date");
var toMs = dateUtils.dateToMilliseconds;
var Widget = require("../../widget/ui.widget");
var abstract = Widget.abstract;
var noop = require("../../../core/utils/common").noop;
var isDefined = require("../../../core/utils/type").isDefined;
var publisherMixin = require("../ui.scheduler.publisher_mixin");
var eventUtils = require("../../../events/utils");
var pointerEvents = require("../../../events/pointer");
var errors = require("../../widget/ui.errors");
var clickEvent = require("../../../events/click");
var contextMenuEvent = require("../../../events/contextmenu");
var dragEvents = require("../../../events/drag");
var Scrollable = require("../../scroll_view/ui.scrollable");
var HorizontalGroupedStrategy = require("./ui.scheduler.work_space.grouped.strategy.horizontal");
var VerticalGroupedStrategy = require("./ui.scheduler.work_space.grouped.strategy.vertical");
var tableCreator = require("../ui.scheduler.table_creator");
var VerticalShader = require("../shaders/ui.scheduler.current_time_shader.vertical");
var AppointmentDragBehavior = require("../appointmentDragBehavior");
var FIXED_CONTAINER_CLASS = require("../constants").FIXED_CONTAINER_CLASS;
var timeZoneUtils = require("../utils.timeZone");
var COMPONENT_CLASS = "dx-scheduler-work-space";
var GROUPED_WORKSPACE_CLASS = "dx-scheduler-work-space-grouped";
var VERTICAL_GROUPED_WORKSPACE_CLASS = "dx-scheduler-work-space-vertical-grouped";
var WORKSPACE_VERTICAL_GROUP_TABLE_CLASS = "dx-scheduler-work-space-vertical-group-table";
var WORKSPACE_WITH_BOTH_SCROLLS_CLASS = "dx-scheduler-work-space-both-scrollbar";
var WORKSPACE_WITH_COUNT_CLASS = "dx-scheduler-work-space-count";
var WORKSPACE_WITH_GROUP_BY_DATE_CLASS = "dx-scheduler-work-space-group-by-date";
var WORKSPACE_WITH_ODD_CELLS_CLASS = "dx-scheduler-work-space-odd-cells";
var TIME_PANEL_CLASS = "dx-scheduler-time-panel";
var TIME_PANEL_CELL_CLASS = "dx-scheduler-time-panel-cell";
var TIME_PANEL_ROW_CLASS = "dx-scheduler-time-panel-row";
var ALL_DAY_PANEL_CLASS = "dx-scheduler-all-day-panel";
var ALL_DAY_TABLE_CLASS = "dx-scheduler-all-day-table";
var ALL_DAY_CONTAINER_CLASS = "dx-scheduler-all-day-appointments";
var ALL_DAY_TITLE_CLASS = "dx-scheduler-all-day-title";
var ALL_DAY_TITLE_HIDDEN_CLASS = "dx-scheduler-all-day-title-hidden";
var ALL_DAY_TABLE_CELL_CLASS = "dx-scheduler-all-day-table-cell";
var ALL_DAY_TABLE_ROW_CLASS = "dx-scheduler-all-day-table-row";
var WORKSPACE_WITH_ALL_DAY_CLASS = "dx-scheduler-work-space-all-day";
var WORKSPACE_WITH_COLLAPSED_ALL_DAY_CLASS = "dx-scheduler-work-space-all-day-collapsed";
var WORKSPACE_WITH_MOUSE_SELECTION_CLASS = "dx-scheduler-work-space-mouse-selection";
var HORIZONTAL_SIZES_CLASS = "dx-scheduler-cell-sizes-horizontal";
var VERTICAL_SIZES_CLASS = "dx-scheduler-cell-sizes-vertical";
var HEADER_PANEL_CLASS = "dx-scheduler-header-panel";
var HEADER_PANEL_CELL_CLASS = "dx-scheduler-header-panel-cell";
var HEADER_ROW_CLASS = "dx-scheduler-header-row";
var GROUP_ROW_CLASS = "dx-scheduler-group-row";
var GROUP_HEADER_CLASS = "dx-scheduler-group-header";
var GROUP_HEADER_CONTENT_CLASS = "dx-scheduler-group-header-content";
var DATE_TABLE_CLASS = "dx-scheduler-date-table";
var DATE_TABLE_CELL_CLASS = "dx-scheduler-date-table-cell";
var DATE_TABLE_ROW_CLASS = "dx-scheduler-date-table-row";
var DATE_TABLE_FOCUSED_CELL_CLASS = "dx-scheduler-focused-cell";
var DATE_TABLE_DROPPABLE_CELL_CLASS = "dx-scheduler-date-table-droppable-cell";
var SCHEDULER_HEADER_SCROLLABLE_CLASS = "dx-scheduler-header-scrollable";
var SCHEDULER_SIDEBAR_SCROLLABLE_CLASS = "dx-scheduler-sidebar-scrollable";
var SCHEDULER_DATE_TABLE_SCROLLABLE_CLASS = "dx-scheduler-date-table-scrollable";
var SCHEDULER_WORKSPACE_DXPOINTERDOWN_EVENT_NAME = eventUtils.addNamespace(pointerEvents.down, "dxSchedulerWorkSpace");
var SCHEDULER_CELL_DXDRAGENTER_EVENT_NAME = eventUtils.addNamespace(dragEvents.enter, "dxSchedulerDateTable");
var SCHEDULER_CELL_DXDROP_EVENT_NAME = eventUtils.addNamespace(dragEvents.drop, "dxSchedulerDateTable");
var SCHEDULER_CELL_DXDRAGLEAVE_EVENT_NAME = eventUtils.addNamespace(dragEvents.leave, "dxSchedulerDateTable");
var SCHEDULER_CELL_DXCLICK_EVENT_NAME = eventUtils.addNamespace(clickEvent.name, "dxSchedulerDateTable");
var SCHEDULER_CELL_DXPOINTERDOWN_EVENT_NAME = eventUtils.addNamespace(pointerEvents.down, "dxSchedulerDateTable");
var SCHEDULER_CELL_DXPOINTERUP_EVENT_NAME = eventUtils.addNamespace(pointerEvents.up, "dxSchedulerDateTable");
var SCHEDULER_CELL_DXPOINTERMOVE_EVENT_NAME = eventUtils.addNamespace(pointerEvents.move, "dxSchedulerDateTable");
var CELL_DATA = "dxCellData";
var DATE_TABLE_CELL_BORDER = 1;
var DATE_TABLE_MIN_CELL_WIDTH = 75;
var DAY_MS = toMs("day");
var HOUR_MS = toMs("hour");
var SCHEDULER_DRAG_AND_DROP_SELECTOR = ".".concat(DATE_TABLE_CLASS, " td, .").concat(ALL_DAY_TABLE_CLASS, " td");
var ScrollSemaphore = function() {
function ScrollSemaphore() {
_classCallCheck(this, ScrollSemaphore);
this.counter = 0
}
_createClass(ScrollSemaphore, [{
key: "isFree",
value: function() {
return 0 === this.counter
}
}, {
key: "take",
value: function() {
this.counter++
}
}, {
key: "release",
value: function() {
this.counter--;
if (this.counter < 0) {
this.counter = 0
}
}
}]);
return ScrollSemaphore
}();
var formatWeekday = function(date) {
return dateLocalization.getDayNames("abbreviated")[date.getDay()]
};
var SchedulerWorkSpace = Widget.inherit({
_supportedKeys: function() {
var clickHandler = function(e) {
e.preventDefault();
e.stopPropagation();
if (this._focusedCells && this._focusedCells.length) {
var $itemElement = $(this.option("focusedElement"));
var $cellElement = $itemElement.length ? $itemElement : this._focusedCells;
e.target = this._focusedCells;
this._showPopup = true;
this._cellClickAction({
event: e,
cellElement: $(this._focusedCells),
cellData: this.getCellData($cellElement)
})
}
};
var arrowPressHandler = function(e, cell) {
e.preventDefault();
e.stopPropagation();
this._moveToCell(cell, e.shiftKey)
};
return extend(this.callBase(), {
enter: clickHandler,
space: clickHandler,
downArrow: function(e) {
var $cell = this._getCellFromNextRow("next", e.shiftKey);
arrowPressHandler.call(this, e, $cell)
},
upArrow: function(e) {
var $cell = this._getCellFromNextRow("prev", e.shiftKey);
arrowPressHandler.call(this, e, $cell)
},
rightArrow: function(e) {
var $rightCell = this._getCellFromNextColumn("next", e.shiftKey);
arrowPressHandler.call(this, e, $rightCell)
},
leftArrow: function(e) {
var $leftCell = this._getCellFromNextColumn("prev", e.shiftKey);
arrowPressHandler.call(this, e, $leftCell)
}
})
},
_isRTL: function() {
return this.option("rtlEnabled")
},
_getFocusedCell: function() {
return this._$focusedCell || this._$dateTable.find("." + DATE_TABLE_CELL_CLASS).eq(0)
},
_getAllFocusedCells: function() {
return this._focusedCells || this._$dateTable.find("." + DATE_TABLE_CELL_CLASS).eq(0)
},
_getCellFromNextRow: function(direction) {
var $currentCell = this._$focusedCell;
if (isDefined($currentCell)) {
var cellIndex = $currentCell.index();
var $row = $currentCell.parent();
var $cell = $row[direction]().children().eq(cellIndex);
$cell = this._checkForViewBounds($cell);
return $cell
}
},
_checkForViewBounds: function($item) {
if (!$item.length) {
$item = this._$focusedCell
}
return $item
},
_getCellFromNextColumn: function(direction, isMultiSelection) {
var $focusedCell = this._$focusedCell;
if (!isDefined($focusedCell)) {
return
}
var $nextCell;
var $row = $focusedCell.parent();
var nextColumnDirection = direction;
var isDirectionNext = "next" === direction;
var previousColumnDirection = isDirectionNext ? "prev" : "next";
var isRTL = this._isRTL();
var groupCount = this._getGroupCount();
var isHorizontalGrouping = this._isHorizontalGroupedWorkSpace();
var isGroupedByDate = this.isGroupedByDate();
var totalCellCount = this._getTotalCellCount(groupCount);
var rowCellCount = isMultiSelection && !isGroupedByDate ? this._getCellCount() : totalCellCount;
var lastIndexInRow = rowCellCount - 1;
var currentIndex = $focusedCell.index();
var step = isGroupedByDate && isMultiSelection ? groupCount : 1;
var isEdgeCell = this._isEdgeCell(isHorizontalGrouping ? totalCellCount - 1 : lastIndexInRow, currentIndex, step, direction);
var sign = isRTL ? 1 : -1;
var directionSign = isDirectionNext ? 1 : -1;
var resultingSign = sign * directionSign;
if (isEdgeCell || isMultiSelection && this._isGroupEndCell($focusedCell, direction)) {
var nextIndex = currentIndex - resultingSign * step + resultingSign * rowCellCount;
var rowDirection = isRTL ? previousColumnDirection : nextColumnDirection;
$nextCell = $row[rowDirection]().children().eq(nextIndex);
$nextCell = this._checkForViewBounds($nextCell)
} else {
$nextCell = $row.children().eq(currentIndex - resultingSign * step)
}
return $nextCell
},
_isEdgeCell: function(lastIndexInRow, cellIndex, step, direction) {
var isRTL = this._isRTL();
var isDirectionNext = "next" === direction;
var rightEdgeCellIndex = isRTL ? 0 : lastIndexInRow;
var leftEdgeCellIndex = isRTL ? lastIndexInRow : 0;
var edgeCellIndex = isDirectionNext ? rightEdgeCellIndex : leftEdgeCellIndex;
var isNextCellGreaterThanEdge = cellIndex + step > edgeCellIndex;
var isNextCellLessThanEdge = cellIndex - step < edgeCellIndex;
var isRightEdgeCell = isRTL ? isNextCellLessThanEdge : isNextCellGreaterThanEdge;
var isLeftEdgeCell = isRTL ? isNextCellGreaterThanEdge : isNextCellLessThanEdge;
return isDirectionNext ? isRightEdgeCell : isLeftEdgeCell
},
_isGroupEndCell: function($cell, direction) {
if (this.isGroupedByDate()) {
return false
}
var isDirectionNext = "next" === direction;
var cellsInRow = this._getCellCount();
var currentCellIndex = $cell.index();
var result = currentCellIndex % cellsInRow;
var endCell = isDirectionNext ? cellsInRow - 1 : 0;
var startCell = isDirectionNext ? 0 : cellsInRow - 1;
return this._isRTL() ? result === startCell : result === endCell
},
_moveToCell: function($cell, isMultiSelection) {
isMultiSelection = isMultiSelection && this.option("allowMultipleCellSelection");
this._setFocusedCell($cell, isMultiSelection);
this._dateTableScrollable.scrollToElement($cell)
},
_setFocusedCell: function($cell, isMultiSelection) {
if (!isDefined($cell) || !$cell.length) {
return
}
this._releaseFocusedCell();
this._focusedCells = [];
if (isMultiSelection) {
$cell = this._correctCellForGroup($cell);
var orientation = "day" === this.option("type") && (!this.option("groups").length || "vertical" === this.option("groupOrientation")) ? "vertical" : "horizontal";
var $targetCells = this._getCellsBetween($cell, this._$prevCell, orientation);
this._focusedCells = $targetCells.toArray()
} else {
this._focusedCells = [$cell.get(0)];
this._$prevCell = $cell
}
var $focusedCells = $(this._focusedCells);
this._toggleFocusClass(true, $focusedCells);
this.setAria("label", "Add appointment", $focusedCells);
this._toggleFocusedCellClass(true, $cell);
this._$focusedCell = $cell;
var selectedCellData = this.getFocusedCellData();
this.option("selectedCellData", selectedCellData);
this._selectionChangedAction({
selectedCellData: selectedCellData
})
},
_correctCellForGroup: function($cell) {
var $focusedCell = this._$focusedCell;
var cellGroupIndex = this._getGroupIndexByCell($cell);
var focusedCellGroupIndex = this._getGroupIndexByCell($focusedCell);
var isDifferentTables = this._hasAllDayClass($cell) !== this._hasAllDayClass($focusedCell);
return focusedCellGroupIndex !== cellGroupIndex || isDifferentTables ? $focusedCell : $cell
},
_getCellsBetween: function($first, $last, direction) {
var isAllDayTable = this._hasAllDayClass($last);
var $cells = this._getCells(isAllDayTable, direction);
var firstIndex = $cells.index($first);
var lastIndex = $cells.index($last);
if (firstIndex > lastIndex) {
var buffer = firstIndex;
firstIndex = lastIndex;
lastIndex = buffer
}
$cells = $cells.slice(firstIndex, lastIndex + 1);
if (this._getGroupCount() > 1) {
var result = [];
var focusedGroupIndex = this._getGroupIndexByCell($first);
each($cells, function(_, cell) {
var groupIndex = this._getGroupIndexByCell($(cell));
if (focusedGroupIndex === groupIndex) {
result.push(cell)
}
}.bind(this));
$cells = $(result)
}
return $cells
},
_hasAllDayClass: function($cell) {
return $cell.hasClass(ALL_DAY_TABLE_CELL_CLASS)
},
_getGroupIndexByCell: function($cell) {
return this._groupedStrategy.getGroupIndexByCell($cell)
},
_toggleFocusedCellClass: function(isFocused, $element) {
var $focusTarget = $element && $element.length ? $element : this._focusTarget();
$focusTarget.toggleClass(DATE_TABLE_FOCUSED_CELL_CLASS, isFocused)
},
_releaseFocusedCell: function($cell) {
$cell = $cell || $(this._focusedCells);
if (isDefined($cell) && $cell.length) {
this._toggleFocusClass(false, $cell);
this._toggleFocusedCellClass(false, $cell);
this.setAria("label", void 0, $cell)
}
this.option("selectedCellData", [])
},
_focusInHandler: function(e) {
if ($(e.target).is(this._focusTarget()) && false !== this._isCellClick) {
delete this._isCellClick;
delete this._contextMenuHandled;
this.callBase.apply(this, arguments);
var $cell = this._getFocusedCell();
this._setFocusedCell($cell)
}
},
_focusOutHandler: function() {
this.callBase.apply(this, arguments);
if (!this._contextMenuHandled) {
this._releaseFocusedCell()
}
},
_focusTarget: function() {
return this.$element()
},
_activeStateUnit: "." + DATE_TABLE_CELL_CLASS + ", ." + ALL_DAY_TABLE_CELL_CLASS,
_getDefaultOptions: function() {
return extend(this.callBase(), {
currentDate: new Date,
intervalCount: 1,
startDate: null,
firstDayOfWeek: void 0,
startDayHour: 0,
endDayHour: 24,
hoursInterval: .5,
activeStateEnabled: true,
hoverStateEnabled: true,
groups: [],
showAllDayPanel: true,
allDayExpanded: false,
onCellClick: null,
crossScrollingEnabled: false,
dataCellTemplate: null,
timeCellTemplate: null,
resourceCellTemplate: null,
dateCellTemplate: null,
allowMultipleCellSelection: true,
indicatorTime: new Date,
indicatorUpdateInterval: 5 * toMs("minute"),
shadeUntilCurrentTime: true,
groupOrientation: "horizontal",
selectedCellData: [],
groupByDate: false
})
},
_optionChanged: function(args) {
switch (args.name) {
case "startDayHour":
case "endDayHour":
this.invoke("validateDayHours");
this._cleanWorkSpace();
break;
case "dateCellTemplate":
case "resourceCellTemplate":
case "dataCellTemplate":
case "timeCellTemplate":
case "hoursInterval":
case "firstDayOfWeek":
case "currentDate":
case "startDate":
this._cleanWorkSpace();
break;
case "groups":
this._cleanView();
this._removeAllDayElements();
this._initGrouping();
this.repaint();
break;
case "groupOrientation":
this._initGroupedStrategy();
this._createAllDayPanelElements();
this._removeAllDayElements();
this._cleanWorkSpace();
this._toggleGroupByDateClass();
break;
case "showAllDayPanel":
if (this._isVerticalGroupedWorkSpace()) {
this._cleanView();
this._removeAllDayElements();
this._initGrouping();
this.repaint()
} else {
this._toggleAllDayVisibility()
}
break;
case "allDayExpanded":
this._changeAllDayVisibility();
this._attachTablesEvents();
this.headerPanelOffsetRecalculate();
this._updateScrollable();
break;
case "onSelectionChanged":
this._createSelectionChangedAction();
break;
case "onCellClick":
this._createCellClickAction();
break;
case "onCellContextMenu":
this._attachContextMenuEvent();
break;
case "intervalCount":
this._cleanWorkSpace();
this._toggleWorkSpaceCountClass();
this._toggleFixedScrollableClass();
break;
case "groupByDate":
this._cleanWorkSpace();
this._toggleGroupByDateClass();
break;
case "crossScrollingEnabled":
this._toggleHorizontalScrollClass();
this._dateTableScrollable.option(this._dateTableScrollableConfig());
break;
case "width":
this.callBase(args);
this._dimensionChanged();
break;
case "allowMultipleCellSelection":
break;
case "selectedCellData":
break;
default:
this.callBase(args)
}
},
_cleanWorkSpace: function() {
this._cleanView();
this._toggleGroupedClass();
this._toggleWorkSpaceWithOddCells();
this._renderView()
},
_init: function() {
this._headerSemaphore = new ScrollSemaphore;
this._sideBarSemaphore = new ScrollSemaphore;
this._dataTableSemaphore = new ScrollSemaphore;
this.callBase();
this._initGrouping();
this._toggleHorizontalScrollClass();
this._toggleWorkSpaceCountClass();
this._toggleGroupByDateClass();
this._toggleWorkSpaceWithOddCells();
this.$element().addClass(COMPONENT_CLASS).addClass(this._getElementClass())
},
_initGrouping: function() {
this._initGroupedStrategy();
this._toggleGroupingDirectionClass();
this._toggleGroupByDateClass()
},
_initGroupedStrategy: function() {
var strategyName = this.option("groups").length ? this.option("groupOrientation") : this._getDefaultGroupStrategy();
var Strategy = "vertical" === strategyName ? VerticalGroupedStrategy : HorizontalGroupedStrategy;
this._groupedStrategy = new Strategy(this)
},
_getDefaultGroupStrategy: function() {
return "horizontal"
},
_isVerticalGroupedWorkSpace: function() {
return !!this.option("groups").length && "vertical" === this.option("groupOrientation")
},
_isHorizontalGroupedWorkSpace: function() {
return !!this.option("groups").length && "horizontal" === this.option("groupOrientation")
},
_toggleHorizontalScrollClass: function() {
this.$element().toggleClass(WORKSPACE_WITH_BOTH_SCROLLS_CLASS, this.option("crossScrollingEnabled"))
},
_toggleGroupByDateClass: function() {
this.$element().toggleClass(WORKSPACE_WITH_GROUP_BY_DATE_CLASS, this.isGroupedByDate())
},
_toggleWorkSpaceCountClass: function() {
this.$element().toggleClass(WORKSPACE_WITH_COUNT_CLASS, this._isWorkSpaceWithCount())
},
_isWorkSpaceWithCount: function() {
return this.option("intervalCount") > 1
},
_toggleWorkSpaceWithOddCells: function() {
this.$element().toggleClass(WORKSPACE_WITH_ODD_CELLS_CLASS, this._isWorkspaceWithOddCells())
},
_isWorkspaceWithOddCells: function() {
return .5 === this.option("hoursInterval")
},
_toggleGroupingDirectionClass: function() {
this.$element().toggleClass(VERTICAL_GROUPED_WORKSPACE_CLASS, this._isVerticalGroupedWorkSpace())
},
_getRealGroupOrientation: function() {
return this._isVerticalGroupedWorkSpace() ? "vertical" : "horizontal"
},
_getTimePanelClass: function() {
return TIME_PANEL_CLASS
},
_getDateTableClass: function() {
return DATE_TABLE_CLASS
},
_getDateTableRowClass: function() {
return DATE_TABLE_ROW_CLASS
},
_getDateTableCellClass: function(i, j) {
var cellClass = DATE_TABLE_CELL_CLASS + " " + HORIZONTAL_SIZES_CLASS + " " + VERTICAL_SIZES_CLASS;
return this._needApplyLastGroupCellClass() ? this._groupedStrategy.addAdditionalGroupCellClasses(cellClass, j + 1, i, j) : cellClass
},
_needApplyLastGroupCellClass: function() {
return true
},
_getGroupRowClass: function() {
return GROUP_ROW_CLASS
},
_getGroupHeaderClass: function(i) {
var cellClass = GROUP_HEADER_CLASS;
return this._groupedStrategy.addAdditionalGroupCellClasses(cellClass, i + 1)
},
_getGroupHeaderContentClass: function() {
return GROUP_HEADER_CONTENT_CLASS
},
_initWorkSpaceUnits: function() {
this._$headerPanel = $("<table>");
this._$thead = $("<thead>").appendTo(this._$headerPanel);
this._$fixedContainer = $("<div>").addClass(FIXED_CONTAINER_CLASS);
this._$allDayContainer = $("<div>").addClass(ALL_DAY_CONTAINER_CLASS);
this._initAllDayPanelElements();
this._createAllDayPanelElements();
this._$timePanel = $("<table>").addClass(this._getTimePanelClass());
this._$dateTable = $("<table>");
this._$groupTable = $("<div>").addClass(WORKSPACE_VERTICAL_GROUP_TABLE_CLASS)
},
_initAllDayPanelElements: function() {
this._allDayTitles = [];
this._allDayTables = [];
this._allDayPanels = []
},
_createAllDayPanelElements: function() {
var groupCount = this._getGroupCount();
if (this._isVerticalGroupedWorkSpace() && 0 !== groupCount) {
for (var i = 0; i < groupCount; i++) {
var $allDayTitle = $("<div>").addClass(ALL_DAY_TITLE_CLASS).text(messageLocalization.format("dxScheduler-allDay"));
this._allDayTitles.push($allDayTitle);
this._$allDayTable = $("<table>");
this._allDayTables.push(this._$allDayTable);
this._$allDayPanel = $("<div>").addClass(ALL_DAY_PANEL_CLASS).append(this._$allDayTable);
this._allDayPanels.push(this._$allDayPanel)
}
} else {
this._$allDayTitle = $("<div>").addClass(ALL_DAY_TITLE_CLASS).text(messageLocalization.format("dxScheduler-allDay")).appendTo(this.$element());
this._$allDayTable = $("<table>");
this._$allDayPanel = $("<div>").addClass(ALL_DAY_PANEL_CLASS).append(this._$allDayTable)
}
},
_initDateTableScrollable: function() {
var $dateTableScrollable = $("<div>").addClass(SCHEDULER_DATE_TABLE_SCROLLABLE_CLASS);
this._dateTableScrollable = this._createComponent($dateTableScrollable, Scrollable, this._dateTableScrollableConfig())
},
_dateTableScrollableConfig: function() {
var config = {
useKeyboard: false,
bounceEnabled: false,
updateManually: true,
pushBackValue: 0
};
if (this._needCreateCrossScrolling()) {
config = extend(config, this._createCrossScrollingConfig())
}
return config
},
_createCrossScrollingConfig: function() {
var _this = this;
var config = {};
config.direction = "both";
config.onScroll = function(e) {
_this._dataTableSemaphore.take();
_this._sideBarSemaphore.isFree() && _this._sidebarScrollable && _this._sidebarScrollable.scrollTo({
top: e.scrollOffset.top
});
_this._headerSemaphore.isFree() && _this._headerScrollable && _this._headerScrollable.scrollTo({
left: e.scrollOffset.left
});
_this._dataTableSemaphore.release()
};
config.onEnd = function() {
_this.notifyObserver("updateResizableArea", {})
};
return config
},
_createWorkSpaceElements: function() {
if (this.option("crossScrollingEnabled")) {
this._createWorkSpaceScrollableElements()
} else {
this._createWorkSpaceStaticElements()
}
},
_createWorkSpaceStaticElements: function() {
if (this._isVerticalGroupedWorkSpace()) {
this._dateTableScrollable.$content().append(this._$allDayContainer, this._$groupTable, this._$timePanel, this._$dateTable);
this.$element().append(this._$fixedContainer, this._$headerPanel, this._dateTableScrollable.$element())
} else {
this._dateTableScrollable.$content().append(this._$timePanel, this._$dateTable);
this.$element().append(this._$fixedContainer, this._$headerPanel, this._$allDayContainer, this._$allDayPanel, this._dateTableScrollable.$element())
}
},
_createWorkSpaceScrollableElements: function() {
this.$element().append(this._$fixedContainer);
this._createHeaderScrollable();
this._createSidebarScrollable();
this.$element().append(this._dateTableScrollable.$element());
this._headerScrollable.$content().append(this._$headerPanel);
this._dateTableScrollable.$content().append(this._$dateTable);
if (this._isVerticalGroupedWorkSpace()) {
this._dateTableScrollable.$content().prepend(this._$allDayContainer);
this._sidebarScrollable.$content().append(this._$groupTable, this._$timePanel)
} else {
this._headerScrollable.$content().append(this._$allDayContainer, this._$allDayPanel)
}
this._sidebarScrollable.$content().append(this._$timePanel)
},
_createHeaderScrollable: function() {
var $headerScrollable = $("<div>").addClass(SCHEDULER_HEADER_SCROLLABLE_CLASS).appendTo(this.$element());
this._headerScrollable = this._createComponent($headerScrollable, Scrollable, this._headerScrollableConfig())
},
_headerScrollableConfig: function() {
var _this2 = this;
var config = {
useKeyboard: false,
showScrollbar: false,
direction: "horizontal",
useNative: false,
updateManually: true,
bounceEnabled: false,
pushBackValue: 0,
onScroll: function(e) {
_this2._headerSemaphore.take();
_this2._dataTableSemaphore.isFree() && _this2._dateTableScrollable.scrollTo({
left: e.scrollOffset.left
});
_this2._headerSemaphore.release()
}
};
return config
},
_createSidebarScrollable: function() {
var _this3 = this;
var $timePanelScrollable = $("<div>").addClass(SCHEDULER_SIDEBAR_SCROLLABLE_CLASS).appendTo(this.$element());
this._sidebarScrollable = this._createComponent($timePanelScrollable, Scrollable, {
useKeyboard: false,
showScrollbar: false,
direction: "vertical",
useNative: false,
updateManually: true,
bounceEnabled: false,
pushBackValue: 0,
onScroll: function(e) {
_this3._sideBarSemaphore.take();
_this3._dataTableSemaphore.isFree() && _this3._dateTableScrollable.scrollTo({
top: e.scrollOffset.top
});
_this3._sideBarSemaphore.release()
}
})
},
_visibilityChanged: function(visible) {
if (visible && this._isVerticalGroupedWorkSpace()) {
this._setHorizontalGroupHeaderCellsHeight()
}
if (visible && this._needCreateCrossScrolling()) {
this._setTableSizes()
}
},
_attachTableClasses: function() {
this._addTableClass(this._$dateTable, this._getDateTableClass());
if (this._isVerticalGroupedWorkSpace()) {
var groupCount = this._getGroupCount();
for (var i = 0; i < groupCount; i++) {
this._addTableClass(this._allDayTables[i], ALL_DAY_TABLE_CLASS)
}
} else {
this._addTableClass(this._$allDayTable, ALL_DAY_TABLE_CLASS)
}
},
_attachHeaderTableClasses: function() {
this._addTableClass(this._$headerPanel, HEADER_PANEL_CLASS)
},
_addTableClass: function($el, className) {
$el && !$el.hasClass(className) && $el.addClass(className)
},
_setTableSizes: function() {
this._attachTableClasses();
var cellWidth = this.getCellWidth();
if (cellWidth < this.getCellMinWidth()) {
cellWidth = this.getCellMinWidth()
}
var minWidth = this.getWorkSpaceMinWidth();
var $headerCells = this._$headerPanel.find("tr").last().find("th");
var width = cellWidth * $headerCells.length;
if (width < minWidth) {
width = minWidth
}
this._$headerPanel.width(width);
this._$dateTable.width(width);
this._$allDayTable && this._$allDayTable.width(width);
this._attachHeaderTableClasses();
if (this._isVerticalGroupedWorkSpace()) {
this._setHorizontalGroupHeaderCellsHeight()
}
},
getWorkSpaceMinWidth: function() {
return this._groupedStrategy.getWorkSpaceMinWidth()
},
_dimensionChanged: function() {
if (this.option("crossScrollingEnabled")) {
this._setTableSizes()
}
this.headerPanelOffsetRecalculate();
this._cleanCellDataCache();
this._cleanAllowedPositions()
},
_needCreateCrossScrolling: function() {
return this.option("crossScrollingEnabled")
},
_getElementClass: noop,
_getRowCount: noop,
_getCellCount: noop,
_getRowCountWithAllDayRows: function() {
var allDayRowCount = this.option("showAllDayPanel") ? 1 : 0;
return this._getRowCount() + allDayRowCount
},
_initMarkup: function() {
this._initWorkSpaceUnits();
this._initDateTableScrollable();
this._createWorkSpaceElements();
this.callBase();
if (!this.option("crossScrollingEnabled")) {
this._attachTableClasses();
this._attachHeaderTableClasses()
}
this._toggleGroupedClass();
this._toggleFixedScrollableClass();
this._renderView();
this._attachEvents();
this._setFocusOnCellByOption(this.option("selectedCellData"))
},
_render: function() {
this.callBase();
this._renderDateTimeIndication();
this._setIndicationUpdateInterval()
},
_toggleGroupedClass: function() {
this.$element().toggleClass(GROUPED_WORKSPACE_CLASS, this._getGroupCount() > 0)
},
_toggleFixedScrollableClass: noop,
_renderView: function() {
this._setFirstViewDate();
this._applyCellTemplates(this._renderGroupHeader());
this._renderDateHeader();
this._renderTimePanel();
if (this._isVerticalGroupedWorkSpace()) {
var groupCount = this._getGroupCount();
for (var i = 0; i < groupCount; i++) {
this._renderAllDayPanel(i)
}
}
this._renderDateTable();
this._renderAllDayPanel();
this._updateGroupTableHeight();
this._shader = new VerticalShader(this)
},
_updateGroupTableHeight: function() {
if (this._isVerticalGroupedWorkSpace() && windowUtils.hasWindow()) {
this._setHorizontalGroupHeaderCellsHeight()
}
},
_renderDateTimeIndication: noop,
_setIndicationUpdateInterval: noop,
_refreshDateTimeIndication: noop,
_setFocusOnCellByOption: function(data) {
var cells = [];
this._releaseFocusedCell();
for (var i = 0; i < data.length; i++) {
var groups = data[i].groups;
var groupIndex = this.option("groups").length && groups ? this._getGroupIndexByResourceId(groups) : 0;
var allDay = !!data[i].allDay;
var coordinates = this.getCoordinatesByDate(data[i].startDate, groupIndex, allDay);
var $cell = this._getCellByCoordinates(coordinates, groupIndex);
if (isDefined($cell)) {
this._toggleFocusClass(true, $cell);
cells.push($cell.get(0))
}
}
this._focusedCells = cells
},
_getGroupIndexByResourceId: function(id) {
var groups = this.option("groups");
var resourceTree = this.invoke("createResourcesTree", groups);
if (!resourceTree.length) {
return 0
}
return this._getGroupIndexRecursively(resourceTree, id)
},
_getGroupIndexRecursively: function(resourceTree, id) {
var _this4 = this;
var currentKey = resourceTree[0].name;
var currentValue = id[currentKey];
return resourceTree.reduce(function(prevIndex, _ref) {
var leafIndex = _ref.leafIndex,
value = _ref.value,
children = _ref.children;
var areValuesEqual = currentValue === value;
if (areValuesEqual && void 0 !== leafIndex) {
return leafIndex
}
if (areValuesEqual) {
return _this4._getGroupIndexRecursively(children, id)
}
return prevIndex
}, 0)
},
_setFirstViewDate: function() {
var firstDayOfWeek = isDefined(this._firstDayOfWeek()) ? this._firstDayOfWeek() : dateLocalization.firstDayOfWeekIndex();
this._firstViewDate = dateUtils.getFirstWeekDate(this._getViewStartByOptions(), firstDayOfWeek);
this._setStartDayHour(this._firstViewDate)
},
_getViewStartByOptions: function() {
if (!this.option("startDate")) {
return this.option("currentDate")
} else {
var startDate = dateUtils.trimTime(this._getStartViewDate());
var currentDate = this.option("currentDate");
var diff = startDate.getTime() <= currentDate.getTime() ? 1 : -1;
var endDate = new Date(startDate.getTime() + this._getIntervalDuration() * diff);
while (!this._dateInRange(currentDate, startDate, endDate, diff)) {
startDate = endDate;
endDate = new Date(startDate.getTime() + this._getIntervalDuration() * diff)
}
return diff > 0 ? startDate : endDate
}
},
_getHeaderDate: function() {
return this.getStartViewDate()
},
_getStartViewDate: function() {
return this.option("startDate")
},
_dateInRange: function(date, startDate, endDate, diff) {
return diff > 0 ? dateUtils.dateInRange(date, startDate, new Date(endDate.getTime() - 1)) : dateUtils.dateInRange(date, endDate, startDate, "date")
},
_getIntervalDuration: function() {
return toMs("day") * this.option("intervalCount")
},
_setStartDayHour: function(date) {
var startDayHour = this.option("startDayHour");
if (isDefined(startDayHour)) {
date.setHours(startDayHour, startDayHour % 1 * 60, 0, 0)
}
},
_firstDayOfWeek: function() {
return this.option("firstDayOfWeek")
},
_attachEvents: function() {
this._createSelectionChangedAction();
this._attachClickEvent();
this._attachContextMenuEvent()
},
_attachClickEvent: function() {
var that = this;
var pointerDownAction = this._createAction(function(e) {
that._pointerDownHandler(e.event)
});
this._createCellClickAction();
var cellSelector = "." + DATE_TABLE_CELL_CLASS + ",." + ALL_DAY_TABLE_CELL_CLASS;
var $element = this.$element();
eventsEngine.off($element, SCHEDULER_WORKSPACE_DXPOINTERDOWN_EVENT_NAME);
eventsEngine.off($element, SCHEDULER_CELL_DXCLICK_EVENT_NAME);
eventsEngine.on($element, SCHEDULER_WORKSPACE_DXPOINTERDOWN_EVENT_NAME, function(e) {
if (eventUtils.isMouseEvent(e) && e.which > 1) {
e.preventDefault();
return
}
pointerDownAction({
event: e
})
});
eventsEngine.on($element, SCHEDULER_CELL_DXCLICK_EVENT_NAME, cellSelector, function(e) {
var $cell = $(e.target);
that._cellClickAction({
event: e,
cellElement: getPublicElement($cell),
cellData: that.getCellData($cell)
})
})
},
_createCellClickAction: function() {
var that = this;
this._cellClickAction = this._createActionByOption("onCellClick", {
afterExecute: function(e) {
that._moveToClosestNonStub(e.args[0].event)
}
})
},
_createSelectionChangedAction: function() {
this._selectionChangedAction = this._createActionByOption("onSelectionChanged")
},
_moveToClosestNonStub: function(e) {
var $target = $(e.target);
if (this._showPopup && this._hasFocusClass($target)) {
delete this._showPopup;
this._showAddAppointmentPopup($target)
}
},
_pointerDownHandler: function(e) {
var $target = $(e.target);
if (!$target.hasClass(DATE_TABLE_CELL_CLASS) && !$target.hasClass(ALL_DAY_TABLE_CELL_CLASS)) {
this._isCellClick = false;
return
}
this._isCellClick = true;
if ($target.hasClass(DATE_TABLE_FOCUSED_CELL_CLASS)) {
this._showPopup = true
} else {
this._setFocusedCell($target)
}
},
_showAddAppointmentPopup: function($cell) {
var firstCellData = this.getCellData($cell.first());
var lastCellData = this.getCellData($cell.last());
var args = {
startDate: this.invoke("convertDateByTimezoneBack", firstCellData.startDate) || firstCellData.startDate,
endDate: this.invoke("convertDateByTimezoneBack", lastCellData.endDate) || lastCellData.endDate
};
if (isDefined(lastCellData.allDay)) {
args.allDay = lastCellData.allDay
}
extend(args, lastCellData.groups);
this.notifyObserver("showAddAppointmentPopup", args)
},
_attachContextMenuEvent: function() {
this._createContextMenuAction();
var cellSelector = "." + DATE_TABLE_CELL_CLASS + ",." + ALL_DAY_TABLE_CELL_CLASS;
var $element = this.$element();
var eventName = eventUtils.addNamespace(contextMenuEvent.name, this.NAME);
eventsEngine.off($element, eventName, cellSelector);
eventsEngine.on($element, eventName, cellSelector, this._contextMenuHandler.bind(this))
},
_contextMenuHandler: function(e) {
var $cell = $(e.target);
this._contextMenuAction({
event: e,
cellElement: getPublicElement($cell),
cellData: this.getCellData($cell)
});
this._contextMenuHandled = true
},
_createContextMenuAction: function() {
this._contextMenuAction = this._createActionByOption("onCellContextMenu")
},
_getGroupHeaderContainer: function() {
if (this._isVerticalGroupedWorkSpace()) {
return this._$groupTable
}
return this._$thead
},
_getDateHeaderContainer: function() {
return this._$thead
},
_renderGroupHeader: function() {
var $container = this._getGroupHeaderContainer();
var groupCount = this._getGroupCount();
var cellTemplates = [];
if (groupCount) {
var groupRows = this._makeGroupRows(this.option("groups"), this.option("groupByDate"));
this._attachGroupCountAttr(groupCount, groupRows);
$container.append(groupRows.elements);
cellTemplates = groupRows.cellTemplates
} else {
this._detachGroupCountAttr()
}
return cellTemplates
},
_applyCellTemplates: function(templates) {
templates.forEach(function(template) {
template()
})
},
_detachGroupCountAttr: function() {
var groupedAttr = this._groupedStrategy.getGroupCountAttr();
this.$element().removeAttr(groupedAttr.attr)
},
_attachGroupCountAttr: function(groupRowCount, groupRows) {
var groupedAttr = this._groupedStrategy.getGroupCountAttr(groupRowCount, groupRows);
this.$element().attr(groupedAttr.attr, groupedAttr.count)
},
headerPanelOffsetRecalculate: function() {
if (!this.option("resourceCellTemplate") && !this.option("dateCellTemplate")) {
return
}
var headerPanelHeight = this.getHeaderPanelHeight();
var headerHeight = this.invoke("getHeaderHeight");
var allDayPanelHeight = this.supportAllDayRow() && this.option("showAllDayPanel") ? this._groupedStrategy.getAllDayTableHeight() : 0;
headerPanelHeight && this._headerScrollable && this._headerScrollable.$element().height(headerPanelHeight + allDayPanelHeight);
headerPanelHeight && this._dateTableScrollable.$element().css({
paddingBottom: allDayPanelHeight + headerPanelHeight + "px",
marginBottom: -1 * (parseInt(headerPanelHeight, 10) + allDayPanelHeight) + "px"
});
headerPanelHeight && this._sidebarScrollable && this._sidebarScrollable.$element().css({
paddingBottom: allDayPanelHeight + headerPanelHeight + "px",
marginBottom: -1 * (parseInt(headerPanelHeight, 10) + allDayPanelHeight) + "px"
});
this._$allDayTitle && this._$allDayTitle.css("top", headerHeight + headerPanelHeight + "px")
},
_makeGroupRows: function(groups, groupByDate) {
var tableCreatorStrategy = this._isVerticalGroupedWorkSpace() ? tableCreator.VERTICAL : tableCreator.HORIZONTAL;
return tableCreator.makeGroupedTable(tableCreatorStrategy, groups, {
groupHeaderRowClass: this._getGroupRowClass(),
groupRowClass: this._getGroupRowClass(),
groupHeaderClass: this._getGroupHeaderClass.bind(this),
groupHeaderContentClass: this._getGroupHeaderContentClass()
}, this._getCellCount() || 1, this.option("resourceCellTemplate"), this._getGroupCount(), groupByDate)
},
_getDateHeaderTemplate: function() {
return this.option("dateCellTemplate")
},
_renderDateHeader: function() {
var $container = this._getDateHeaderContainer();
var $headerRow = $("<tr>").addClass(HEADER_ROW_CLASS);
var count = this._getCellCount();
var cellTemplate = this._getDateHeaderTemplate();
var repeatCount = this._calculateHeaderCellRepeatCount();
var templateCallbacks = [];
var groupByDate = this.isGroupedByDate();
var colspan = groupByDate ? this._getGroupCount() : 1;
var i;
var j;
if (!groupByDate) {
for (j = 0; j < repeatCount; j++) {
for (i = 0; i < count; i++) {
this._renderDateHeaderTemplate($headerRow, i, j * repeatCount + i, cellTemplate, templateCallbacks)
}
}
$container.append($headerRow)
} else {
for (i = 0; i < count; i++) {
var $cell = this._renderDateHeaderTemplate($headerRow, i, i * repeatCount, cellTemplate, templateCallbacks);
$cell.attr("colSpan", colspan)
}
$container.prepend($headerRow)
}
this._applyCellTemplates(templateCallbacks);
return $headerRow
},
_renderDateHeaderTemplate: function($container, i, calculatedIndex, cellTemplate, templateCallbacks) {
var text = this._getHeaderText(i);
var $cell = $("<th>").addClass(this._getHeaderPanelCellClass(i)).attr("title", text);
if (cellTemplate && cellTemplate.render) {
templateCallbacks.push(cellTemplate.render.bind(cellTemplate, {
model: {
text: text,
date: this._getDateByIndex(i)
},
index: calculatedIndex,
container: getPublicElement($cell)
}))
} else {
$cell.text(text)
}
$container.append($cell);
return $cell
},
_getHeaderPanelCellClass: function(i) {
var cellClass = HEADER_PANEL_CELL_CLASS + " " + HORIZONTAL_SIZES_CLASS;
return this._groupedStrategy.addAdditionalGroupCellClasses(cellClass, i + 1)
},
_calculateHeaderCellRepeatCount: function() {
return this._groupedStrategy.calculateHeaderCellRepeatCount()
},
_renderAllDayPanel: function(index) {
var cellCount = this._getCellCount();
if (!this._isVerticalGroupedWorkSpace()) {
cellCount *= this._getGroupCount() || 1
}
var cellTemplates = this._renderTableBody({
container: this._allDayPanels.length ? getPublicElement(this._allDayTables[index]) : getPublicElement(this._$allDayTable),
rowCount: 1,
cellCount: cellCount,
cellClass: this._getAllDayPanelCellClass.bind(this),
rowClass: ALL_DAY_TABLE_ROW_CLASS,
cellTemplate: this.option("dataCellTemplate"),
getCellData: this._getAllDayCellData.bind(this),
groupIndex: index
}, true);
this._toggleAllDayVisibility();
this._applyCellTemplates(cellTemplates)
},
_getAllDayPanelCellClass: function(i, j) {
var cellClass = ALL_DAY_TABLE_CELL_CLASS + " " + HORIZONTAL_SIZES_CLASS;
return this._groupedStrategy.addAdditionalGroupCellClasses(cellClass, j + 1)
},
_getAllDayCellData: function(cell, rowIndex, cellIndex, groupIndex) {
var startDate = this._getDateByCellIndexes(rowIndex, cellIndex);
startDate = dateUtils.trimTime(startDate);
var data = {
startDate: startDate,
endDate: new Date(startDate.getTime() + DAY_MS),
allDay: true
};
var groups = this._getCellGroups(groupIndex || this._getGroupIndex(rowIndex, cellIndex));
if (groups.length) {
data.groups = {}
}
for (var i = 0; i < groups.length; i++) {
data.groups[groups[i].name] = groups[i].id
}
return {
key: CELL_DATA,
value: data
}
},
_toggleAllDayVisibility: function() {
var showAllDayPanel = this.option("showAllDayPanel");
this._$allDayPanel.toggle(showAllDayPanel);
this._$allDayTitle && this._$allDayTitle.toggleClass(ALL_DAY_TITLE_HIDDEN_CLASS, !showAllDayPanel);
this.$element().toggleClass(WORKSPACE_WITH_ALL_DAY_CLASS, showAllDayPanel);
this._changeAllDayVisibility();
this._updateScrollable()
},
_changeAllDayVisibility: function() {
this.$element().toggleClass(WORKSPACE_WITH_COLLAPSED_ALL_DAY_CLASS, !this.option("allDayExpanded") && this.option("showAllDayPanel"))
},
_updateScrollable: function() {
this._dateTableScrollable.update();
this._headerScrollable && this._headerScrollable.update();
this._sidebarScrollable && this._sidebarScrollable.update()
},
_renderTimePanel: function() {
var _this5 = this;
var repeatCount = this._groupedStrategy.calculateTimeCellRepeatCount();
var startViewDate = this._getDateWithSkippedDST();
var _getTimeText = function(i) {
var index = i % _this5._getRowCount();
if (index % 2 === 0) {
return dateLocalization.format(_this5._getTimeCellDateCore(startViewDate, i), "shorttime")
}
return ""
};
this._renderTableBody({
container: getPublicElement(this._$timePanel),
rowCount: this._getTimePanelRowCount() * repeatCount,
cellCount: 1,
cellClass: this._getTimeCellClass.bind(this),
rowClass: TIME_PANEL_ROW_CLASS,
cellTemplate: this.option("timeCellTemplate"),
getCellText: _getTimeText.bind(this),
getCellDate: this._getTimeCellDate.bind(this),
groupCount: this._getGroupCount(),
allDayElements: this._insertAllDayRowsIntoDateTable() ? this._allDayTitles : void 0
})
},
_getDateWithSkippedDST: function() {
var result = new Date(this.getStartViewDate());
if (timeZoneUtils.isTimezoneChangeInDate(result)) {
result = new Date(result.setDate(result.getDate() + 1))
}
return result
},
_getTimePanelRowCount: function() {
return this._getCellCountInDay()
},
_getCellCountInDay: function(skipRound) {
var result = this._calculateDayDuration() / this.option("hoursInterval");
return skipRound ? result : Math.ceil(result)
},
_calculateDayDuration: function() {
return this.option("endDayHour") - this.option("startDayHour")
},
_getTimeCellClass: function(i) {
var cellClass = TIME_PANEL_CELL_CLASS + " " + VERTICAL_SIZES_CLASS;
return this._groupedStrategy.addAdditionalGroupCellClasses(cellClass, i, i)
},
_getTimeCellDateAdjustedDST: function(i) {
var startViewDate = new Date(this.getStartViewDate());
if (timeZoneUtils.isTimezoneChangeInDate(startViewDate)) {
startViewDate = new Date(startViewDate.setDate(startViewDate.getDate() + 1))
}
return this._getTimeCellDateCore(startViewDate, i)
},
_getTimeCellDate: function(i) {
return this._getTimeCellDateCore(this.getStartViewDate(), i)
},
_getTimeCellDateCore: function(startViewDate, i) {
var result = new Date(startViewDate);
var timeCellDuration = Math.round(this.getCellDuration());
var cellCountInDay = this._getCellCountInDay(true);
result.setMilliseconds(result.getMilliseconds() + timeCellDuration * (i % cellCountInDay));
return result
},
_renderDateTable: function() {
var groupCount = this._getGroupCount();
this._renderTableBody({
container: getPublicElement(this._$dateTable),
rowCount: this._getTotalRowCount(groupCount),
cellCount: this._getTotalCellCount(groupCount),
cellClass: this._getDateTableCellClass.bind(this),
rowClass: this._getDateTableRowClass(),
cellTemplate: this.option("dataCellTemplate"),
getCellData: this._getCellData.bind(this),
allDayElements: this._insertAllDayRowsIntoDateTable() ? this._allDayPanels : void 0,
groupCount: groupCount,
groupByDate: this.option("groupByDate")
})
},
_insertAllDayRowsIntoDateTable: function() {
return this._groupedStrategy.insertAllDayRowsIntoDateTable()
},
_getTotalCellCount: function(groupCount) {
return this._groupedStrategy.getTotalCellCount(groupCount)
},
_getTotalRowCount: function() {
return this._groupedStrategy.getTotalRowCount()
},
_getCellData: function(cell, rowIndex, cellIndex) {
var data = this._prepareCellData(rowIndex, cellIndex, cell);
return {
key: CELL_DATA,
value: data
}
},
_prepareCellData: function(rowIndex, cellIndex) {
var startDate = this._getDateByCellIndexes(rowIndex, cellIndex);
var endDate = this.calculateEndDate(startDate);
var data = {
startDate: startDate,
endDate: endDate,
allDay: this._getTableAllDay()
};
var groups = this._getCellGroups(this._getGroupIndex(rowIndex, cellIndex));
if (groups.length) {
data.groups = {}
}
for (var i = 0; i < groups.length; i++) {
data.groups[groups[i].name] = groups[i].id
}
return data
},
_getGroupIndex: function(rowIndex, cellIndex) {
return this._groupedStrategy.getGroupIndex(rowIndex, cellIndex)
},
_getTableAllDay: function() {
return false
},
calculateEndDate: function(startDate) {
var result = new Date(startDate);
result.setMilliseconds(result.getMilliseconds() + Math.round(this._getInterval()));
return result
},
_getGroupCount: function() {
var groups = this.option("groups");
var result = 0;
for (var i = 0, len = groups.length; i < len; i++) {
if (!i) {
result = groups[i].items.length
} else {
result *= groups[i].items.length
}
}
return result
},
_getPathToLeaf: function(leafIndex) {
var tree = this.invoke("createResourcesTree", this.option("groups"));
function findLeafByIndex(data, index) {
for (var i = 0; i < data.length; i++) {
if (data[i].leafIndex === index) {
return data[i]
} else {
var _leaf = findLeafByIndex(data[i].children, index);
if (_leaf) {
return _leaf
}
}
}
}
function makeBranch(leaf, result) {
result = result || [];
result.push(leaf.value);
if (leaf.parent) {
makeBranch(leaf.parent, result)
}
return result
}
var leaf = findLeafByIndex(tree, leafIndex);
return makeBranch(leaf).reverse()
},
_getCellGroups: function(groupIndex) {
var result = [];
if (this._getGroupCount()) {
var groups = this.option("groups");
if (groupIndex < 0) {
return
}
var path = this._getPathToLeaf(groupIndex);
for (var i = 0; i < groups.length; i++) {
result.push({
name: groups[i].name,
id: path[i]
})
}
}
return result
},
_attachTablesEvents: function() {
var _this6 = this;
var that = this;
var isPointerDown = false;
var cellHeight;
var cellWidth;
var $element = this.$element();
eventsEngine.off($element, SCHEDULER_CELL_DXDRAGENTER_EVENT_NAME);
eventsEngine.off($element, SCHEDULER_CELL_DXDRAGLEAVE_EVENT_NAME);
eventsEngine.off($element, SCHEDULER_CELL_DXDROP_EVENT_NAME);
eventsEngine.off($element, SCHEDULER_CELL_DXPOINTERMOVE_EVENT_NAME);
eventsEngine.off($element, SCHEDULER_CELL_DXPOINTERDOWN_EVENT_NAME);
eventsEngine.on($element, SCHEDULER_CELL_DXDRAGENTER_EVENT_NAME, SCHEDULER_DRAG_AND_DROP_SELECTOR, {
itemSizeFunc: function($element) {
if (!cellHeight) {
cellHeight = getBoundingRect($element.get(0)).height
}
if (!cellWidth) {
cellWidth = getBoundingRect($element.get(0)).width
}
return {
width: cellWidth,
height: cellHeight
}
},
checkDropTarget: function(target, event) {
return !_this6._isOutsideScrollable(target, event)
}
}, function(e) {
if (that._$currentTableTarget) {
that.removeDroppableCellClass(that._$currentTableTarget)
}
that._$currentTableTarget = $(e.target);
that._$currentTableTarget.addClass(DATE_TABLE_DROPPABLE_CELL_CLASS)
});
eventsEngine.on($element, SCHEDULER_CELL_DXDRAGLEAVE_EVENT_NAME, function(e) {
if (!$element.find($(e.draggingElement)).length) {
that.removeDroppableCellClass()
}
});
eventsEngine.on($element, SCHEDULER_CELL_DXDROP_EVENT_NAME, SCHEDULER_DRAG_AND_DROP_SELECTOR, function(e) {
that.removeDroppableCellClass($(e.target));
cellHeight = 0;
cellWidth = 0
});
eventsEngine.on($element, SCHEDULER_CELL_DXPOINTERDOWN_EVENT_NAME, SCHEDULER_DRAG_AND_DROP_SELECTOR, function(e) {
if (eventUtils.isMouseEvent(e) && 1 === e.which) {
isPointerDown = true;
that.$element().addClass(WORKSPACE_WITH_MOUSE_SELECTION_CLASS);
eventsEngine.off(domAdapter.getDocument(), SCHEDULER_CELL_DXPOINTERUP_EVENT_NAME);
eventsEngine.on(domAdapter.getDocument(), SCHEDULER_CELL_DXPOINTERUP_EVENT_NAME, function() {
isPointerDown = false;
that.$element().removeClass(WORKSPACE_WITH_MOUSE_SELECTION_CLASS)
})
}
});
eventsEngine.on($element, SCHEDULER_CELL_DXPOINTERMOVE_EVENT_NAME, SCHEDULER_DRAG_AND_DROP_SELECTOR, function(e) {
if (isPointerDown && that._dateTableScrollable && !that._dateTableScrollable.option("scrollByContent")) {
e.preventDefault();
e.stopPropagation();
that._moveToCell($(e.target), true)
}
})
},
_getDateTables: function() {
return this._$dateTable.add(this._$allDayTable)
},
_getDateTable: function() {
return this._$dateTable
},
_getAllDayTable: function() {
return this._$allDayTable
},
_getInterval: function() {
if (void 0 === this._interval) {
this._interval = this.option("hoursInterval") * HOUR_MS
}
return this._interval
},
_getHeaderText: function(headerIndex) {
return dateLocalization.format(this._getDateByIndex(headerIndex), this._getFormat())
},
_getDateByIndex: abstract,
_getFormat: abstract,
_calculateCellIndex: function(rowIndex, cellIndex) {
return this._groupedStrategy.calculateCellIndex(rowIndex, cellIndex)
},
_renderTableBody: function(options, delayCellTemplateRendering) {
var result = [];
if (!delayCellTemplateRendering) {
this._applyCellTemplates(tableCreator.makeTable(options))
} else {
result = tableCreator.makeTable(options)
}
return result
},
_removeAllDayElements: function() {
this._$allDayTable && this._$allDayTable.remove();
this._$allDayTitle && this._$allDayTitle.remove()
},
_cleanView: function() {
this._cleanCellDataCache();
this._cleanAllowedPositions();
this._$thead.empty();
this._$dateTable.empty();
this._shader && this._shader.clean();
this._$timePanel.empty();
this._$allDayTable && this._$allDayTable.empty();
this._$groupTable.empty();
delete this._hiddenInterval;
delete this._interval
},
_clean: function() {
eventsEngine.off(domAdapter.getDocument(), SCHEDULER_CELL_DXPOINTERUP_EVENT_NAME);
this.callBase()
},
getWorkArea: function() {
return this._dateTableScrollable.$content()
},
getScrollable: function() {
return this._dateTableScrollable
},
getScrollableScrollTop: function() {
return this._dateTableScrollable.scrollTop()
},
getGroupedScrollableScrollTop: function(allDay) {
return this._groupedStrategy.getScrollableScrollTop(allDay)
},
getScrollableScrollLeft: function() {
return this._dateTableScrollable.scrollLeft()
},
getScrollableOuterWidth: function() {
return this._dateTableScrollable.scrollWidth()
},
getScrollableContainer: function() {
return this._dateTableScrollable._container()
},
getHeaderPanelHeight: function() {
return this._$headerPanel && this._$headerPanel.outerHeight(true)
},
getTimePanelWidth: function() {
return this._$timePanel && getBoundingRect(this._$timePanel.get(0)).width
},
getGroupTableWidth: function() {
return this._$groupTable ? this._$groupTable.outerWidth() : 0
},
getWorkSpaceLeftOffset: function() {
return this._groupedStrategy.getLeftOffset()
},
getGroupedStrategy: function() {
return this._groupedStrategy
},
_getCellCoordinatesByIndex: function(index) {
var cellIndex = Math.floor(index / this._getRowCount());
var rowIndex = index - this._getRowCount() * cellIndex;
return {
cellIndex: cellIndex,
rowIndex: rowIndex
}
},
_getDateByCellIndexes: function(rowIndex, cellIndex, patchedIndexes) {
cellIndex = !patchedIndexes ? this._patchCellIndex(cellIndex) : cellIndex;
var firstViewDate = this.getStartViewDate();
var currentDate = new Date(firstViewDate.getTime() + this._getMillisecondsOffset(rowIndex, cellIndex) + this._getOffsetByCount(cellIndex));
currentDate.setTime(currentDate.getTime() + dateUtils.getTimezonesDifference(firstViewDate, currentDate));
return currentDate
},
_patchCellIndex: function(cellIndex) {
if (this.isGroupedByDate()) {
cellIndex = Math.floor(cellIndex / this._getGroupCount())
}
return cellIndex
},
_getOffsetByCount: function() {
return 0
},
_getMillisecondsOffset: function(rowIndex, cellIndex) {
return this._getInterval() * this._calculateCellIndex(rowIndex, cellIndex) + this._calculateHiddenInterval(rowIndex, cellIndex)
},
_calculateHiddenInterval: function(rowIndex, cellIndex) {
var dayCount = cellIndex % this._getCellCount();
return dayCount * this._getHiddenInterval()
},
_getHiddenInterval: function() {
if (void 0 === this._hiddenInterval) {
this._hiddenInterval = DAY_MS - this.getVisibleDayDuration()
}
return this._hiddenInterval
},
_getIntervalBetween: function(currentDate, allDay) {
var firstViewDate = this.getStartViewDate();
var startDayTime = this.option("startDayHour") * HOUR_MS;
var timeZoneOffset = dateUtils.getTimezonesDifference(firstViewDate, currentDate);
var fullInterval = currentDate.getTime() - firstViewDate.getTime() - timeZoneOffset;
var days = this._getDaysOfInterval(fullInterval, startDayTime);
var weekendsCount = this._getWeekendsCount(days);
var result = (days - weekendsCount) * DAY_MS;
if (!allDay) {
result = fullInterval - days * this._getHiddenInterval() - weekendsCount * this.getVisibleDayDuration()
}
return result
},
_getWeekendsCount: function() {
return 0
},
_getDaysOfInterval: function(fullInterval, startDayTime) {
return Math.floor((fullInterval + startDayTime) / DAY_MS)
},
_getGroupIndexes: function(appointmentResources) {
var result = [];
if (appointmentResources && this.option("groups").length) {
var tree = this.invoke("createResourcesTree", this.option("groups"));
result = this.invoke("getResourceTreeLeaves", tree, appointmentResources)
}
return result
},
_updateIndex: function(index) {
return index * this._getRowCount()
},
_getDroppableCell: function() {
return this._getDateTables().find("." + DATE_TABLE_DROPPABLE_CELL_CLASS)
},
_getWorkSpaceWidth: function() {
if (this._needCreateCrossScrolling()) {
return getBoundingRect(this._$dateTable.get(0)).width
}
return getBoundingRect(this.$element().get(0)).width - this.getTimePanelWidth()
},
_getCellPositionByIndex: function(index, groupIndex, inAllDayRow) {
var cellCoordinates = this._getCellCoordinatesByIndex(index);
var $cell = this._getCellByCoordinates(cellCoordinates, groupIndex, inAllDayRow);
var result = this._getCellPosition($cell);
this.setCellDataCache(cellCoordinates, groupIndex, $cell);
if (result) {
result.rowIndex = cellCoordinates.rowIndex;
result.cellIndex = cellCoordinates.cellIndex
}
return result
},
_getCellPosition: function($cell) {
var position = $cell.position();
if (this.option("rtlEnabled")) {
position.left += getBoundingRect($cell.get(0)).width
}
return position
},
_getCellByCoordinates: function(cellCoordinates, groupIndex, inAllDayRow) {
var indexes = this._groupedStrategy.prepareCellIndexes(cellCoordinates, groupIndex, inAllDayRow);
return this._$dateTable.find("tr").eq(indexes.rowIndex).find("td").eq(indexes.cellIndex)
},
_getCells: function(allDay, direction) {
var cellClass = allDay ? ALL_DAY_TABLE_CELL_CLASS : DATE_TABLE_CELL_CLASS;
if ("vertical" === direction) {
var result = [];
for (var i = 1;; i++) {
var cells = this.$element().find("tr .".concat(cellClass, ":nth-child(").concat(i, ")"));
if (!cells.length) {
break
}
result = result.concat(cells.toArray())
}
return $(result)
} else {
return this.$element().find("." + cellClass)
}
},
_setHorizontalGroupHeaderCellsHeight: function() {
var height = getBoundingRect(this._$dateTable.get(0)).height;
this._$groupTable.outerHeight(height)
},
_getDateTableBorder: function() {
return DATE_TABLE_CELL_BORDER
},
_getDateTableBorderOffset: function() {
return 2 * this._getDateTableBorder()
},
_getGroupHeaderCellsContent: function() {
return this.$element().find("." + GROUP_HEADER_CONTENT_CLASS)
},
_getGroupHeaderCells: function() {
return this.$element().find("." + GROUP_HEADER_CLASS)
},
_getScrollCoordinates: function(hours, minutes, date) {
var currentDate = date || new Date(this.option("currentDate"));
var startDayHour = this.option("startDayHour");
var endDayHour = this.option("endDayHour");
if (hours < startDayHour) {
hours = startDayHour
}
if (hours >= endDayHour) {
hours = endDayHour - 1
}
currentDate.setHours(hours, minutes, 0, 0);
return this.getCoordinatesByDate(currentDate)
},
_isOutsideScrollable: function(target, event) {
var $dateTableScrollableElement = this._dateTableScrollable.$element();
var scrollableSize = getBoundingRect($dateTableScrollableElement.get(0));
var window = windowUtils.getWindow();
var isTargetInAllDayPanel = !$(target).closest($dateTableScrollableElement).length;
var isOutsideHorizontalScrollable = event.pageX < scrollableSize.left || event.pageX > scrollableSize.left + scrollableSize.width + (window.scrollX || 0);
var isOutsideVerticalScrollable = event.pageY < scrollableSize.top || event.pageY > scrollableSize.top + scrollableSize.height + (window.scrollY || 0);
if (isTargetInAllDayPanel && !isOutsideHorizontalScrollable) {
return false
}
return isOutsideVerticalScrollable || isOutsideHorizontalScrollable
},
setCellDataCache: function(cellCoordinates, groupIndex, $cell) {
var cache = this.getCellDataCache();
var data = this.getCellData($cell);
var key = JSON.stringify({
rowIndex: cellCoordinates.rowIndex,
cellIndex: cellCoordinates.cellIndex,
groupIndex: groupIndex
});
cache[key] = data
},
setCellDataCacheAlias: function(appointment, geometry) {
var key = JSON.stringify({
rowIndex: appointment.rowIndex,
cellIndex: appointment.cellIndex,
groupIndex: appointment.groupIndex
});
var aliasKey = JSON.stringify({
top: geometry.top,
left: geometry.left
});
var cache = this.getCellDataCache();
if (cache[key]) {
cache[aliasKey] = cache[key]
}
},
getCellDataCache: function(key) {
if (!this._cache) {
this._cache = {}
}
return key ? this._cache[key] : this._cache
},
_cleanCellDataCache: function() {
delete this._cache
},
_cleanAllowedPositions: function() {
delete this._maxAllowedVerticalPosition;
delete this._maxAllowedPosition
},
supportAllDayRow: function() {
return true
},
keepOriginalHours: function() {
return false
},
getFocusedCellData: function() {
var $focusedCells = this._getAllFocusedCells();
var result = [];
if ($focusedCells.length > 1) {
result = this._getMultipleCellsData($focusedCells)
} else {
var data = this.getCellData($focusedCells);
data && result.push(data)
}
return result
},
_getMultipleCellsData: function($cells) {
var data = [];
for (var i = 0; i < $cells.length; i++) {
data.push(dataUtils.data($cells[i], CELL_DATA))
}
return data
},
getCellData: function($cell) {
var data = $cell[0] ? dataUtils.data($cell[0], CELL_DATA) : void 0;
return extend(true, {}, data)
},
_getHorizontalMax: function(groupIndex) {
groupIndex = this.isGroupedByDate() ? this._getGroupCount() - 1 : groupIndex;
return this._groupedStrategy.getHorizontalMax(groupIndex)
},
getCoordinatesByDate: function(date, groupIndex, inAllDayRow) {
groupIndex = groupIndex || 0;
var index = this.getCellIndexByDate(date, inAllDayRow);
var position = this._getCellPositionByIndex(index, groupIndex, inAllDayRow);
var shift = this.getPositionShift(inAllDayRow ? 0 : this.getTimeShift(date), inAllDayRow);
var horizontalHMax = this._getHorizontalMax(groupIndex, date);
if (!position) {
throw errors.Error("E1039")
}
var coordinates = {
cellPosition: position.left + shift.cellPosition,
top: position.top + shift.top,
left: position.left + shift.left,
rowIndex: position.rowIndex,
cellIndex: position.cellIndex,
hMax: horizontalHMax,
vMax: this.getVerticalMax(groupIndex),
groupIndex: groupIndex
};
return coordinates
},
getVerticalMax: function(groupIndex) {
return this._groupedStrategy.getVerticalMax(groupIndex)
},
_getOffsetByAllDayPanel: function(groupIndex) {
return this._groupedStrategy._getOffsetByAllDayPanel(groupIndex)
},
_getGroupTop: function(groupIndex) {
return this._groupedStrategy._getGroupTop(groupIndex)
},
isGroupedByDate: function() {
return this.option("groupByDate") && this._isHorizontalGroupedWorkSpace() && this._getGroupCount() > 0
},
getCellIndexByDate: function(date, inAllDayRow) {
var timeInterval = inAllDayRow ? 864e5 : this._getInterval();
var dateTimeStamp = this._getIntervalBetween(date, inAllDayRow);
var index = Math.floor(dateTimeStamp / timeInterval);
if (inAllDayRow) {
index = this._updateIndex(index)
}
if (index < 0) {
index = 0
}
return index
},
getPositionShift: function(timeShift, isAllDay) {
return {
top: timeShift * this.getCellHeight(),
left: 0,
cellPosition: 0
}
},
getTimeShift: function(date) {
var currentDayStart = new Date(date);
var cellDuration = this.getCellDuration();
var currentDayEndHour = new Date(new Date(date).setHours(this.option("endDayHour"), 0, 0));
if (date.getTime() <= currentDayEndHour.getTime()) {
currentDayStart.setHours(this.option("startDayHour"), 0, 0, 0)
}
var currentDateTime = date.getTime();
var currentDayStartTime = currentDayStart.getTime();
var minTime = this._firstViewDate.getTime();
return currentDateTime > minTime ? (currentDateTime - currentDayStartTime) % cellDuration / cellDuration : 0
},
_isSkippedData: function() {
return false
},
getCoordinatesByDateInGroup: function(date, appointmentResources, inAllDayRow) {
var indexes = this._getGroupIndexes(appointmentResources);
var result = [];
if (this._isSkippedData(date)) {
return result
}
if (indexes.length) {
for (var i = 0; i < indexes.length; i++) {
result.push(this.getCoordinatesByDate(date, indexes[i], inAllDayRow))
}
} else {
result.push(this.getCoordinatesByDate(date, 0, inAllDayRow))
}
return result
},
getDroppableCellIndex: function() {
var $droppableCell = this._getDroppableCell();
var $row = $droppableCell.parent();
var rowIndex = $row.index();
return rowIndex * $row.find("td").length + $droppableCell.index()
},
getDataByDroppableCell: function() {
var cellData = this.getCellData(this._getDroppableCell());
var allDay = cellData.allDay;
var startDate = cellData.startDate;
var endDate = startDate && this.invoke("calculateAppointmentEndDate", allDay, startDate);
return {
startDate: startDate,
endDate: endDate,
allDay: allDay,
groups: cellData.groups
}
},
getDateRange: function() {
return [this.getStartViewDate(), this.getEndViewDateByEndDayHour()]
},
getCellWidth: function() {
var cell = this._getCells().first().get(0);
return cell && getBoundingRect(cell).width
},
getCellMinWidth: function() {
return DATE_TABLE_MIN_CELL_WIDTH
},
getRoundedCellWidth: function(groupIndex, startIndex, cellCount) {
if (groupIndex < 0) {
return 0
}
var $row = this.$element().find("." + this._getDateTableRowClass()).eq(0);
var width = 0;
var $cells = $row.find("." + DATE_TABLE_CELL_CLASS);
var totalCellCount = this._getCellCount() * groupIndex;
cellCount = cellCount || this._getCellCount();
if (!typeUtils.isDefined(startIndex)) {
startIndex = totalCellCount
}
for (var i = startIndex; i < totalCellCount + cellCount; i++) {
width += getBoundingRect($($cells).eq(i).get(0)).width
}
return width / (totalCellCount + cellCount - startIndex)
},
getCellHeight: function() {
var cell = this._getCells().first().get(0);
return cell && getBoundingRect(cell).height
},
getAllDayHeight: function() {
var cell = this._getCells(true).first().get(0);
return this.option("showAllDayPanel") ? cell && getBoundingRect(cell).height || 0 : 0
},
getAllDayOffset: function() {
return this._groupedStrategy.getAllDayOffset()
},
getMaxAllowedPosition: function() {
if (!this._maxAllowedPosition) {
var isRtl = this.option("rtlEnabled");
this._maxAllowedPosition = [];
this._$dateTable.find("tr").first().find("td:nth-child(" + this._getCellCount() + "n)").each(function(_, cell) {
var maxPosition = $(cell).position().left;
if (!isRtl) {
maxPosition += getBoundingRect(cell).width
}
this._maxAllowedPosition.push(Math.round(maxPosition))
}.bind(this))
}
return this._maxAllowedPosition
},
getMaxAllowedVerticalPosition: function() {
if (!this._maxAllowedVerticalPosition) {
var that = this;
this._maxAllowedVerticalPosition = [];
var rows = this._getRowCount();
this._$dateTable.find("tr:nth-child(" + rows + "n)").each(function(_, row) {
var maxPosition = $(row).position().top + getBoundingRect(row).height;
that._maxAllowedVerticalPosition.push(Math.round(maxPosition))
})
}
return this._maxAllowedVerticalPosition
},
getFixedContainer: function() {
return this._$fixedContainer
},
getAllDayContainer: function() {
return this._$allDayContainer
},
getCellIndexByCoordinates: function(coordinates, allDay) {
var cellCount = this._getTotalCellCount(this._getGroupCount());
var cellWidth = Math.floor(this._getWorkSpaceWidth() / cellCount);
var cellHeight = allDay ? this.getAllDayHeight() : this.getCellHeight();
var leftOffset = this._isRTL() || this.option("crossScrollingEnabled") ? 0 : this.getWorkSpaceLeftOffset();
var topIndex = Math.floor(Math.floor(coordinates.top) / Math.floor(cellHeight));
var leftIndex = Math.floor((coordinates.left + 5 - leftOffset) / cellWidth);
if (this._isRTL()) {
leftIndex = cellCount - leftIndex - 1
}
return cellCount * topIndex + leftIndex
},
getStartViewDate: function() {
return this._firstViewDate
},
getEndViewDate: function() {
var dateOfLastViewCell = this.getDateOfLastViewCell();
var endDateOfLastViewCell = this.calculateEndViewDate(dateOfLastViewCell);
return this._adjustEndViewDateByDaylightDiff(dateOfLastViewCell, endDateOfLastViewCell)
},
getEndViewDateByEndDayHour: function() {
var dateOfLastViewCell = this.getDateOfLastViewCell();
var endTime = dateUtils.dateTimeFromDecimal(this.option("endDayHour"));
var endDateOfLastViewCell = new Date(dateOfLastViewCell.setHours(endTime.hours, endTime.minutes));
return this._adjustEndViewDateByDaylightDiff(dateOfLastViewCell, endDateOfLastViewCell)
},
calculateEndViewDate: function(dateOfLastViewCell) {
return new Date(dateOfLastViewCell.getTime() + this.getCellDuration())
},
_adjustEndViewDateByDaylightDiff: function(startDate, endDate) {
var daylightDiff = timeZoneUtils.getDaylightOffsetInMs(startDate, endDate);
var endDateOfLastViewCell = new Date(endDate.getTime() - daylightDiff);
return new Date(endDateOfLastViewCell.getTime() - toMs("minute"))
},
getDateOfLastViewCell: function() {
var rowIndex = this._getRowCount() - 1;
var cellIndex = this._getCellCount();
if (this.isGroupedByDate()) {
cellIndex = cellIndex * this._getGroupCount() - 1
} else {
cellIndex -= 1
}
return this._getDateByCellIndexes(rowIndex, cellIndex, true)
},
getCellDuration: function() {
return 36e5 * this.option("hoursInterval")
},
getIntervalDuration: function(allDay) {
return allDay ? toMs("day") : this.getCellDuration()
},
getVisibleDayDuration: function() {
return this.option("hoursInterval") * this._getCellCountInDay() * HOUR_MS
},
getGroupBounds: function(coordinates) {
var cellCount = this._getCellCount();
var $cells = this._getCells();
var cellWidth = this.getCellWidth();
var result = this._groupedStrategy.getGroupBoundsOffset(cellCount, $cells, cellWidth, coordinates);
if (this._isRTL()) {
var startOffset = result.left;
result.left = result.right - 2 * cellWidth;
result.right = startOffset + 2 * cellWidth
}
return result
},
needRecalculateResizableArea: function() {
return this._isVerticalGroupedWorkSpace() && 0 !== this.getScrollable().scrollTop()
},
getCellDataByCoordinates: function(coordinates, allDay) {
var key = JSON.stringify({
top: coordinates.top,
left: coordinates.left
});
var data = this.getCellDataCache(key);
if (data) {
return data
}
var $cells = this._getCells(allDay);
var cellIndex = this.getCellIndexByCoordinates(coordinates, allDay);
var $cell = $cells.eq(cellIndex);
return this.getCellData($cell)
},
getVisibleBounds: function() {
var result = {};
var $scrollable = this.getScrollable().$element();
var cellHeight = this.getCellHeight();
var scrolledCellCount = this.getScrollableScrollTop() / cellHeight;
var totalCellCount = scrolledCellCount + $scrollable.height() / cellHeight;
result.top = {
hours: Math.floor(scrolledCellCount * this.option("hoursInterval")) + this.option("startDayHour"),
minutes: scrolledCellCount % 2 ? 30 : 0
};
result.bottom = {
hours: Math.floor(totalCellCount * this.option("hoursInterval")) + this.option("startDayHour"),
minutes: Math.floor(totalCellCount) % 2 ? 30 : 0
};
return result
},
updateScrollPosition: function(date) {
date = this.invoke("convertDateByTimezone", date);
var bounds = this.getVisibleBounds();
var startDateHour = date.getHours();
var startDateMinutes = date.getMinutes();
if (this.needUpdateScrollPosition(startDateHour, startDateMinutes, bounds, date)) {
this.scrollToTime(startDateHour, startDateMinutes, date)
}
},
needUpdateScrollPosition: function(hours, minutes, bounds) {
var isUpdateNeeded = false;
if (hours < bounds.top.hours || hours > bounds.bottom.hours) {
isUpdateNeeded = true
}
if (hours === bounds.top.hours && minutes < bounds.top.minutes) {
isUpdateNeeded = true
}
if (hours === bounds.bottom.hours && minutes > bounds.top.minutes) {
isUpdateNeeded = true
}
return isUpdateNeeded
},
getGroupWidth: function(groupIndex) {
var result = this._getCellCount() * this.getCellWidth();
var position = this.getMaxAllowedPosition();
var currentPosition = position[groupIndex];
if (position.length && currentPosition) {
if (this._isRTL()) {
result = currentPosition - position[groupIndex + 1]
} else {
if (0 === groupIndex) {
result = currentPosition
} else {
result = currentPosition - position[groupIndex - 1]
}
}
}
return result
},
scrollToTime: function(hours, minutes, date) {
var min = this.getStartViewDate();
var max = this.getEndViewDate();
if (date < min || date > max) {
errors.log("W1008", date);
return
}
var coordinates = this._getScrollCoordinates(hours, minutes, date);
var scrollable = this.getScrollable();
scrollable.scrollBy({
top: coordinates.top - scrollable.scrollTop(),
left: 0
})
},
getDistanceBetweenCells: function(startIndex, endIndex) {
var result = 0;
this.$element().find("." + this._getDateTableRowClass()).first().find("." + DATE_TABLE_CELL_CLASS).each(function(index) {
if (index < startIndex || index > endIndex) {
return true
}
result += getBoundingRect(this).width
});
return result
},
needApplyCollectorOffset: function() {
return false
},
initDragBehavior: function(scheduler) {
if (!this.dragBehavior && scheduler) {
this.dragBehavior = new AppointmentDragBehavior(scheduler);
this.dragBehavior.addTo(this.getWorkArea());
this.dragBehavior.addTo(this.getAllDayContainer());
this.dragBehavior.addTo(this._$allDayPanel)
}
},
_isApplyCompactAppointmentOffset: function() {
return this._supportCompactDropDownAppointments()
},
_supportCompactDropDownAppointments: function() {
return true
},
_formatWeekday: function(date) {
return formatWeekday(date)
},
_formatWeekdayAndDay: function(date) {
return formatWeekday(date) + " " + dateLocalization.format(date, "day")
},
removeDroppableCellClass: function($cellElement) {
($cellElement || this._getDroppableCell()).removeClass(DATE_TABLE_DROPPABLE_CELL_CLASS)
}
}).include(publisherMixin);
module.exports = SchedulerWorkSpace;