devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
1,116 lines (939 loc) • 47.7 kB
JavaScript
"use strict";
var $ = require("../../core/renderer"),
window = require("../../core/utils/window").getWindow(),
eventsEngine = require("../../events/core/events_engine"),
eventUtils = require("../../events/utils"),
clickEvent = require("../../events/click"),
commonUtils = require("../../core/utils/common"),
typeUtils = require("../../core/utils/type"),
each = require("../../core/utils/iterator").each,
browser = require("../../core/utils/browser"),
extend = require("../../core/utils/extend").extend,
equalByValue = commonUtils.equalByValue,
Guid = require("../../core/guid"),
modules = require("./ui.grid_core.modules"),
Form = require("../form"),
gridCoreUtils = require("./ui.grid_core.utils"),
themes = require("../themes"),
COLUMN_HEADERS_VIEW = "columnHeadersView",
ROWS_VIEW = "rowsView",
FOOTER_VIEW = "footerView",
COLUMN_VIEWS = [COLUMN_HEADERS_VIEW, ROWS_VIEW, FOOTER_VIEW],
ADAPTIVE_NAMESPACE = "dxDataGridAdaptivity",
HIDDEN_COLUMNS_WIDTH = "adaptiveHidden",
ADAPTIVE_ROW_TYPE = "detailAdaptive",
FORM_ITEM_CONTENT_CLASS = "dx-field-item-content",
FORM_ITEM_MODIFIED = "dx-item-modified",
HIDDEN_COLUMN_CLASS = "hidden-column",
ADAPTIVE_COLUMN_BUTTON_CLASS = "adaptive-more",
ADAPTIVE_COLUMN_NAME_CLASS = "dx-command-adaptive",
COMMAND_ADAPTIVE_HIDDEN_CLASS = "dx-command-adaptive-hidden",
ADAPTIVE_DETAIL_ROW_CLASS = "dx-adaptive-detail-row",
ADAPTIVE_ITEM_TEXT_CLASS = "dx-adaptive-item-text",
MASTER_DETAIL_CELL_CLASS = "dx-master-detail-cell",
LAST_DATA_CELL_CLASS = "dx-last-data-cell",
ADAPTIVE_COLUMN_NAME = "adaptive",
EDIT_MODE_BATCH = "batch",
EDIT_MODE_ROW = "row",
EDIT_MODE_FORM = "form",
EDIT_MODE_POPUP = "popup",
REVERT_TOOLTIP_CLASS = "revert-tooltip";
function getColumnId(column) {
return column.command ? "command:" + column.command : column.index;
}
function getDataCellElements($row) {
return $row.find("td:not(.dx-datagrid-hidden-column):not([class*='dx-command-'])");
}
function adaptiveCellTemplate(container, options) {
var $adaptiveColumnButton,
$container = $(container),
adaptiveColumnsController = options.component.getController("adaptiveColumns");
if (options.rowType !== "groupFooter") {
$adaptiveColumnButton = $("<span>").addClass(adaptiveColumnsController.addWidgetPrefix(ADAPTIVE_COLUMN_BUTTON_CLASS));
eventsEngine.on($adaptiveColumnButton, eventUtils.addNamespace(clickEvent.name, ADAPTIVE_NAMESPACE), adaptiveColumnsController.createAction(function () {
adaptiveColumnsController.toggleExpandAdaptiveDetailRow(options.key);
}));
$adaptiveColumnButton.appendTo($container);
} else {
$container.get(0).innerHTML = " ";
}
}
var AdaptiveColumnsController = modules.ViewController.inherit({
_isRowEditMode: function _isRowEditMode() {
var editMode = this._editingController.getEditMode();
return editMode === EDIT_MODE_ROW;
},
_isItemModified: function _isItemModified(item, cellOptions) {
var columnIndex = this._columnsController.getVisibleIndex(item.column.index),
rowIndex = this._dataController.getRowIndexByKey(cellOptions.key),
row = this._dataController.items()[rowIndex + 1];
return row && row.modifiedValues && typeUtils.isDefined(row.modifiedValues[columnIndex]);
},
_renderFormViewTemplate: function _renderFormViewTemplate(item, cellOptions, container) {
var that = this,
$container = $(container),
column = item.column,
cellValue = column.calculateCellValue(cellOptions.data),
focusAction = that.createAction(function () {
eventsEngine.trigger($container, clickEvent.name);
}),
cellText;
cellValue = gridCoreUtils.getDisplayValue(column, cellValue, cellOptions.data, cellOptions.rowType);
cellText = gridCoreUtils.formatValue(cellValue, column);
if (column.allowEditing && that.option("useKeyboard")) {
$container.attr("tabIndex", that.option("tabIndex"));
eventsEngine.off($container, "focus", focusAction);
eventsEngine.on($container, "focus", focusAction);
}
if (column.cellTemplate) {
var templateOptions = extend({}, cellOptions, { value: cellValue, text: cellText, column: column });
that._rowsView.renderTemplate($container, column.cellTemplate, templateOptions, !!$container.closest(window.document).length);
} else {
container = $container.get(0);
if (column.encodeHtml) {
container.textContent = cellText;
} else {
container.innerHTML = cellText;
}
$container.addClass(ADAPTIVE_ITEM_TEXT_CLASS);
if (!typeUtils.isDefined(cellText) || cellText === "") {
$container.html(" ");
}
if (!that._isRowEditMode()) {
if (that._isItemModified(item, cellOptions)) {
$container.addClass(FORM_ITEM_MODIFIED);
}
}
}
},
_getTemplate: function _getTemplate(item, cellOptions) {
var that = this,
column = item.column,
editingController = this.getController("editing");
return function (options, container) {
var isItemEdited = that._isItemEdited(item),
$container = $(container),
columnIndex = that._columnsController.getVisibleIndex(column.visibleIndex),
templateOptions = extend({}, cellOptions);
templateOptions.value = cellOptions.row.values[columnIndex];
if (isItemEdited || column.showEditorAlways) {
editingController.renderFormEditTemplate(templateOptions, item, options.component, $container, !isItemEdited);
} else {
templateOptions.column = column;
templateOptions.columnIndex = columnIndex;
that._renderFormViewTemplate(item, templateOptions, $container);
that.getView("rowsView")._cellPrepared($container, templateOptions);
}
};
},
_isVisibleColumnsValid: function _isVisibleColumnsValid(visibleColumns) {
var getCommandColumnsCount = function getCommandColumnsCount() {
var result = 0,
j,
visibleColumn;
for (j = 0; j < visibleColumns.length; j++) {
visibleColumn = visibleColumns[j];
if (visibleColumn.command) {
result++;
}
}
return result;
};
if (visibleColumns < 2) {
return false;
}
if (visibleColumns.length - getCommandColumnsCount() <= 1) {
return false;
}
return true;
},
_calculatePercentWidths: function _calculatePercentWidths(widths, visibleColumns) {
var that = this,
percentWidths = 0;
visibleColumns.forEach(function (item, index) {
if (widths[index] !== HIDDEN_COLUMNS_WIDTH) {
percentWidths += that._getItemPercentWidth(item);
}
});
return percentWidths;
},
_isPercentWidth: function _isPercentWidth(width) {
return typeUtils.isString(width) && width.slice(-1) === "%";
},
_isColumnHidden: function _isColumnHidden(column) {
return this._hiddenColumns.filter(function (hiddenColumn) {
return hiddenColumn.index === column.index;
}).length > 0;
},
_getAverageColumnsWidth: function _getAverageColumnsWidth(containerWidth, columns, columnsCanFit) {
var that = this,
fixedColumnsWidth = 0,
columnsWithoutFixedWidthCount = 0;
columns.forEach(function (column) {
if (!that._isColumnHidden(column)) {
var width = column.width;
if (typeUtils.isDefined(width) && !isNaN(parseFloat(width))) {
fixedColumnsWidth += that._isPercentWidth(width) ? that._calculatePercentWidth({
visibleIndex: column.visibleIndex,
columnsCount: columns.length,
columnsCanFit: columnsCanFit,
bestFitWidth: column.bestFitWidth,
columnWidth: width,
containerWidth: containerWidth
}) : parseFloat(width);
} else {
columnsWithoutFixedWidthCount++;
}
}
});
return (containerWidth - fixedColumnsWidth) / columnsWithoutFixedWidthCount;
},
_calculatePercentWidth: function _calculatePercentWidth(options) {
var columnFitted = options.visibleIndex < options.columnsCount - 1 && options.columnsCanFit,
partialWidth = options.containerWidth * parseFloat(options.columnWidth) / 100,
resultWidth = options.columnsCanFit && partialWidth < options.bestFitWidth ? options.bestFitWidth : partialWidth;
return columnFitted ? this.component.$element().width() * parseFloat(options.columnWidth) / 100 : resultWidth;
},
_getNotTruncatedColumnWidth: function _getNotTruncatedColumnWidth(column, containerWidth, contentColumns, columnsCanFit) {
var columnId = getColumnId(column),
widthOption = this._columnsController.columnOption(columnId, "width"),
bestFitWidth = this._columnsController.columnOption(columnId, "bestFitWidth"),
columnsCount = contentColumns.length,
colWidth;
if (widthOption && widthOption !== "auto") {
if (this._isPercentWidth(widthOption)) {
colWidth = this._calculatePercentWidth({
visibleIndex: column.visibleIndex,
columnsCount: columnsCount,
columnsCanFit: columnsCanFit,
bestFitWidth: bestFitWidth,
columnWidth: widthOption,
containerWidth: containerWidth
});
} else {
return widthOption;
}
} else {
var columnAutoWidth = this.option("columnAutoWidth");
colWidth = columnAutoWidth || !!column.command ? bestFitWidth : this._getAverageColumnsWidth(containerWidth, contentColumns, columnsCanFit);
}
var isTruncated = colWidth < bestFitWidth;
return isTruncated ? null : colWidth;
},
_getItemPercentWidth: function _getItemPercentWidth(item) {
var result = 0;
if (item.width && this._isPercentWidth(item.width)) {
result = parseFloat(item.width);
}
return result;
},
_getCommandColumnsWidth: function _getCommandColumnsWidth() {
var that = this,
columns = that._columnsController.getVisibleColumns(),
colWidth = 0;
each(columns, function (index, column) {
if (column.index < 0 || column.command) {
colWidth += that._columnsController.columnOption(getColumnId(column), "bestFitWidth") || 0;
}
});
return colWidth;
},
_isItemEdited: function _isItemEdited(item) {
if (this.isFormEditMode()) {
return false;
}
if (this._isRowEditMode()) {
var editRowKey = this._editingController.getEditRowKey();
if (equalByValue(editRowKey, this._dataController.adaptiveExpandedKey())) {
return true;
}
} else {
var rowIndex = this._dataController.getRowIndexByKey(this._dataController.adaptiveExpandedKey()) + 1,
columnIndex = this._columnsController.getVisibleIndex(item.column.index);
return this._editingController.isEditCell(rowIndex, columnIndex);
}
},
_getFormItemsByHiddenColumns: function _getFormItemsByHiddenColumns(hiddenColumns) {
var items = [];
each(hiddenColumns, function (_, column) {
items.push({
column: column,
name: column.name,
dataField: column.dataField,
visibleIndex: column.visibleIndex
});
});
return items;
},
_getAdaptiveColumnVisibleIndex: function _getAdaptiveColumnVisibleIndex(visibleColumns) {
var i, column;
for (i = 0; i < visibleColumns.length; i++) {
column = visibleColumns[i];
if (column.command === ADAPTIVE_COLUMN_NAME) {
return i;
}
}
},
_hideAdaptiveColumn: function _hideAdaptiveColumn(resultWidths, visibleColumns) {
var visibleIndex = this._getAdaptiveColumnVisibleIndex(visibleColumns);
if (typeUtils.isDefined(visibleIndex)) {
resultWidths[visibleIndex] = HIDDEN_COLUMNS_WIDTH;
this._addCssClassToColumn(COMMAND_ADAPTIVE_HIDDEN_CLASS, visibleIndex);
}
},
_removeCssClassFromColumn: function _removeCssClassFromColumn(cssClassName) {
var i, view, $cells;
for (i = 0; i < COLUMN_VIEWS.length; i++) {
view = this.getView(COLUMN_VIEWS[i]);
if (view && view.isVisible() && view.element()) {
$cells = view.element().find("." + cssClassName);
$cells.removeClass(cssClassName);
}
}
},
_removeCssClassesFromColumns: function _removeCssClassesFromColumns() {
this._removeCssClassFromColumn(COMMAND_ADAPTIVE_HIDDEN_CLASS);
this._removeCssClassFromColumn(this.addWidgetPrefix(HIDDEN_COLUMN_CLASS));
},
_isCellValid: function _isCellValid($cell) {
return !$cell.hasClass(MASTER_DETAIL_CELL_CLASS);
},
_addCssClassToColumn: function _addCssClassToColumn(cssClassName, visibleIndex) {
var that = this;
COLUMN_VIEWS.forEach(function (viewName) {
var view = that.getView(viewName);
view && that._addCssClassToViewColumn(view, cssClassName, visibleIndex);
});
},
_addCssClassToViewColumn: function _addCssClassToViewColumn(view, cssClassName, visibleIndex) {
var viewName = view.name,
rowsCount,
rowIndex,
$cellElement,
currentVisibleIndex,
column = this._columnsController.getVisibleColumns()[visibleIndex],
editFormRowIndex = this._editingController && this._editingController.getEditFormRowIndex();
if (view && view.isVisible() && column) {
rowsCount = view.getRowsCount();
var $rowElements = view._getRowElements();
for (rowIndex = 0; rowIndex < rowsCount; rowIndex++) {
if (rowIndex !== editFormRowIndex || viewName !== ROWS_VIEW) {
currentVisibleIndex = viewName === COLUMN_HEADERS_VIEW ? this._columnsController.getVisibleIndex(column.index, rowIndex) : visibleIndex;
if (currentVisibleIndex >= 0) {
$cellElement = $rowElements.eq(rowIndex).children().eq(currentVisibleIndex);
this._isCellValid($cellElement) && $cellElement.addClass(cssClassName);
}
}
}
}
},
isFormEditMode: function isFormEditMode() {
var editMode = this._editingController.getEditMode();
return editMode === EDIT_MODE_FORM || editMode === EDIT_MODE_POPUP;
},
hideRedundantColumns: function hideRedundantColumns(resultWidths, visibleColumns, hiddenQueue) {
var that = this,
visibleColumn;
this._hiddenColumns = [];
if (that._isVisibleColumnsValid(visibleColumns) && hiddenQueue.length) {
var totalWidth = 0,
percentWidths,
$rootElement = that.component.$element(),
rootElementWidth = $rootElement.width() - that._getCommandColumnsWidth(),
contentColumns = visibleColumns.filter(function (item) {
return !item.command;
}),
columnsCanFit,
i,
contentColumnCount = contentColumns.length,
needHideColumn;
do {
needHideColumn = false;
totalWidth = 0;
percentWidths = that._calculatePercentWidths(resultWidths, visibleColumns);
columnsCanFit = percentWidths < 100 && percentWidths !== 0;
for (i = 0; i < visibleColumns.length; i++) {
visibleColumn = visibleColumns[i];
var columnWidth = that._getNotTruncatedColumnWidth(visibleColumn, rootElementWidth, contentColumns, columnsCanFit),
columnId = getColumnId(visibleColumn),
widthOption = that._columnsController.columnOption(columnId, "width"),
columnBestFitWidth = that._columnsController.columnOption(columnId, "bestFitWidth");
if (resultWidths[i] === HIDDEN_COLUMNS_WIDTH) {
continue;
}
if (!columnWidth && !visibleColumn.command && !visibleColumn.fixed) {
needHideColumn = true;
break;
}
if (widthOption && widthOption !== "auto") {
totalWidth += columnWidth;
} else {
totalWidth += columnBestFitWidth || 0;
}
}
needHideColumn = needHideColumn || totalWidth > $rootElement.width();
if (needHideColumn) {
var column = hiddenQueue.pop(),
visibleIndex = that._columnsController.getVisibleIndex(column.index);
that._addCssClassToColumn(that.addWidgetPrefix(HIDDEN_COLUMN_CLASS), visibleIndex);
resultWidths[visibleIndex] = HIDDEN_COLUMNS_WIDTH;
contentColumnCount--;
this._hiddenColumns.push(column);
}
} while (needHideColumn && contentColumnCount > 1 && hiddenQueue.length);
if (contentColumnCount === contentColumns.length) {
that._hideAdaptiveColumn(resultWidths, visibleColumns);
}
} else {
that._hideAdaptiveColumn(resultWidths, visibleColumns);
}
},
getItemContentByColumnIndex: function getItemContentByColumnIndex(visibleColumnIndex) {
var $itemContent, i, item;
for (i = 0; i < this._$itemContents.length; i++) {
$itemContent = this._$itemContents.eq(i);
item = $itemContent.data("dx-form-item");
if (item && item.column && this._columnsController.getVisibleIndex(item.column.index) === visibleColumnIndex) {
return $itemContent;
}
}
},
toggleExpandAdaptiveDetailRow: function toggleExpandAdaptiveDetailRow(key, alwaysExpanded) {
if (!(this.isFormEditMode() && this._editingController.isEditing())) {
this.getController("data").toggleExpandAdaptiveDetailRow(key, alwaysExpanded);
}
},
createFormByHiddenColumns: function createFormByHiddenColumns(container, options) {
var that = this,
$container = $(container),
userFormOptions = {
items: that._getFormItemsByHiddenColumns(that._hiddenColumns),
formID: "dx-" + new Guid()
},
defaultFormOptions = themes.isMaterial() ? {
colCount: 2,
screenByWidth: function screenByWidth() {
return "lg";
}
} : {};
this.executeAction("onAdaptiveDetailRowPreparing", { formOptions: userFormOptions });
that._$itemContents = null;
that._form = that._createComponent($("<div>").appendTo($container), Form, extend(defaultFormOptions, userFormOptions, {
customizeItem: function customizeItem(item) {
var column = item.column || that._columnsController.columnOption(item.name || item.dataField);
if (column) {
item.label = item.label || {};
item.label.text = item.label.text || column.caption;
item.column = column;
item.template = that._getTemplate(item, options, that.updateForm.bind(that));
}
userFormOptions.customizeItem && userFormOptions.customizeItem.call(this, item);
},
onContentReady: function onContentReady(e) {
userFormOptions.onContentReady && userFormOptions.onContentReady.call(this, e);
that._$itemContents = $container.find("." + FORM_ITEM_CONTENT_CLASS);
}
}));
},
hasAdaptiveDetailRowExpanded: function hasAdaptiveDetailRowExpanded() {
return typeUtils.isDefined(this._dataController.adaptiveExpandedKey());
},
updateForm: function updateForm(hiddenColumns) {
if (this.hasAdaptiveDetailRowExpanded()) {
if (this._form && typeUtils.isDefined(this._form._contentReadyAction)) {
if (hiddenColumns && hiddenColumns.length) {
this._form.option("items", this._getFormItemsByHiddenColumns(hiddenColumns));
} else {
this._form.repaint();
}
}
}
},
updateHidingQueue: function updateHidingQueue(columns) {
var that = this,
hideableColumns = columns.filter(function (column) {
return column.visible && !column.fixed && !(typeUtils.isDefined(column.groupIndex) && column.groupIndex >= 0);
}),
columnsHasHidingPriority,
i;
that._hidingColumnsQueue = [];
if (that.option("allowColumnResizing") && that.option("columnResizingMode") === "widget") {
return that._hidingColumnsQueue;
}
for (i = 0; i < hideableColumns.length; i++) {
if (typeUtils.isDefined(hideableColumns[i].hidingPriority) && hideableColumns[i].hidingPriority >= 0) {
columnsHasHidingPriority = true;
that._hidingColumnsQueue[hideableColumns[i].hidingPriority] = hideableColumns[i];
}
}
if (columnsHasHidingPriority) {
that._hidingColumnsQueue.reverse();
} else if (that.option("columnHidingEnabled")) {
for (i = 0; i < hideableColumns.length; i++) {
var visibleIndex = that._columnsController.getVisibleIndex(hideableColumns[i].index);
that._hidingColumnsQueue[visibleIndex] = hideableColumns[i];
}
}
that._hidingColumnsQueue = that._hidingColumnsQueue.filter(Object);
return that._hidingColumnsQueue;
},
getHiddenColumns: function getHiddenColumns() {
return this._hiddenColumns;
},
hasHiddenColumns: function hasHiddenColumns() {
return this._hiddenColumns.length > 0;
},
getHidingColumnsQueue: function getHidingColumnsQueue() {
return this._hidingColumnsQueue;
},
init: function init() {
var that = this;
that._columnsController = that.getController("columns");
that._dataController = that.getController("data");
that._rowsView = that.getView("rowsView");
that._columnsController.addCommandColumn({
command: ADAPTIVE_COLUMN_NAME,
visible: true,
adaptiveHidden: true,
cssClass: ADAPTIVE_COLUMN_NAME_CLASS,
width: "auto",
cellTemplate: adaptiveCellTemplate
});
that._columnsController.columnsChanged.add(function () {
var isAdaptiveVisible = !!that.updateHidingQueue(that._columnsController.getColumns()).length;
that._columnsController.columnOption("command:adaptive", "adaptiveHidden", !isAdaptiveVisible, true);
});
that._editingController = that.getController("editing");
that._hidingColumnsQueue = [];
that._hiddenColumns = [];
that.createAction("onAdaptiveDetailRowPreparing");
that.callBase();
},
optionChanged: function optionChanged(args) {
if (args.name === "columnHidingEnabled") {
this._columnsController.columnOption("command:adaptive", "adaptiveHidden", !args.value);
}
this.callBase(args);
},
publicMethods: function publicMethods() {
return ["isAdaptiveDetailRowExpanded", "expandAdaptiveDetailRow", "collapseAdaptiveDetailRow"];
},
/**
* @name GridBaseMethods.isAdaptiveDetailRowExpanded
* @publicName isAdaptiveDetailRowExpanded(key)
* @param1 key:any
*/
isAdaptiveDetailRowExpanded: function isAdaptiveDetailRowExpanded(key) {
return this._dataController.adaptiveExpandedKey() && commonUtils.equalByValue(this._dataController.adaptiveExpandedKey(), key);
},
/**
* @name GridBaseMethods.expandAdaptiveDetailRow
* @publicName expandAdaptiveDetailRow(key)
* @param1 key:any
*/
expandAdaptiveDetailRow: function expandAdaptiveDetailRow(key) {
if (!this.hasAdaptiveDetailRowExpanded()) {
this.toggleExpandAdaptiveDetailRow(key);
}
},
/**
* @name GridBaseMethods.collapseAdaptiveDetailRow
* @publicName collapseAdaptiveDetailRow()
*/
collapseAdaptiveDetailRow: function collapseAdaptiveDetailRow() {
if (this.hasAdaptiveDetailRowExpanded()) {
this.toggleExpandAdaptiveDetailRow();
}
}
});
module.exports = {
defaultOptions: function defaultOptions() {
return {
/**
* @name GridBaseOptions.columnHidingEnabled
* @publicName columnHidingEnabled
* @type boolean
* @default false
*/
columnHidingEnabled: false,
/**
* @name GridBaseOptions.onAdaptiveDetailRowPreparing
* @publicName onAdaptiveDetailRowPreparing
* @extends Action
* @type function(e)
* @type_function_param1 e:object
* @type_function_param1_field4 formOptions:object
* @action
*/
onAdaptiveDetailRowPreparing: null
};
},
controllers: {
adaptiveColumns: AdaptiveColumnsController
},
extenders: {
views: {
rowsView: {
_getCellTemplate: function _getCellTemplate(options) {
var that = this,
column = options.column;
if (options.rowType === ADAPTIVE_ROW_TYPE && column.command === "detail") {
return function (container, options) {
that._adaptiveColumnsController.createFormByHiddenColumns($(container), options);
};
}
return that.callBase(options);
},
_createRow: function _createRow(row) {
var $row = this.callBase(row);
if (row && row.rowType === ADAPTIVE_ROW_TYPE && row.key === this._dataController.adaptiveExpandedKey()) {
$row.addClass(ADAPTIVE_DETAIL_ROW_CLASS);
}
return $row;
},
_renderCells: function _renderCells($row, options) {
this.callBase($row, options);
var hidingColumnsQueueLength = this._adaptiveColumnsController.getHidingColumnsQueue().length,
hiddenColumnsLength = this._adaptiveColumnsController.getHiddenColumns().length;
if (hidingColumnsQueueLength && !hiddenColumnsLength) {
getDataCellElements($row).last().addClass(LAST_DATA_CELL_CLASS);
}
},
_getColumnIndexByElementCore: function _getColumnIndexByElementCore($element) {
var $itemContent = $element.closest("." + FORM_ITEM_CONTENT_CLASS);
if ($itemContent.length && $itemContent.closest(this.component.$element()).length) {
var formItem = $itemContent.length ? $itemContent.first().data("dx-form-item") : null;
return formItem && formItem.column && this._columnsController.getVisibleIndex(formItem.column.index);
} else {
return this.callBase($element);
}
},
_cellPrepared: function _cellPrepared($cell, options) {
this.callBase.apply(this, arguments);
if (options.row.rowType !== ADAPTIVE_ROW_TYPE && options.column.visibleWidth === HIDDEN_COLUMNS_WIDTH) {
$cell.addClass(this.addWidgetPrefix(HIDDEN_COLUMN_CLASS));
}
},
_getCellElement: function _getCellElement(rowIndex, columnIdentifier) {
var item = this._dataController.items()[rowIndex];
if (item && item.rowType === ADAPTIVE_ROW_TYPE) {
return this._adaptiveColumnsController.getItemContentByColumnIndex(columnIdentifier);
} else {
return this.callBase(rowIndex, columnIdentifier);
}
},
getContextMenuItems: function getContextMenuItems(options) {
if (options.row && options.row.rowType === "detailAdaptive") {
var view = this.component.getView("columnHeadersView");
var formItem = $(options.targetElement).closest(".dx-field-item-label").next().data("dx-form-item");
options.column = formItem ? formItem.column : options.column;
return view.getContextMenuItems && view.getContextMenuItems(options);
}
return this.callBase && this.callBase(options);
},
isClickableElement: function isClickableElement($target) {
var isClickable = this.callBase ? this.callBase($target) : false;
return isClickable || !!$target.closest("." + ADAPTIVE_COLUMN_NAME_CLASS).length;
},
init: function init() {
this.callBase();
this._adaptiveColumnsController = this.getController("adaptiveColumns");
}
}
},
controllers: {
export: {
_updateColumnWidth: function _updateColumnWidth(column, width) {
this.callBase(column, column.visibleWidth === HIDDEN_COLUMNS_WIDTH ? column.bestFitWidth : width);
}
},
columnsResizer: {
_pointCreated: function _pointCreated(point, cellsLength, columns) {
var result = this.callBase(point, cellsLength, columns),
currentColumn = columns[point.columnIndex] || {},
nextColumnIndex = this._getNextColumnIndex(point.columnIndex),
nextColumn = columns[nextColumnIndex] || {},
hasHiddenColumnsOnly = nextColumnIndex !== point.columnIndex + 1 && nextColumn.command,
hasAdaptiveHiddenWidth = currentColumn.visibleWidth === HIDDEN_COLUMNS_WIDTH || hasHiddenColumnsOnly;
return result || hasAdaptiveHiddenWidth;
},
_getNextColumnIndex: function _getNextColumnIndex(currentColumnIndex) {
var visibleColumns = this._columnsController.getVisibleColumns(),
index = this.callBase(currentColumnIndex);
while (visibleColumns[index] && visibleColumns[index].visibleWidth === HIDDEN_COLUMNS_WIDTH) {
index++;
}
return index;
}
},
draggingHeader: {
_pointCreated: function _pointCreated(point, columns, location, sourceColumn) {
var result = this.callBase(point, columns, location, sourceColumn),
column = columns[point.columnIndex - 1] || {},
hasAdaptiveHiddenWidth = column.visibleWidth === HIDDEN_COLUMNS_WIDTH;
return result || hasAdaptiveHiddenWidth;
}
},
editing: {
_isRowEditMode: function _isRowEditMode() {
return this.getEditMode() === EDIT_MODE_ROW;
},
_getFormEditItemTemplate: function _getFormEditItemTemplate(cellOptions, column) {
if (this.getEditMode() !== EDIT_MODE_ROW && cellOptions.rowType === "detailAdaptive") {
cellOptions.columnIndex = this._columnsController.getVisibleIndex(column.index);
return this.getColumnTemplate(cellOptions);
}
return this.callBase(cellOptions, column);
},
_closeEditItem: function _closeEditItem($targetElement) {
var $itemContents = $targetElement.closest("." + FORM_ITEM_CONTENT_CLASS),
rowIndex = this._dataController.getRowIndexByKey(this._dataController.adaptiveExpandedKey()) + 1,
formItem = $itemContents.length ? $itemContents.first().data("dx-form-item") : null,
columnIndex = formItem && formItem.column && this._columnsController.getVisibleIndex(formItem.column.index);
if (!this.isEditCell(rowIndex, columnIndex)) {
this.callBase($targetElement);
}
},
_beforeUpdateItems: function _beforeUpdateItems(rowIndices, rowIndex) {
if (!this._adaptiveController.isFormEditMode() && this._adaptiveController.hasHiddenColumns()) {
var items = this._dataController.items(),
item = items[rowIndex],
oldExpandRowIndex = gridCoreUtils.getIndexByKey(this._dataController.adaptiveExpandedKey(), items);
this._isForceRowAdaptiveExpand = !this._adaptiveController.hasAdaptiveDetailRowExpanded();
if (oldExpandRowIndex >= 0 && rowIndex > oldExpandRowIndex) {
this._editRowIndex--;
}
if (oldExpandRowIndex >= 0) {
rowIndices.push(oldExpandRowIndex + 1);
}
rowIndices.push(rowIndex + 1);
this._dataController.adaptiveExpandedKey(item.key);
}
},
_afterInsertRow: function _afterInsertRow(options) {
this.callBase(options);
if (this._adaptiveController.hasHiddenColumns()) {
this._adaptiveController.toggleExpandAdaptiveDetailRow(options.key, this.isRowEditMode());
this._isForceRowAdaptiveExpand = true;
}
},
_collapseAdaptiveDetailRow: function _collapseAdaptiveDetailRow() {
if (this._isRowEditMode() && this._isForceRowAdaptiveExpand) {
this._adaptiveController.collapseAdaptiveDetailRow();
this._isForceRowAdaptiveExpand = false;
}
},
_cancelEditAdaptiveDetailRow: function _cancelEditAdaptiveDetailRow() {
if (this._adaptiveController.hasHiddenColumns()) {
this._collapseAdaptiveDetailRow();
}
},
_afterSaveEditData: function _afterSaveEditData() {
this.callBase();
if (this._isRowEditMode() && this._adaptiveController.hasHiddenColumns() && this.getController("validating").validate(true)) {
this._cancelEditAdaptiveDetailRow();
}
},
_beforeCancelEditData: function _beforeCancelEditData() {
this.callBase();
this._cancelEditAdaptiveDetailRow();
},
_getRowIndicesForCascadeUpdating: function _getRowIndicesForCascadeUpdating(row) {
var rowIndices = this.callBase.apply(this, arguments);
if (this._adaptiveController.isAdaptiveDetailRowExpanded(row.key)) {
rowIndices.push(row.rowType === ADAPTIVE_ROW_TYPE ? row.rowIndex - 1 : row.rowIndex + 1);
}
return rowIndices;
},
_beforeCloseEditCellInBatchMode: function _beforeCloseEditCellInBatchMode(rowIndices) {
var expandedKey = this._dataController._adaptiveExpandedKey,
rowIndex;
if (expandedKey) {
rowIndex = gridCoreUtils.getIndexByKey(expandedKey, this._dataController.items());
if (rowIndex > -1) {
rowIndices.unshift(rowIndex);
}
}
},
editRow: function editRow(rowIndex) {
if (this._adaptiveController.isFormEditMode()) {
this._adaptiveController.collapseAdaptiveDetailRow();
}
this.callBase(rowIndex);
},
deleteRow: function deleteRow(rowIndex) {
var rowKey = this._dataController.getKeyByRowIndex(rowIndex);
if (this.getEditMode() === EDIT_MODE_BATCH && this._adaptiveController.isAdaptiveDetailRowExpanded(rowKey)) {
this._adaptiveController.collapseAdaptiveDetailRow();
}
this.callBase(rowIndex);
},
init: function init() {
this.callBase();
this._adaptiveController = this.getController("adaptiveColumns");
}
},
resizing: {
_needBestFit: function _needBestFit() {
return this.callBase() || !!this._adaptiveColumnsController.getHidingColumnsQueue().length;
},
_updateScrollableForIE: function _updateScrollableForIE() {
var that = this;
if (browser.msie && parseInt(browser.version) <= 11) {
setTimeout(function () {
that.getView("rowsView")._updateScrollable();
});
}
},
_correctColumnWidths: function _correctColumnWidths(resultWidths, visibleColumns) {
var adaptiveController = this._adaptiveColumnsController,
columnAutoWidth = this.option("columnAutoWidth"),
oldHiddenColumns = adaptiveController.getHiddenColumns(),
hiddenColumns,
hidingColumnsQueue = adaptiveController.updateHidingQueue(this._columnsController.getColumns());
adaptiveController.hideRedundantColumns(resultWidths, visibleColumns, hidingColumnsQueue);
hiddenColumns = adaptiveController.getHiddenColumns();
if (adaptiveController.hasAdaptiveDetailRowExpanded()) {
if (oldHiddenColumns.length !== hiddenColumns.length) {
adaptiveController.updateForm(hiddenColumns);
}
}
!hiddenColumns.length && adaptiveController.collapseAdaptiveDetailRow();
if (columnAutoWidth && hidingColumnsQueue.length && !hiddenColumns.length) {
this._updateScrollableForIE();
}
return this.callBase.apply(this, arguments);
},
_toggleBestFitMode: function _toggleBestFitMode(isBestFit) {
isBestFit && this._adaptiveColumnsController._removeCssClassesFromColumns();
this.callBase(isBestFit);
if (!this.option("legacyRendering") && this._adaptiveColumnsController.getHidingColumnsQueue().length) {
var $rowsTable = this._rowsView._getTableElement();
$rowsTable.get(0).style.width = isBestFit ? "auto" : "";
}
},
_needStretch: function _needStretch() {
return this.callBase.apply(this, arguments) || this._adaptiveColumnsController.getHidingColumnsQueue().length;
},
init: function init() {
this._adaptiveColumnsController = this.getController("adaptiveColumns");
this.callBase();
}
},
data: {
_processItems: function _processItems(items, changeType) {
var that = this,
item,
expandRowIndex;
items = that.callBase.apply(that, arguments);
if (changeType === "loadingAll" || !typeUtils.isDefined(that._adaptiveExpandedKey)) {
return items;
}
expandRowIndex = gridCoreUtils.getIndexByKey(that._adaptiveExpandedKey, items);
if (expandRowIndex >= 0) {
item = items[expandRowIndex];
items.splice(expandRowIndex + 1, 0, {
visible: true,
rowType: ADAPTIVE_ROW_TYPE,
key: item.key,
data: item.data,
modifiedValues: item.modifiedValues,
inserted: item.inserted,
values: item.values
});
} else {
that._adaptiveExpandedKey = undefined;
}
return items;
},
_getRowIndicesForExpand: function _getRowIndicesForExpand(key) {
var rowIndices = this.callBase.apply(this, arguments),
lastRowIndex;
if (this.getController("adaptiveColumns").isAdaptiveDetailRowExpanded(key)) {
lastRowIndex = rowIndices[rowIndices.length - 1];
rowIndices.push(lastRowIndex + 1);
}
return rowIndices;
},
adaptiveExpandedKey: function adaptiveExpandedKey(value) {
if (typeUtils.isDefined(value)) {
this._adaptiveExpandedKey = value;
} else {
return this._adaptiveExpandedKey;
}
},
toggleExpandAdaptiveDetailRow: function toggleExpandAdaptiveDetailRow(key, alwaysExpanded) {
var that = this;
var oldExpandRowIndex = gridCoreUtils.getIndexByKey(that._adaptiveExpandedKey, that._items);
var newExpandRowIndex = gridCoreUtils.getIndexByKey(key, that._items);
if (oldExpandRowIndex >= 0 && oldExpandRowIndex === newExpandRowIndex && !alwaysExpanded) {
key = undefined;
newExpandRowIndex = -1;
}
that._adaptiveExpandedKey = key;
if (oldExpandRowIndex >= 0) {
oldExpandRowIndex++;
}
if (newExpandRowIndex >= 0) {
newExpandRowIndex++;
}
that.updateItems({
changeType: "update",
rowIndices: [oldExpandRowIndex, newExpandRowIndex]
});
},
init: function init() {
this.callBase();
this._adaptiveExpandedKey = undefined;
}
},
editorFactory: {
_getFocusCellSelector: function _getFocusCellSelector() {
return this.callBase() + ", .dx-adaptive-detail-row .dx-field-item > .dx-field-item-content";
},
_getTooltipsSelector: function _getTooltipsSelector() {
return this.callBase() + ", .dx-field-item-content ." + this.addWidgetPrefix(REVERT_TOOLTIP_CLASS);
}
},
columns: {
_isColumnVisible: function _isColumnVisible(column) {
return this.callBase(column) && !column.adaptiveHidden;
}
},
keyboardNavigation: {
_isCellValid: function _isCellValid($cell) {
return this.callBase($cell) && !$cell.hasClass(this.addWidgetPrefix(HIDDEN_COLUMN_CLASS));
},
_processNextCellInMasterDetail: function _processNextCellInMasterDetail($nextCell) {
this.callBase($nextCell);
if (!this._isInsideEditForm($nextCell) && $nextCell) {
var focusHandler = function focusHandler() {
eventsEngine.off($nextCell, "focus", focusHandler);
eventsEngine.trigger($nextCell, "dxclick");
};
eventsEngine.on($nextCell, "focus", focusHandler);
}
},
_handleTabKeyOnMasterDetailCell: function _handleTabKeyOnMasterDetailCell(eventTarget, direction) {
var result = this.callBase(eventTarget, direction),
$currentCell = this._getFocusedCell();
if (!result && $currentCell) {
var $row = $currentCell.parent(),
$dataCells = getDataCellElements($row),
$targetCell = direction === "next" ? $dataCells.last() : $dataCells.first(),
rowIndex = $row.get(0).rowIndex,
adaptiveController = this._adaptiveController,
key = this._dataController.getKeyByRowIndex(direction === "next" ? rowIndex : rowIndex - 1),
isCellElementsEquals = $currentCell && $targetCell && $currentCell.get(0) === $targetCell.get(0);
return adaptiveController.isAdaptiveDetailRowExpanded(key) && isCellElementsEquals;
}
return result;
},
init: function init() {
this.callBase();
this._adaptiveController = this.getController("adaptiveColumns");
}
}
}
}
};