devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
511 lines (404 loc) • 18.1 kB
JavaScript
"use strict";
var $ = require("../../core/renderer"),
noop = require("../../core/utils/common").noop,
extend = require("../../core/utils/extend").extend,
registerComponent = require("../../core/component_registrator"),
SchedulerWorkSpace = require("./ui.scheduler.work_space.indicator"),
windowUtils = require("../../core/utils/window"),
dateUtils = require("../../core/utils/date"),
tableCreator = require("./ui.scheduler.table_creator"),
HorizontalShader = require("./ui.scheduler.current_time_shader.horizontal");
var TIMELINE_CLASS = "dx-scheduler-timeline",
GROUP_TABLE_CLASS = "dx-scheduler-group-table",
HORIZONTAL_GROUPED_WORKSPACE_CLASS = "dx-scheduler-work-space-horizontal-grouped";
var HORIZONTAL = "horizontal",
DATE_TABLE_CELL_HEIGHT = 75,
DATE_TABLE_CELL_BORDER = 1,
toMs = dateUtils.dateToMilliseconds;
var SchedulerTimeline = SchedulerWorkSpace.inherit({
_init: function _init() {
this.callBase();
this.$element().addClass(TIMELINE_CLASS);
this._$sidebarTable = $("<table>").addClass(GROUP_TABLE_CLASS);
},
_getCellFromNextRow: function _getCellFromNextRow(direction, isMultiSelection) {
if (!isMultiSelection) {
return this.callBase(direction, isMultiSelection);
}
return this._$focusedCell;
},
_getDefaultGroupStrategy: function _getDefaultGroupStrategy() {
return "vertical";
},
_toggleGroupingDirectionClass: function _toggleGroupingDirectionClass() {
this.$element().toggleClass(HORIZONTAL_GROUPED_WORKSPACE_CLASS, this._isHorizontalGroupedWorkSpace());
},
_getDefaultOptions: function _getDefaultOptions() {
return extend(this.callBase(), {
groupOrientation: "vertical"
});
},
_getRightCell: function _getRightCell() {
var $rightCell,
$focusedCell = this._$focusedCell,
rowCellCount = this._getCellCount(),
edgeCellIndex = this._isRTL() ? 0 : rowCellCount - 1,
direction = this._isRTL() ? "prev" : "next";
if ($focusedCell.index() === edgeCellIndex) {
$rightCell = $focusedCell;
} else {
$rightCell = $focusedCell[direction]();
$rightCell = this._checkForViewBounds($rightCell);
}
return $rightCell;
},
_getLeftCell: function _getLeftCell() {
var $leftCell,
$focusedCell = this._$focusedCell,
rowCellCount = this._getCellCount(),
edgeCellIndex = this._isRTL() ? rowCellCount - 1 : 0,
direction = this._isRTL() ? "next" : "prev";
if ($focusedCell.index() === edgeCellIndex) {
$leftCell = $focusedCell;
} else {
$leftCell = $focusedCell[direction]();
$leftCell = this._checkForViewBounds($leftCell);
}
return $leftCell;
},
_getRowCount: function _getRowCount() {
return 1;
},
_getCellCount: function _getCellCount() {
return this._getCellCountInDay() * this.option("intervalCount");
},
_getTotalRowCount: function _getTotalRowCount(groupCount) {
if (this._isHorizontalGroupedWorkSpace()) {
return this._getRowCount();
} else {
groupCount = groupCount || 1;
return this._getRowCount() * groupCount;
}
},
_getDateByIndex: function _getDateByIndex(index) {
var resultDate = new Date(this._firstViewDate),
dayIndex = Math.floor(index / this._getCellCountInDay());
resultDate.setTime(this._firstViewDate.getTime() + this._calculateCellIndex(0, index) * this._getInterval() + dayIndex * this._getHiddenInterval());
return resultDate;
},
_getFormat: function _getFormat() {
return "shorttime";
},
_needApplyLastGroupCellClass: function _needApplyLastGroupCellClass() {
return true;
},
_calculateHiddenInterval: function _calculateHiddenInterval(rowIndex, cellIndex) {
var dayIndex = Math.floor(cellIndex / this._getCellCountInDay());
return dayIndex * this._getHiddenInterval();
},
_getMillisecondsOffset: function _getMillisecondsOffset(rowIndex, cellIndex) {
cellIndex = this._calculateCellIndex(rowIndex, cellIndex);
return this._getInterval() * cellIndex + this._calculateHiddenInterval(rowIndex, cellIndex);
},
_createWorkSpaceElements: function _createWorkSpaceElements() {
this._createWorkSpaceScrollableElements();
},
_getWorkSpaceHeight: function _getWorkSpaceHeight() {
if (this.option("crossScrollingEnabled")) {
return this._$dateTable.get(0).getBoundingClientRect().height;
}
return this.$element().get(0).getBoundingClientRect().height;
},
_dateTableScrollableConfig: function _dateTableScrollableConfig() {
var headerScrollableOnScroll;
var config = this.callBase(),
timelineConfig = {
direction: HORIZONTAL,
onStart: function () {
if (this._headerScrollable) {
headerScrollableOnScroll = this._headerScrollable.option("onScroll");
this._headerScrollable.option("onScroll", undefined);
}
}.bind(this),
onScroll: function (e) {
this._headerScrollable && this._headerScrollable.scrollTo({
left: e.scrollOffset.left
});
}.bind(this),
onEnd: function (e) {
this._headerScrollable && this._headerScrollable.option("onScroll", headerScrollableOnScroll);
}.bind(this)
};
return this.option("crossScrollingEnabled") ? config : extend(config, timelineConfig);
},
_renderTimePanel: noop,
_renderAllDayPanel: noop,
_getTableAllDay: function _getTableAllDay() {
return false;
},
_getDateHeaderTemplate: function _getDateHeaderTemplate() {
return this.option("timeCellTemplate");
},
_toggleAllDayVisibility: noop,
_changeAllDayVisibility: noop,
supportAllDayRow: function supportAllDayRow() {
return false;
},
_isHorizontalGroupedWorkSpace: function _isHorizontalGroupedWorkSpace() {
return !!this.option("groups").length && this.option("groupOrientation") === "horizontal";
},
_getGroupHeaderContainer: function _getGroupHeaderContainer() {
if (this._isHorizontalGroupedWorkSpace()) {
return this._$thead;
}
return this._$sidebarTable;
},
_insertAllDayRowsIntoDateTable: function _insertAllDayRowsIntoDateTable() {
return false;
},
_createAllDayPanelElements: noop,
_renderView: function _renderView() {
this._setFirstViewDate();
var groupCellTemplates = this._renderGroupHeader();
this._renderDateHeader();
this._renderAllDayPanel();
this._renderTimePanel();
this._renderDateTable();
this._shader = new HorizontalShader();
this._$sidebarTable.appendTo(this._sidebarScrollable.$content());
this._setGroupHeaderCellsHeight();
this._applyCellTemplates(groupCellTemplates);
},
getIndicationWidth: function getIndicationWidth() {
var today = this._getToday(),
cellWidth = this.getCellWidth(),
date = this._getIndicationFirstViewDate(),
hiddenInterval = this._getHiddenInterval(),
timeDiff = today.getTime() - date.getTime();
var differenceInDays = Math.ceil(timeDiff / toMs("day")) - 1,
duration = timeDiff - differenceInDays * hiddenInterval,
cellCount = duration / this.getCellDuration();
return cellCount * cellWidth;
},
_renderIndicator: function _renderIndicator(height, rtlOffset, $container, groupCount) {
var $indicator,
width = this.getIndicationWidth();
if (this.option("groupOrientation") === "vertical") {
$indicator = this._createIndicator($container);
$indicator.height($container.get(0).getBoundingClientRect().height);
$indicator.css("left", rtlOffset ? rtlOffset - width : width);
} else {
for (var i = 0; i < groupCount; i++) {
var offset = this._getCellCount() * this.getCellWidth() * i;
$indicator = this._createIndicator($container);
$indicator.height($container.get(0).getBoundingClientRect().height);
$indicator.css("left", rtlOffset ? rtlOffset - width - offset : width + offset);
}
}
},
_isVerticalShader: function _isVerticalShader() {
return false;
},
_isCurrentTimeHeaderCell: function _isCurrentTimeHeaderCell(headerIndex) {
var result = false;
if (this.option("showCurrentTimeIndicator") && this._needRenderDateTimeIndicator()) {
var date = this._getDateByIndex(headerIndex);
var now = this._getToday();
date = new Date(date);
if (dateUtils.sameDate(now, date)) {
var startCellDate = new Date(date),
endCellDate = new Date(date);
endCellDate = endCellDate.setMilliseconds(date.getMilliseconds() + this.getCellDuration());
result = dateUtils.dateInRange(now, startCellDate, endCellDate);
}
}
return result;
},
_cleanView: function _cleanView() {
this.callBase();
this._$sidebarTable.empty();
},
_visibilityChanged: function _visibilityChanged(visible) {
this._setGroupHeaderCellsHeight();
this.callBase(visible);
},
_setTableSizes: function _setTableSizes() {
this.callBase();
var cellHeight = DATE_TABLE_CELL_HEIGHT,
minHeight = this._getWorkSpaceMinHeight(),
$groupCells = this._$sidebarTable.find("tr");
var height = cellHeight * $groupCells.length;
if (height < minHeight) {
height = minHeight;
}
this._$sidebarTable.height(height);
this._$dateTable.height(height);
this._setGroupHeaderCellsHeight();
},
_getWorkSpaceMinHeight: function _getWorkSpaceMinHeight() {
var minHeight = this._getWorkSpaceHeight(),
workspaceContainerHeight = this.$element().outerHeight(true) - this.getHeaderPanelHeight();
if (minHeight < workspaceContainerHeight) {
minHeight = workspaceContainerHeight;
}
return minHeight;
},
_makeGroupRows: function _makeGroupRows(groups) {
var tableCreatorStrategy = this.option("groupOrientation") === "vertical" ? tableCreator.VERTICAL : tableCreator.HORIZONTAL;
return tableCreator.makeGroupedTable(tableCreatorStrategy, groups, {
groupRowClass: this._getGroupRowClass(),
groupHeaderRowClass: this._getGroupRowClass(),
groupHeaderClass: this._getGroupHeaderClass(),
groupHeaderContentClass: this._getGroupHeaderContentClass()
}, undefined, this.option("resourceCellTemplate"));
},
_setGroupHeaderCellsHeight: function _setGroupHeaderCellsHeight() {
if (!windowUtils.hasWindow()) {
return;
}
if (this._isHorizontalGroupedWorkSpace()) {
return;
}
var cellHeight = this.getCellHeight() - DATE_TABLE_CELL_BORDER * 2;
cellHeight = this._ensureGroupHeaderCellsHeight(cellHeight);
this._getGroupHeaderCellsContent().css("height", cellHeight);
},
_ensureGroupHeaderCellsHeight: function _ensureGroupHeaderCellsHeight(cellHeight) {
var minCellHeight = this._calculateMinCellHeight();
if (cellHeight < minCellHeight) {
return minCellHeight;
}
return cellHeight;
},
_calculateMinCellHeight: function _calculateMinCellHeight() {
var dateTable = this._getDateTable(),
dateTableRowSelector = "." + this._getDateTableRowClass();
return dateTable.get(0).getBoundingClientRect().height / dateTable.find(dateTableRowSelector).length - DATE_TABLE_CELL_BORDER * 2;
},
_getCellCoordinatesByIndex: function _getCellCoordinatesByIndex(index) {
return {
cellIndex: index % this._getCellCount(),
rowIndex: 0
};
},
_getCellByCoordinates: function _getCellByCoordinates(cellCoordinates, groupIndex) {
var indexes = this._groupedStrategy.prepareCellIndexes(cellCoordinates, groupIndex);
return this._$dateTable.find("tr").eq(indexes.rowIndex).find("td").eq(indexes.cellIndex);
},
_getWorkSpaceWidth: function _getWorkSpaceWidth() {
return this._$dateTable.outerWidth(true);
},
_getGroupIndexByCell: function _getGroupIndexByCell($cell) {
return $cell.parent().index();
},
_getIndicationFirstViewDate: function _getIndicationFirstViewDate() {
return new Date(this._firstViewDate);
},
_getIntervalBetween: function _getIntervalBetween(currentDate, allDay) {
var startDayHour = this.option("startDayHour"),
endDayHour = this.option("endDayHour"),
firstViewDate = this.getStartViewDate(),
firstViewDateTime = firstViewDate.getTime(),
hiddenInterval = (24 - endDayHour + startDayHour) * toMs("hour"),
timeZoneOffset = dateUtils.getTimezonesDifference(firstViewDate, currentDate),
apptStart = currentDate.getTime(),
fullInterval = apptStart - firstViewDateTime - timeZoneOffset,
fullDays = Math.floor(fullInterval / toMs("day")),
tailDuration = fullInterval - fullDays * toMs("day"),
tailDelta = 0,
cellCount = this._getCellCountInDay() * (fullDays - this._getWeekendsCount(fullDays)),
gapBeforeAppt = apptStart - dateUtils.trimTime(new Date(currentDate)).getTime(),
result = cellCount * this.option("hoursInterval") * toMs("hour");
if (!allDay) {
if (currentDate.getHours() < startDayHour) {
tailDelta = tailDuration - hiddenInterval + gapBeforeAppt;
} else if (currentDate.getHours() >= startDayHour && currentDate.getHours() < endDayHour) {
tailDelta = tailDuration;
} else if (currentDate.getHours() >= startDayHour && currentDate.getHours() >= endDayHour) {
tailDelta = tailDuration - (gapBeforeAppt - endDayHour * toMs("hour"));
} else if (!fullDays) {
result = fullInterval;
}
result += tailDelta;
}
return result;
},
_getWeekendsCount: function _getWeekendsCount() {
return 0;
},
getAllDayContainer: function getAllDayContainer() {
return null;
},
getTimePanelWidth: function getTimePanelWidth() {
return 0;
},
getPositionShift: function getPositionShift(timeShift) {
var positionShift = this.callBase(timeShift),
left = this.getCellWidth() * timeShift;
if (this.option("rtlEnabled")) {
left *= -1;
}
left += positionShift.left;
return {
top: 0,
left: left
};
},
getVisibleBounds: function getVisibleBounds() {
var isRtl = this.option("rtlEnabled");
var result = {},
$scrollable = this.getScrollable().$element(),
cellWidth = this.getCellWidth(),
scrollableOffset = isRtl ? this.getScrollableOuterWidth() - this.getScrollableScrollLeft() : this.getScrollableScrollLeft(),
scrolledCellCount = scrollableOffset / cellWidth,
visibleCellCount = $scrollable.width() / cellWidth,
totalCellCount = isRtl ? scrolledCellCount - visibleCellCount : scrolledCellCount + visibleCellCount,
leftDate = this._getDateByIndex(scrolledCellCount),
rightDate = this._getDateByIndex(totalCellCount);
if (isRtl) {
leftDate = this._getDateByIndex(totalCellCount);
rightDate = this._getDateByIndex(scrolledCellCount);
}
result.left = {
hours: leftDate.getHours(),
minutes: leftDate.getMinutes() >= 30 ? 30 : 0,
date: dateUtils.trimTime(leftDate)
};
result.right = {
hours: rightDate.getHours(),
minutes: rightDate.getMinutes() >= 30 ? 30 : 0,
date: dateUtils.trimTime(rightDate)
};
return result;
},
needUpdateScrollPosition: function needUpdateScrollPosition(hours, minutes, bounds, date) {
var isUpdateNeeded = false;
isUpdateNeeded = this._dateWithinBounds(bounds, date);
if (hours < bounds.left.hours || hours > bounds.right.hours) {
isUpdateNeeded = true;
}
if (hours === bounds.left.hours && minutes < bounds.left.minutes) {
isUpdateNeeded = true;
}
if (hours === bounds.right.hours && minutes > bounds.right.minutes) {
isUpdateNeeded = true;
}
return isUpdateNeeded;
},
_dateWithinBounds: function _dateWithinBounds(bounds, date) {
var trimmedDate = dateUtils.trimTime(new Date(date)),
isUpdateNeeded = false;
if (trimmedDate < bounds.left.date || trimmedDate > bounds.right.date) {
isUpdateNeeded = true;
}
return isUpdateNeeded;
},
scrollToTime: function scrollToTime(hours, minutes, date) {
var coordinates = this._getScrollCoordinates(hours, minutes, date),
scrollable = this.getScrollable(),
offset = this.option("rtlEnabled") ? this.getScrollableContainer().get(0).getBoundingClientRect().width : 0;
scrollable.scrollBy({ left: coordinates.left - scrollable.scrollLeft() - offset, top: 0 });
}
});
registerComponent("dxSchedulerTimeline", SchedulerTimeline);
module.exports = SchedulerTimeline;