UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

553 lines (444 loc) • 23.3 kB
"use strict"; var $ = require("../../core/renderer"), treeListCore = require("./ui.tree_list.core"), commonUtils = require("../../core/utils/common"), noop = require("../../core/utils/common").noop, selectionModule = require("../grid_core/ui.grid_core.selection"), errors = require("../widget/ui.errors"), extend = require("../../core/utils/extend").extend; var TREELIST_SELECT_ALL_CLASS = "dx-treelist-select-all", CELL_FOCUS_DISABLED_CLASS = "dx-cell-focus-disabled", SELECT_CHECKBOX_CLASS = "dx-select-checkbox"; var originalRowClick = selectionModule.extenders.views.rowsView._rowClick; var nodeExists = function nodeExists(array, currentKey) { return !!array.filter(function (key) { return key === currentKey; }).length; }; treeListCore.registerModule("selection", extend(true, {}, selectionModule, { defaultOptions: function defaultOptions() { return extend(true, selectionModule.defaultOptions(), { selection: { showCheckBoxesMode: "always", /** * @name dxTreeListOptions.selection.recursive * @publicName recursive * @type boolean * @default false */ recursive: false } }); }, extenders: { controllers: { data: { _handleDataChanged: function _handleDataChanged(e) { var selectionController = this.getController("selection"), isRecursiveSelection = selectionController.isRecursiveSelection(); if (isRecursiveSelection && (!e || e.changeType !== "updateSelectionState")) { selectionController.updateSelectionState({ selectedItemKeys: this.option("selectedRowKeys") }); } this.callBase.apply(this, arguments); }, loadDescendants: function loadDescendants() { var that = this, d = that.callBase.apply(that, arguments), selectionController = that.getController("selection"), isRecursiveSelection = selectionController.isRecursiveSelection(); if (isRecursiveSelection) { d.done(function () { selectionController.updateSelectionState({ selectedItemKeys: that.option("selectedRowKeys") }); }); } return d; } }, selection: { init: function init() { this.callBase.apply(this, arguments); this._selectionStateByKey = {}; }, renderSelectCheckBoxContainer: function renderSelectCheckBoxContainer($container, model) { var that = this, rowsView = that.component.getView("rowsView"); $container.addClass(CELL_FOCUS_DISABLED_CLASS); var $checkbox = rowsView._renderSelectCheckBox($container, { value: model.row.isSelected, row: model.row, column: model.column }); rowsView._attachCheckBoxClickEvent($checkbox); }, _updateSelectColumn: noop, _getVisibleNodeKeys: function _getVisibleNodeKeys(isRecursiveSelection) { var component = this.component, root = component.getRootNode(), keys = []; root && treeListCore.foreachNodes(root.children, function (node) { if (node.key !== undefined && (node.visible || isRecursiveSelection)) { keys.push(node.key); } return isRecursiveSelection ? false : component.isRowExpanded(node.key); }); return keys; }, isSelectAll: function isSelectAll() { var component = this.component, hasIndeterminateState, visibleKeys = this._getVisibleNodeKeys(); var selectedVisibleKeys = visibleKeys.filter(function (key) { return component.isRowSelected(key); }); if (!selectedVisibleKeys.length) { hasIndeterminateState = visibleKeys.some(function (key) { return component.isRowSelected(key) === undefined; }); return hasIndeterminateState ? undefined : false; } else if (selectedVisibleKeys.length === visibleKeys.length) { return true; } }, selectAll: function selectAll() { var that = this, isRecursiveSelection = that.isRecursiveSelection(), visibleKeys = that._getVisibleNodeKeys(isRecursiveSelection).filter(function (key) { return !that.isRowSelected(key); }); return that.selectRows(visibleKeys, true); }, deselectAll: function deselectAll() { var isRecursiveSelection = this.isRecursiveSelection(), visibleKeys = this._getVisibleNodeKeys(isRecursiveSelection); return this.deselectRows(visibleKeys); }, selectedItemKeys: function selectedItemKeys(value, preserve, isDeselect, isSelectAll) { var that = this, selectedRowKeys = that.option("selectedRowKeys"), isRecursiveSelection = this.isRecursiveSelection(), normalizedArgs = isRecursiveSelection && that._normalizeSelectionArgs({ keys: value || [] }, !isDeselect); if (normalizedArgs && !commonUtils.equalByValue(normalizedArgs.selectedRowKeys, selectedRowKeys)) { that._isSelectionNormalizing = true; return this.callBase(normalizedArgs.selectedRowKeys, false, false, false).always(function () { that._isSelectionNormalizing = false; }).done(function (items) { normalizedArgs.selectedRowsData = items; that._fireSelectionChanged(normalizedArgs); }); } return this.callBase(value, preserve, isDeselect, isSelectAll); }, changeItemSelection: function changeItemSelection(itemIndex, keyboardKeys) { var isRecursiveSelection = this.isRecursiveSelection(); if (isRecursiveSelection && !keyboardKeys.shift) { var key = this._dataController.getKeyByRowIndex(itemIndex); return this.selectedItemKeys(key, true, this.isRowSelected(key)); } return this.callBase.apply(this, arguments); }, _updateParentSelectionState: function _updateParentSelectionState(node, isSelected) { var that = this, state = isSelected, parentNode = node.parent, hasNonSelectedState, hasSelectedState; if (parentNode.children.length > 1) { if (isSelected === false) { hasSelectedState = parentNode.children.some(function (childNode, index, children) { return that._selectionStateByKey[childNode.key]; }); state = hasSelectedState ? undefined : false; } else if (isSelected === true) { hasNonSelectedState = parentNode.children.some(function (childNode) { return !that._selectionStateByKey[childNode.key]; }); state = hasNonSelectedState ? undefined : true; } } this._selectionStateByKey[parentNode.key] = state; if (parentNode.parent && parentNode.parent.level >= 0) { this._updateParentSelectionState(parentNode, state); } }, _updateChildrenSelectionState: function _updateChildrenSelectionState(node, isSelected) { var that = this, children = node.children; children.forEach(function (childNode) { that._selectionStateByKey[childNode.key] = isSelected; if (childNode.children.length > 0) { that._updateChildrenSelectionState(childNode, isSelected); } }); }, _updateSelectionStateCore: function _updateSelectionStateCore(keys, isSelected) { var node, dataController = this._dataController; for (var i = 0; i < keys.length; i++) { this._selectionStateByKey[keys[i]] = isSelected; node = dataController.getNodeByKey(keys[i]); if (node) { this._updateParentSelectionState(node, isSelected); this._updateChildrenSelectionState(node, isSelected); } } }, _getSelectedParentKeys: function _getSelectedParentKeys(key, selectedItemKeys, useCash) { var isSelected, selectedParentNode, node = this._dataController.getNodeByKey(key), parentNode = node && node.parent, result = []; while (parentNode && parentNode.level >= 0) { result.unshift(parentNode.key); isSelected = useCash ? !nodeExists(selectedItemKeys, parentNode.key) && this.isRowSelected(parentNode.key) : selectedItemKeys.indexOf(parentNode.key) >= 0; if (isSelected) { selectedParentNode = parentNode; result = this._getSelectedParentKeys(selectedParentNode.key, selectedItemKeys, useCash).concat(result); break; } else if (useCash) { break; } parentNode = parentNode.parent; } return selectedParentNode && result || []; }, _getSelectedChildKeys: function _getSelectedChildKeys(node, keysToIgnore) { var that = this, childKeys = []; node && treeListCore.foreachNodes(node.children, function (childNode) { var ignoreKeyIndex = keysToIgnore.indexOf(childNode.key); if (ignoreKeyIndex < 0) { childKeys.push(childNode.key); } return ignoreKeyIndex > 0 || ignoreKeyIndex < 0 && that._selectionStateByKey[childNode.key] === undefined; }); return childKeys; }, _normalizeParentKeys: function _normalizeParentKeys(key, args) { var that = this, index, childKeys, parentNode, keysToIgnore = [key], parentNodeKeys = that._getSelectedParentKeys(key, args.selectedRowKeys); if (parentNodeKeys.length) { keysToIgnore = keysToIgnore.concat(parentNodeKeys); keysToIgnore.forEach(function (key) { index = args.selectedRowKeys.indexOf(key); if (index >= 0) { args.selectedRowKeys.splice(index, 1); } }); parentNode = that._dataController.getNodeByKey(parentNodeKeys[0]); childKeys = that._getSelectedChildKeys(parentNode, keysToIgnore); args.selectedRowKeys = args.selectedRowKeys.concat(childKeys); } }, _normalizeChildrenKeys: function _normalizeChildrenKeys(key, args) { var that = this, index, node = that._dataController.getNodeByKey(key); node && node.children.forEach(function (childNode) { index = args.selectedRowKeys.indexOf(childNode.key); if (index >= 0) { args.selectedRowKeys.splice(index, 1); } that._normalizeChildrenKeys(childNode.key, args); }); }, _normalizeSelectedRowKeysCore: function _normalizeSelectedRowKeysCore(keys, args, isSelect) { var that = this, index; keys.forEach(function (key) { if (that.isRowSelected(key) === isSelect) { return; } that._normalizeChildrenKeys(key, args); index = args.selectedRowKeys.indexOf(key); if (isSelect) { if (index < 0) { args.selectedRowKeys.push(key); } args.currentSelectedRowKeys.push(key); } else { if (index >= 0) { args.selectedRowKeys.splice(index, 1); } args.currentDeselectedRowKeys.push(key); that._normalizeParentKeys(key, args); } }); }, _normalizeSelectionArgs: function _normalizeSelectionArgs(args, isSelect) { var result, keys = Array.isArray(args.keys) ? args.keys : [args.keys], selectedRowKeys = this.option("selectedRowKeys") || []; if (keys.length) { result = { currentSelectedRowKeys: [], currentDeselectedRowKeys: [], selectedRowKeys: selectedRowKeys.slice(0) }; this._normalizeSelectedRowKeysCore(keys, result, isSelect); } return result; }, _updateSelectedItems: function _updateSelectedItems(args) { this.updateSelectionState(args); this.callBase(args); }, _fireSelectionChanged: function _fireSelectionChanged() { if (!this._isSelectionNormalizing) { this.callBase.apply(this, arguments); } }, _isModeLeavesOnly: function _isModeLeavesOnly(mode) { return mode === "leavesOnly" || mode === true; }, _getAllSelectedRowKeys: function _getAllSelectedRowKeys(parentKeys) { var that = this, result = []; parentKeys.forEach(function (key) { var insertIndex = result.length, parentKeys = that._getSelectedParentKeys(key, result, true), childKeys = that._dataController.getChildNodeKeys(key); result.splice.apply(result, [insertIndex, 0].concat(parentKeys)); result.push(key); result = result.concat(childKeys); }); return result; }, _getParentSelectedRowKeys: function _getParentSelectedRowKeys(keys) { var that = this, result = []; keys.forEach(function (key) { var parentKeys = that._getSelectedParentKeys(key, keys); !parentKeys.length && result.push(key); }); return result; }, _getLeafSelectedRowKeys: function _getLeafSelectedRowKeys(keys) { var that = this, result = [], dataController = that._dataController; keys.forEach(function (key) { var node = dataController.getNodeByKey(key); node && !node.hasChildren && result.push(key); }); return result; }, isRecursiveSelection: function isRecursiveSelection() { var selectionMode = this.option("selection.mode"), isRecursive = this.option("selection.recursive"); return selectionMode === "multiple" && isRecursive; }, updateSelectionState: function updateSelectionState(options) { var removedItemKeys = options.removedItemKeys || [], selectedItemKeys = options.selectedItemKeys || []; this._updateSelectionStateCore(removedItemKeys, false); this._updateSelectionStateCore(selectedItemKeys, true); }, isRowSelected: function isRowSelected(key) { var result = this.callBase.apply(this, arguments), isRecursiveSelection = this.isRecursiveSelection(); if (!result && isRecursiveSelection) { if (key in this._selectionStateByKey) { return this._selectionStateByKey[key]; } return false; } return result; }, /** * @name dxTreeListMethods.getSelectedRowKeys * @publicName getSelectedRowKeys(leavesOnly) * @param1 leavesOnly:boolean * @return Array<any> * @deprecated */ /** * @name dxTreeListMethods.getSelectedRowKeys * @publicName getSelectedRowKeys(mode) * @param1 mode:string * @return Array<any> */ getSelectedRowKeys: function getSelectedRowKeys(mode) { var that = this; if (!that._dataController) { return []; } if (mode === true) { errors.log("W0002", "dxTreeList", "getSelectedRowKeys(leavesOnly)", "18.1", "Use the 'getSelectedRowKeys(mode)' method with a string parameter instead"); } var selectedRowKeys = that.callBase.apply(that, arguments); if (mode) { if (this.isRecursiveSelection()) { selectedRowKeys = this._getAllSelectedRowKeys(selectedRowKeys); } if (mode !== "all") { if (mode === "excludeRecursive") { selectedRowKeys = that._getParentSelectedRowKeys(selectedRowKeys); } else if (that._isModeLeavesOnly(mode)) { selectedRowKeys = that._getLeafSelectedRowKeys(selectedRowKeys); } } } return selectedRowKeys; } } }, views: { columnHeadersView: { _processTemplate: function _processTemplate(template, options) { var that = this, resultTemplate, renderingTemplate = this.callBase(template, options); var firstDataColumnIndex = that._columnsController.getFirstDataColumnIndex(); if (renderingTemplate && options.column.index === firstDataColumnIndex) { resultTemplate = { render: function render(options) { if (that.option("selection.mode") === "multiple") { that.renderSelectAll(options.container, options.model); } renderingTemplate.render(options); } }; } else { resultTemplate = renderingTemplate; } return resultTemplate; }, renderSelectAll: function renderSelectAll($cell, options) { $cell.addClass(TREELIST_SELECT_ALL_CLASS); this._renderSelectAllCheckBox($cell); }, _isSortableElement: function _isSortableElement($target) { return this.callBase($target) && !$target.closest("." + SELECT_CHECKBOX_CLASS).length; } }, rowsView: { _renderExpandIcon: function _renderExpandIcon($container, options) { var $iconContainer = this.callBase($container, options); if (this.option("selection.mode") === "multiple") { this.getController("selection").renderSelectCheckBoxContainer($iconContainer, options); } return $iconContainer; }, _rowClick: function _rowClick(e) { var $targetElement = $(e.event.target); if (this.isExpandIcon($targetElement)) { this.callBase.apply(this, arguments); } else { originalRowClick.apply(this, arguments); } } } } } }));