diff --git a/src/components/treetable/TreeTableBody.js b/src/components/treetable/TreeTableBody.js index af8f2e007b..acb96e6aa2 100644 --- a/src/components/treetable/TreeTableBody.js +++ b/src/components/treetable/TreeTableBody.js @@ -1,5 +1,6 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; +import DomHandler from '../utils/DomHandler'; import { TreeTableRow } from './TreeTableRow'; export class TreeTableBody extends Component { @@ -60,19 +61,194 @@ export class TreeTableBody extends Component { onContextMenu: PropTypes.func } + constructor(props) { + super(props); + + this.onRowClick = this.onRowClick.bind(this); + } + createRow(node, index) { return ( ); } + flattenizeTree(nodes) { + let rows = []; + nodes = nodes || this.props.value; + + for (let node of nodes) { + rows.push(node.key); + + if (this.isExpandedKey(node.key)) { + rows = rows.concat(this.flattenizeTree(node.children)); + } + } + + return rows; + } + + isExpandedKey(key) { + return this.props.expandedKeys && !!this.props.expandedKeys[key]; + } + + onRowClick(event, node) { + + if (this.props.onRowClick) { + this.props.onRowClick({ + originalEvent: event, + node: node + }); + } + + let targetNode = event.target.nodeName; + if (targetNode === 'INPUT' || targetNode === 'BUTTON' || targetNode === 'A' || DomHandler.hasClass(event.target, 'p-clickable') + || DomHandler.hasClass(event.target, 'p-treetable-toggler') || DomHandler.hasClass(event.target.parentElement, 'p-treetable-toggler')) { + return; + } + + if ((this.isSingleSelectionMode() || this.isMultipleSelectionMode()) && node.selectable !== false) { + let selectionKeys; + const selected = this.isSelected(node); + const metaSelection = this.nodeTouched ? false : this.props.metaKeySelection; + const flatKeys = this.flattenizeTree(); + const rowIndex = flatKeys.findIndex(key => key === node.key); + + if(this.isMultipleSelectionMode() && event.shiftKey) { + DomHandler.clearSelection(); + + // find first selected row + const anchorRowIndex = flatKeys.findIndex(key => this.props.selectionKeys[key]); + const rangeStart = Math.min(rowIndex, anchorRowIndex); + const rangeEnd = Math.max(rowIndex, anchorRowIndex); + + selectionKeys = {...this.props.selectionKeys}; + + for (let i = rangeStart; i <= rangeEnd; i++) { + const rowKey = flatKeys[i]; + selectionKeys[rowKey] = true; + } + } + else { + this.anchorRowIndex = rowIndex; + + if (metaSelection) { + let metaKey = (event.metaKey||event.ctrlKey); + + if (selected && metaKey) { + if (this.isSingleSelectionMode()) { + selectionKeys = null; + } + else { + selectionKeys = {...this.props.selectionKeys}; + delete selectionKeys[node.key]; + } + + if (this.props.onUnselect) { + this.props.onUnselect({ + originalEvent: event, + node: node + }); + } + } + else { + if (this.isSingleSelectionMode()) { + selectionKeys = node.key; + } + else if (this.isMultipleSelectionMode()) { + selectionKeys = !metaKey ? {} : (this.props.selectionKeys ? {...this.props.selectionKeys} : {}); + selectionKeys[node.key] = true; + } + + if (this.props.onSelect) { + this.props.onSelect({ + originalEvent: event, + node: node + }); + } + } + } + else { + if (this.isSingleSelectionMode()) { + if (selected) { + selectionKeys = null; + + if (this.props.onUnselect) { + this.props.onUnselect({ + originalEvent: event, + node: node + }); + } + } + else { + selectionKeys = node.key; + + if (this.props.onSelect) { + this.props.onSelect({ + originalEvent: event, + node: node + }); + } + } + } + else { + if (selected) { + selectionKeys = {...this.props.selectionKeys}; + delete selectionKeys[node.key]; + + if (this.props.onUnselect) { + this.props.onUnselect({ + originalEvent: event, + node: node + }); + } + } + else { + selectionKeys = this.props.selectionKeys ? {...this.props.selectionKeys} : {}; + selectionKeys[node.key] = true; + + if (this.props.onSelect) { + this.props.onSelect({ + originalEvent: event, + node: node + }); + } + } + } + } + } + + if (this.props.onSelectionChange) { + this.props.onSelectionChange({ + originalEvent: event, + value: selectionKeys + }) + } + } + } + + isSingleSelectionMode() { + return this.props.selectionMode && this.props.selectionMode === 'single'; + } + + isMultipleSelectionMode() { + return this.props.selectionMode && this.props.selectionMode === 'multiple'; + } + + isSelected(node) { + if ((this.props.selectionMode === 'single' || this.props.selectionMode === 'multiple') && this.props.selectionKeys) + return (this.props.selectionMode === 'single') ? this.props.selectionKeys === node.key : this.props.selectionKeys[node.key] !== undefined; + else + return false; + } + renderRows() { if (this.props.paginator && !this.props.lazy) { let rpp = this.props.rows||0; diff --git a/src/components/treetable/TreeTableRow.js b/src/components/treetable/TreeTableRow.js index 5fe4984b82..05512aef2b 100644 --- a/src/components/treetable/TreeTableRow.js +++ b/src/components/treetable/TreeTableRow.js @@ -127,114 +127,7 @@ export class TreeTableRow extends Component { onClick(event) { if (this.props.onRowClick) { - this.props.onRowClick({ - originalEvent: event, - node: this.props.node - }); - } - - let targetNode = event.target.nodeName; - if (targetNode === 'INPUT' || targetNode === 'BUTTON' || targetNode === 'A' || DomHandler.hasClass(event.target, 'p-clickable') - || DomHandler.hasClass(event.target, 'p-treetable-toggler') || DomHandler.hasClass(event.target.parentElement, 'p-treetable-toggler')) { - return; - } - - if ((this.isSingleSelectionMode() || this.isMultipleSelectionMode()) && this.props.node.selectable !== false) { - let selectionKeys; - const selected = this.isSelected(); - const metaSelection = this.nodeTouched ? false : this.props.metaKeySelection; - - if (metaSelection) { - let metaKey = (event.metaKey||event.ctrlKey); - - if (selected && metaKey) { - if (this.isSingleSelectionMode()) { - selectionKeys = null; - } - else { - selectionKeys = {...this.props.selectionKeys}; - delete selectionKeys[this.props.node.key]; - } - - if (this.props.onUnselect) { - this.props.onUnselect({ - originalEvent: event, - node: this.props.node - }); - } - } - else { - if (this.isSingleSelectionMode()) { - selectionKeys = this.props.node.key; - } - else if (this.isMultipleSelectionMode()) { - selectionKeys = !metaKey ? {} : (this.props.selectionKeys ? {...this.props.selectionKeys} : {}); - selectionKeys[this.props.node.key] = true; - } - - if (this.props.onSelect) { - this.props.onSelect({ - originalEvent: event, - node: this.props.node - }); - } - } - } - else { - if (this.isSingleSelectionMode()) { - if (selected) { - selectionKeys = null; - - if (this.props.onUnselect) { - this.props.onUnselect({ - originalEvent: event, - node: this.props.node - }); - } - } - else { - selectionKeys = this.props.node.key; - - if (this.props.onSelect) { - this.props.onSelect({ - originalEvent: event, - node: this.props.node - }); - } - } - } - else { - if (selected) { - selectionKeys = {...this.props.selectionKeys}; - delete selectionKeys[this.props.node.key]; - - if (this.props.onUnselect) { - this.props.onUnselect({ - originalEvent: event, - node: this.props.node - }); - } - } - else { - selectionKeys = this.props.selectionKeys ? {...this.props.selectionKeys} : {}; - selectionKeys[this.props.node.key] = true; - - if (this.props.onSelect) { - this.props.onSelect({ - originalEvent: event, - node: this.props.node - }); - } - } - } - } - - if (this.props.onSelectionChange) { - this.props.onSelectionChange({ - originalEvent: event, - value: selectionKeys - }) - } + this.props.onRowClick(event, this.props.node); } this.nodeTouched = false; @@ -428,14 +321,6 @@ export class TreeTableRow extends Component { } } - isSingleSelectionMode() { - return this.props.selectionMode && this.props.selectionMode === 'single'; - } - - isMultipleSelectionMode() { - return this.props.selectionMode && this.props.selectionMode === 'multiple'; - } - isExpanded() { return this.props.expandedKeys ? this.props.expandedKeys[this.props.node.key] !== undefined : false; }