From 0f2ba4e533ed64313aad3ebf71117f7087e3e841 Mon Sep 17 00:00:00 2001 From: mertsincan Date: Fri, 16 Apr 2021 10:34:11 +0300 Subject: [PATCH] Refactor #1926 --- src/components/datatable/BodyCell.js | 69 ++--- src/components/datatable/BodyRow.js | 14 +- src/components/datatable/DataTable.d.ts | 19 +- src/components/datatable/DataTable.js | 14 +- src/components/datatable/TableBody.js | 349 ++++++++++++------------ 5 files changed, 223 insertions(+), 242 deletions(-) diff --git a/src/components/datatable/BodyCell.js b/src/components/datatable/BodyCell.js index bd89d97473..71262d1ab0 100644 --- a/src/components/datatable/BodyCell.js +++ b/src/components/datatable/BodyCell.js @@ -48,7 +48,7 @@ export class BodyCell extends Component { } } - if (this.props.cellSelection) { + if (this.props.allowCellSelection) { const cell = event.currentTarget; switch (event.which) { @@ -145,7 +145,7 @@ export class BodyCell extends Component { }); } - if (this.props.cellSelection && this.props.onClick) { + if (this.props.allowCellSelection && this.props.onClick) { this.props.onClick({ originalEvent: event, value: ObjectUtils.resolveFieldData(this.props.rowData, this.props.field), @@ -262,53 +262,37 @@ export class BodyCell extends Component { findNextSelectableCell(cell) { let nextCell = cell.nextElementSibling; if (nextCell) { - if (DomHandler.hasClass(nextCell, 'p-selectable-cell')) - return nextCell; - else - return this.findNextSelectableRow(nextCell); - } - else { - return null; + return DomHandler.hasClass(nextCell, 'p-selectable-cell') ? nextCell : this.findNextSelectableRow(nextCell); } + + return null; } findPrevSelectableCell(cell) { let prevCell = cell.previousElementSibling; if (prevCell) { - if (DomHandler.hasClass(prevCell, 'p-selectable-cell')) - return prevCell; - else - return this.findPrevSelectableRow(prevCell); - } - else { - return null; + return DomHandler.hasClass(prevCell, 'p-selectable-cell') ? prevCell : this.findPrevSelectableRow(prevCell); } + + return null; } findNextSelectableRow(row) { let nextRow = row.nextElementSibling; if (nextRow) { - if (DomHandler.hasClass(nextRow, 'p-selectable-row')) - return nextRow; - else - return this.findNextSelectableRow(nextRow); - } - else { - return null; + return DomHandler.hasClass(nextRow, 'p-selectable-row') ? nextRow : this.findNextSelectableRow(nextRow); } + + return null; } findPrevSelectableRow(row) { let prevRow = row.previousElementSibling; if (prevRow) { - if (DomHandler.hasClass(prevRow, 'p-selectable-row')) - return prevRow; - else - return this.findPrevSelectableRow(prevRow); - } - else { - return null; + return DomHandler.hasClass(prevRow, 'p-selectable-row') ? prevRow : this.findPrevSelectableRow(prevRow); } + + return null; } changeTabIndex(currentCell, nextCell) { @@ -319,36 +303,23 @@ export class BodyCell extends Component { } getTabIndex(cellSelected) { - return this.props.cellSelection ? (cellSelected ? 0 : (this.props.rowIndex === 0 && this.props.index === 0 ? 0 : -1)) : null; + return this.props.allowCellSelection ? (cellSelected ? 0 : (this.props.rowIndex === 0 && this.props.index === 0 ? 0 : -1)) : null; } isSelected() { if (this.props.selection) { - if (this.props.selection instanceof Array) - return this.findIndexInSelection() > -1; - else - return this.equals(this.props.selection); + return (this.props.selection instanceof Array) ? this.findIndexInSelection() > -1 : this.equals(this.props.selection); } return false; } equals(selectedCell) { - return selectedCell.rowIndex === this.props.rowIndex && (selectedCell.field === this.props.field || selectedCell.cellIndex === this.props.index); + return (selectedCell.rowIndex === this.props.rowIndex || selectedCell.rowData === this.props.rowData) && (selectedCell.field === this.props.field || selectedCell.cellIndex === this.props.index); } findIndexInSelection() { - let index = -1; - if (this.props.selection) { - for (let i = 0; i < this.props.selection.length; i++) { - if (this.equals(this.props.selection[i])) { - index = i; - break; - } - } - } - - return index; + return this.props.selection ? this.props.selection.findIndex(d => this.equals(d)) : -1; } unbindDocumentEditListener() { @@ -397,10 +368,10 @@ export class BodyCell extends Component { render() { let content, editorKeyHelper; - let cellSelected = this.props.cellSelection && this.isSelected() + let cellSelected = this.props.allowCellSelection && this.isSelected(); let cellClassName = classNames(this.props.bodyClassName || this.props.className, { 'p-selection-column': this.props.selectionMode, - 'p-selectable-cell': this.props.cellSelection, + 'p-selectable-cell': this.props.allowCellSelection, 'p-highlight': cellSelected, 'p-editable-column': this.props.editor, 'p-cell-editing': this.state.editing && this.props.editor diff --git a/src/components/datatable/BodyRow.js b/src/components/datatable/BodyRow.js index aa136a5953..7715ad3256 100644 --- a/src/components/datatable/BodyRow.js +++ b/src/components/datatable/BodyRow.js @@ -133,7 +133,7 @@ export class BodyRow extends Component { } onKeyDown(event) { - if (this.props.selectionMode && !this.props.cellSelection) { + if (this.isFocusable() && !this.props.allowCellSelection) { const row = event.currentTarget; switch (event.which) { @@ -270,16 +270,20 @@ export class BodyRow extends Component { event.preventDefault(); } + isFocusable() { + return this.props.selectionMode && this.props.selectionModeInColumn !== 'single' && this.props.selectionModeInColumn !== 'multiple'; + } + getTabIndex() { - return this.props.selectionMode && !this.props.cellSelection ? (this.props.rowIndex === 0 ? 0 : -1) : null; + return this.isFocusable() && !this.props.allowCellSelection ? (this.props.rowIndex === 0 ? 0 : -1) : null; } render() { let columns = React.Children.toArray(this.props.children); let conditionalClassNames = { - 'p-highlight': !this.props.cellSelection && this.props.selected, + 'p-highlight': !this.props.allowCellSelection && this.props.selected, 'p-highlight-contextmenu': this.props.contextMenuSelected, - 'p-selectable-row': this.props.selectionMode + 'p-selectable-row': this.props.allowRowSelection }; if (this.props.rowClassName) { @@ -311,7 +315,7 @@ export class BodyRow extends Component { let cell = ; + showRowReorderElement={this.props.showRowReorderElement} showSelectionElement={this.props.showSelectionElement} allowCellSelection={this.props.allowCellSelection} onClick={this.props.onCellClick} />; cells.push(cell); } diff --git a/src/components/datatable/DataTable.d.ts b/src/components/datatable/DataTable.d.ts index eebf4dd1ce..6cb8bf5186 100644 --- a/src/components/datatable/DataTable.d.ts +++ b/src/components/datatable/DataTable.d.ts @@ -12,11 +12,7 @@ declare namespace DataTable { type EmptyMessageType = React.ReactNode | ((frozen: boolean) => React.ReactNode); - type SelectionModeType = 'single' | 'multiple'; - - type RowSelectionModeType = 'new' | 'add' | 'checkbox' | 'radio'; - - type CellSelectionModeType = 'new' | 'add'; + type SelectionModeType = 'single' | 'multiple' | 'checkbox' | 'radioButton'; type ColumnResizeModeType = 'fit' | 'expand'; @@ -94,6 +90,16 @@ declare namespace DataTable { originalEvent: React.MouseEvent; } + interface CellClickEventParams { + originalEvent: React.MouseEvent; + value: any; + field: string; + rowData: any; + rowIndex: number; + cellIndex: number; + selected: boolean; + } + interface RowEditSaveParams extends RowEventParams { valid: boolean; } @@ -157,8 +163,6 @@ declare namespace DataTable { removableSort?: boolean; emptyMessage?: EmptyMessageType; selectionMode?: SelectionModeType; - rowSelectionMode?: RowSelectionModeType; - cellSelectionMode?: CellSelectionModeType; dragSelection?: boolean; cellSelection?: boolean; selection?: any | any[]; @@ -220,6 +224,7 @@ declare namespace DataTable { onRowUnselect?(e: UnselectParams): void; onRowExpand?(e: EventParams): void; onRowCollapse?(e: EventParams): void; + onCellClick?(e: CellClickEventParams): void; onCellSelect?(e: SelectParams): void; onCellUnselect?(e: UnselectParams): void; onContextMenu?(e: EventParams): void; diff --git a/src/components/datatable/DataTable.js b/src/components/datatable/DataTable.js index 6af701844e..030ae73d79 100644 --- a/src/components/datatable/DataTable.js +++ b/src/components/datatable/DataTable.js @@ -45,8 +45,6 @@ export class DataTable extends Component { removableSort: false, emptyMessage: null, selectionMode: null, - rowSelectionMode: 'new', - cellSelectionMode: 'new', dragSelection: false, cellSelection: false, selection: null, @@ -110,6 +108,7 @@ export class DataTable extends Component { onRowCollapse: null, onContextMenu: null, onColReorder: null, + onCellClick: null, onCellSelect: null, onCellUnselect: null, onRowReorder: null, @@ -158,8 +157,6 @@ export class DataTable extends Component { removableSort: PropTypes.bool, emptyMessage: PropTypes.any, selectionMode: PropTypes.string, - rowSelectionMode: PropTypes.string, - cellSelectionMode: PropTypes.string, dragSelection: PropTypes.bool, cellSelection: PropTypes.bool, selection: PropTypes.any, @@ -221,6 +218,7 @@ export class DataTable extends Component { onRowUnselect: PropTypes.func, onRowExpand: PropTypes.func, onRowCollapse: PropTypes.func, + onCellClick: PropTypes.func, onCellSelect: PropTypes.func, onCellUnselect: PropTypes.func, onContextMenu: PropTypes.func, @@ -1333,8 +1331,8 @@ export class DataTable extends Component { getSelectionModeInColumn(columns) { if (Array.isArray(columns)) { - for(let col of columns) { - if(col.props.selectionMode) + for (let col of columns) { + if (col.props.selectionMode) return col.props.selectionMode; } } @@ -1354,7 +1352,7 @@ export class DataTable extends Component { createTableBody(value, columns, frozen, selectionModeInColumn) { return + dragSelection={this.props.dragSelection} cellSelection={this.props.cellSelection} onCellClick={this.props.onCellClick} onCellSelect={this.props.onCellSelect} onCellUnselect={this.props.onCellUnselect}> {columns} ; } diff --git a/src/components/datatable/TableBody.js b/src/components/datatable/TableBody.js index e96ef23194..e51884cfc0 100644 --- a/src/components/datatable/TableBody.js +++ b/src/components/datatable/TableBody.js @@ -15,6 +15,8 @@ export class TableBody extends Component { this.onRowEditingToggle = this.onRowEditingToggle.bind(this); this.onRadioClick = this.onRadioClick.bind(this); this.onCheckboxClick = this.onCheckboxClick.bind(this); + this.onDragSelectionMouseMove = this.onDragSelectionMouseMove.bind(this); + this.onDragSelectionMouseUp = this.onDragSelectionMouseUp.bind(this); this.onRowDragEnd = this.onRowDragEnd.bind(this); this.onRowDragLeave = this.onRowDragLeave.bind(this); this.onRowDrop = this.onRowDrop.bind(this); @@ -26,67 +28,61 @@ export class TableBody extends Component { } onRowClick(event) { - if (this.props.cellSelection) { + if (this.allowCellSelection() || !this.allowSelection(event)) { return; } - let targetNode = event.originalEvent.target.nodeName; - if (targetNode === 'INPUT' || targetNode === 'BUTTON' || targetNode === 'A' || (DomHandler.hasClass(event.originalEvent.target, 'p-clickable'))) { - return; - } + this.props.onRowClick && this.props.onRowClick(event); - if (this.props.onRowClick) { - this.props.onRowClick(event); - } - - const allowRadioRowSelection = this.isRadioSelectionMode() && !this.isRadioRowSelectionMode(); - const allowCheckboxRowSelection = this.isCheckboxSelectionMode() && !this.isCheckboxRowSelectionMode(); - - if (this.props.selectionMode || allowRadioRowSelection || allowCheckboxRowSelection) { - if ((this.isMultipleSelectionMode() || allowCheckboxRowSelection) && event.originalEvent.shiftKey && this.anchorRowIndex !== null) { + if (this.allowRowSelection()) { + if (this.allowRangeSelection(event)) { this.onRangeSelection(event); } else { - let metaKey = !this.rowTouched && this.props.metaKeySelection && (event.originalEvent.metaKey || event.originalEvent.ctrlKey); + const toggleable = this.isRadioSelectionModeInColumn() || this.isCheckboxSelectionModeInColumn() || this.allowMetaKeySelection(event); this.anchorRowIndex = event.index; this.rangeRowIndex = event.index; this.anchorRowFirst = this.props.first; - if (this.isSingleSelectionMode() || this.isRadioSelectionMode()) { - this.onSingleSelection({ ...event, toggleable: metaKey, type: 'row' }); + if (this.isSingleSelection()) { + this.onSingleSelection({ ...event, toggleable, type: 'row' }); } else { - this.onMultipleSelection({ ...event, toggleable: metaKey, type: 'row' }); + this.onMultipleSelection({ ...event, toggleable, type: 'row' }); } } } + else { + this.focusOnElement(event.originalEvent); + } this.rowTouched = false; } onCellClick(event) { - let targetNode = event.originalEvent.target.nodeName; - if (targetNode === 'INPUT' || targetNode === 'BUTTON' || targetNode === 'A' || (DomHandler.hasClass(event.originalEvent.target, 'p-clickable'))) { + if (!this.allowSelection(event)) { return; } - if (this.props.selectionMode) { - if (this.isMultipleSelectionMode() && event.originalEvent.shiftKey && this.anchorRowIndex !== null) { + this.props.onCellClick && this.props.onCellClick(event); + + if (this.allowCellSelection()) { + if (this.allowRangeSelection(event)) { this.onRangeSelection(event); } else { - let metaKey = !this.rowTouched && this.props.metaKeySelection && (event.originalEvent.metaKey || event.originalEvent.ctrlKey); + let toggleable = this.allowMetaKeySelection(event); let { originalEvent, ...data } = event; this.anchorRowIndex = event.rowIndex; this.rangeRowIndex = event.rowIndex; this.anchorRowFirst = this.props.first; this.anchorCellIndex = event.cellIndex; - if (this.isSingleSelectionMode()) { - this.onSingleSelection({ originalEvent, data, toggleable: metaKey, type: 'cell' }); + if (this.isSingleSelection()) { + this.onSingleSelection({ originalEvent, data, toggleable, type: 'cell' }); } else { - this.onMultipleSelection({ originalEvent, data, toggleable: metaKey, type: 'cell' }); + this.onMultipleSelection({ originalEvent, data, toggleable, type: 'cell' }); } } } @@ -94,53 +90,8 @@ export class TableBody extends Component { this.rowTouched = false; } - onSelect(event) { - if (this.props.cellSelection) { - this.props.onCellSelect && this.props.onCellSelect({ originalEvent: event.originalEvent, ...event.data, type: event.type }); - } - else { - this.props.onRowSelect && this.props.onRowSelect(event); - } - } - - onUnselect(event) { - if (this.props.cellSelection) { - this.props.onCellUnselect && this.props.onCellUnselect({ originalEvent: event.originalEvent, ...event.data, type: event.type }); - } - else { - this.props.onRowUnselect && this.props.onRowUnselect(event); - } - } - - onRangeSelection(event) { - DomHandler.clearSelection(); - this.rangeRowIndex = this.props.cellSelection ? event.rowIndex : event.index; - let selectionInRange = this.selectRange(event); - let isAddSelectionMode = this.props.cellSelection ? this.isAddCellSelectionMode() : this.isAddRowSelectionMode(); - let selection = isAddSelectionMode ? [...new Set([...(this.props.selection || []), ...selectionInRange])] : selectionInRange; - let target = event.originalEvent.currentTarget; - - if (this.props.onSelectionChange && selection !== this.props.selection) { - this.props.onSelectionChange({ - originalEvent: event.originalEvent, - value: selection - }); - } - - this.anchorRowIndex = this.rangeRowIndex; - this.anchorCellIndex = event.cellIndex; - - if (this.isCheckboxSelectionMode() && !this.props.cellSelection) { - const checkbox = DomHandler.findSingle(target, 'td.p-selection-column .p-checkbox-box'); - checkbox && checkbox.focus(); - } - else { - target && target.focus(); - } - } - onSingleSelection({ originalEvent, data, toggleable, type }) { - let selected = this.props.cellSelection ? data.selected : this.isSelected(data); + let selected = this.isSelected(data); let selection = this.props.selection; if (selected) { @@ -154,13 +105,7 @@ export class TableBody extends Component { this.onSelect({ originalEvent, data, type }); } - if (this.isRadioSelectionMode() && !this.props.cellSelection) { - const target = originalEvent.currentTarget; - const radio = DomHandler.findSingle(target, 'td.p-selection-column input[type="radio"]'); - if (radio) { - radio.focus(); - } - } + this.focusOnElement(originalEvent, true); if (this.props.onSelectionChange && selection !== this.props.selection) { this.props.onSelectionChange({ @@ -171,10 +116,8 @@ export class TableBody extends Component { } onMultipleSelection({ originalEvent, data, toggleable, type }) { - let selected = this.props.cellSelection ? data.selected : this.isSelected(data); - let selection = this.props.selection; - const isNewSelectionMode = this.props.cellSelection ? this.isNewCellSelectionMode() : this.isNewRowSelectionMode(); - const isAddSelectionMode = this.props.cellSelection ? this.isAddCellSelectionMode() : this.isAddRowSelectionMode(); + let selected = this.isSelected(data); + let selection = this.props.selection || []; if (selected) { if (toggleable) { @@ -182,24 +125,18 @@ export class TableBody extends Component { selection = this.props.selection.filter((val, i) => i !== selectionIndex); this.onUnselect({ originalEvent, data, type }); } - else if (isNewSelectionMode) { - (this.props.selection || []).forEach(d => this.onUnselect({ originalEvent, data: d, type })); + else if (selection.length) { + this.props.selection.forEach(d => this.onUnselect({ originalEvent, data: d, type })); selection = [data]; this.onSelect({ originalEvent, data, type }); } } else { - selection = toggleable || isAddSelectionMode ? [...selection || [], data] : [data]; + selection = toggleable && this.isMultipleSelection() ? [...selection, data] : [data]; this.onSelect({ originalEvent, data, type }); } - if (this.isCheckboxSelectionMode() && !this.props.cellSelection) { - const target = originalEvent.currentTarget; - const checkbox = DomHandler.findSingle(target, 'td.p-selection-column .p-checkbox-box'); - if (checkbox) { - checkbox.focus(); - } - } + this.focusOnElement(originalEvent, true); if (this.props.onSelectionChange && selection !== this.props.selection) { this.props.onSelectionChange({ @@ -209,6 +146,25 @@ export class TableBody extends Component { } } + onRangeSelection(event) { + DomHandler.clearSelection(); + this.rangeRowIndex = this.allowCellSelection() ? event.rowIndex : event.index; + let selectionInRange = this.selectRange(event); + let selection = this.isMultipleSelection() ? [...new Set([...(this.props.selection || []), ...selectionInRange])] : selectionInRange; + + if (this.props.onSelectionChange && selection !== this.props.selection) { + this.props.onSelectionChange({ + originalEvent: event.originalEvent, + value: selection + }); + } + + this.anchorRowIndex = this.rangeRowIndex; + this.anchorCellIndex = event.cellIndex; + + this.focusOnElement(event.originalEvent, false); + } + selectRange(event) { let rangeStart, rangeEnd; let isLazyAndPaginator = this.props.lazy && this.props.paginator; @@ -235,7 +191,7 @@ export class TableBody extends Component { rangeEnd -= this.props.first; } - return this.props.cellSelection ? this.selectRangeOnCell(event, rangeStart, rangeEnd) : this.selectRangeOnRow(event, rangeStart, rangeEnd); + return this.allowCellSelection() ? this.selectRangeOnCell(event, rangeStart, rangeEnd) : this.selectRangeOnRow(event, rangeStart, rangeEnd); } selectRangeOnRow(event, rowRangeStart, rowRangeEnd) { @@ -289,58 +245,71 @@ export class TableBody extends Component { this.onSelect({ originalEvent: event.originalEvent, data: rangeRowData, type: 'cell' }); } } + return selection; } + onSelect(event) { + if (this.allowCellSelection()) + this.props.onCellSelect && this.props.onCellSelect({ originalEvent: event.originalEvent, ...event.data, type: event.type }); + else + this.props.onRowSelect && this.props.onRowSelect(event); + } + + onUnselect(event) { + if (this.allowCellSelection()) + this.props.onCellUnselect && this.props.onCellUnselect({ originalEvent: event.originalEvent, ...event.data, type: event.type }); + else + this.props.onRowUnselect && this.props.onRowUnselect(event); + } + enableDragSelection(event) { if (this.props.dragSelection && !this.dragSelectionHelper) { this.dragSelectionHelper = document.createElement('div'); DomHandler.addClass(this.dragSelectionHelper, 'p-datatable-drag-selection-helper'); - const currentX = event.clientX; - const currentY = event.clientY; - + this.initialDragPosition = { x: event.clientX, y: event.clientY }; this.dragSelectionHelper.style.top = `${event.pageY}px`; this.dragSelectionHelper.style.left = `${event.pageX}px`; - let dragSelectionMouseMove = (e) => { - const dx = e.clientX - currentX; - const dy = e.clientY - currentY; + this.bindDragSelectionEvents(); + } + } - if (dy < 0) - this.dragSelectionHelper.style.top = `${e.pageY}px`; - if (dx < 0) - this.dragSelectionHelper.style.left = `${e.pageX}px`; + bindDragSelectionEvents() { + document.addEventListener('mousemove', this.onDragSelectionMouseMove); + document.addEventListener('mouseup', this.onDragSelectionMouseUp); + document.body.appendChild(this.dragSelectionHelper); + } - this.dragSelectionHelper.style.height = `${Math.abs(dy)}px`; - this.dragSelectionHelper.style.width = `${Math.abs(dx)}px`; + unbindDragSelectionEvents() { + this.onDragSelectionMouseUp(); + } - e.preventDefault(); - }; + onDragSelectionMouseMove(event) { + const { x, y } = this.initialDragPosition; + const dx = event.clientX - x; + const dy = event.clientY - y; - let dragSelectionMouseUp = () => { - if (this.dragSelectionHelper) { - this.dragSelectionHelper.remove(); - this.dragSelectionHelper = null; - } + if (dy < 0) + this.dragSelectionHelper.style.top = `${event.pageY + 5}px`; + if (dx < 0) + this.dragSelectionHelper.style.left = `${event.pageX + 5}px`; - document.removeEventListener('mousemove', dragSelectionMouseMove); - document.removeEventListener('mouseup', dragSelectionMouseUp); - dragSelectionMouseMove = dragSelectionMouseUp = null; - }; + this.dragSelectionHelper.style.height = `${Math.abs(dy)}px`; + this.dragSelectionHelper.style.width = `${Math.abs(dx)}px`; - document.addEventListener('mousemove', dragSelectionMouseMove); - document.addEventListener('mouseup', dragSelectionMouseUp); - document.body.appendChild(this.dragSelectionHelper); - } + event.preventDefault(); } - allowRowDrag(event) { - return this.props.dragSelection && !this.props.cellSelection && this.isMultipleSelectionMode() && !event.originalEvent.shiftKey; - } + onDragSelectionMouseUp() { + if (this.dragSelectionHelper) { + this.dragSelectionHelper.remove(); + this.dragSelectionHelper = null; + } - allowCellDrag(event) { - return this.props.dragSelection && this.props.cellSelection && this.isMultipleSelectionMode() && !event.originalEvent.shiftKey; + document.removeEventListener('mousemove', this.onDragSelectionMouseMove); + document.removeEventListener('mouseup', this.onDragSelectionMouseUp); } onRowMouseDown(event) { @@ -412,52 +381,80 @@ export class TableBody extends Component { this.onMultipleSelection({ ...event, toggleable: true, type: 'checkbox' }); } - isSingleSelectionMode() { - return this.props.selectionMode === 'single'; + allowDrag(event) { + return this.props.dragSelection && this.isMultipleSelection() && !event.originalEvent.shiftKey; + } + + allowRowDrag(event) { + return !this.allowCellSelection() && this.allowDrag(event); + } + + allowCellDrag(event) { + return this.allowCellSelection() && this.allowDrag(event); + } + + allowSelection(event) { + let targetNode = event.originalEvent.target.nodeName; + if (targetNode === 'INPUT' || targetNode === 'BUTTON' || targetNode === 'A' || (DomHandler.hasClass(event.originalEvent.target, 'p-clickable'))) { + return false; + } + + return true; + } + + allowMetaKeySelection(event) { + return !this.rowTouched && (!this.props.metaKeySelection || (this.props.metaKeySelection && (event.originalEvent.metaKey || event.originalEvent.ctrlKey))) + } + + allowRangeSelection(event) { + return this.isMultipleSelection() && event.originalEvent.shiftKey && this.anchorRowIndex !== null; + } + + allowRowSelection() { + return (this.props.selectionMode || this.props.selectionModeInColumn) && !this.isRadioOnlySelection() && !this.isCheckboxOnlySelection(); } - isMultipleSelectionMode() { - return this.props.selectionMode === 'multiple'; + allowCellSelection() { + return this.props.cellSelection && !this.isRadioSelectionModeInColumn() && !this.isCheckboxSelectionModeInColumn(); } isRadioSelectionMode() { - return this.props.selectionModeInColumn === 'single'; + return this.props.selectionMode === 'radioButton'; } isCheckboxSelectionMode() { - return this.props.selectionModeInColumn === 'multiple'; + return this.props.selectionMode === 'checkbox'; } - isNewRowSelectionMode() { - return this.props.rowSelectionMode === 'new'; + isRadioSelectionModeInColumn() { + return this.props.selectionModeInColumn === 'single'; } - isAddRowSelectionMode() { - return this.props.rowSelectionMode === 'add'; + isCheckboxSelectionModeInColumn() { + return this.props.selectionModeInColumn === 'multiple'; } - isRadioRowSelectionMode() { - return this.props.rowSelectionMode === 'radio'; + isSingleSelection() { + return (this.props.selectionMode === 'single' && !this.isCheckboxSelectionModeInColumn()) || + (!this.isRadioSelectionMode() && this.isRadioSelectionModeInColumn()); } - isCheckboxRowSelectionMode() { - return this.props.rowSelectionMode === 'checkbox'; + isMultipleSelection() { + return (this.props.selectionMode === 'multiple' && !this.isRadioSelectionModeInColumn()) || + (!this.isCheckboxSelectionMode() && this.isCheckboxSelectionModeInColumn()); } - isNewCellSelectionMode() { - return this.props.cellSelectionMode === 'new'; + isRadioOnlySelection() { + return this.isRadioSelectionMode() && this.isRadioSelectionModeInColumn(); } - isAddCellSelectionMode() { - return this.props.cellSelectionMode === 'add'; + isCheckboxOnlySelection() { + return this.isCheckboxSelectionMode() && this.isCheckboxSelectionModeInColumn(); } isSelected(rowData) { if (rowData && this.props.selection) { - if (this.props.selection instanceof Array) - return this.findIndexInSelection(rowData) > -1; - else - return this.equals(rowData, this.props.selection); + return (this.props.selection instanceof Array) ? this.findIndexInSelection(rowData) > -1 : this.equals(rowData, this.props.selection); } return false; @@ -471,27 +468,32 @@ export class TableBody extends Component { return false; } - equals(data1, data2) { - return this.compareSelectionBy === 'equals' ? (data1 === data2) : ObjectUtils.equals(data1, data2, this.props.dataKey); + focusOnElement(event, isFocused) { + const target = event.currentTarget; + + if (!this.allowCellSelection()) { + if (this.isCheckboxSelectionModeInColumn()) { + const checkbox = DomHandler.findSingle(target, 'td.p-selection-column .p-checkbox-box'); + checkbox && checkbox.focus(); + } + else if (this.isRadioSelectionModeInColumn()) { + const radio = DomHandler.findSingle(target, 'td.p-selection-column input[type="radio"]'); + radio && radio.focus(); + } + } + + !isFocused && target && target.focus(); } - equalsByCell(data1, data2) { - return (data1.rowIndex === data2.rowIndex || data1.rowData === data2.rowData) && (data1.field === data2.field || data1.cellIndex === data2.cellIndex); + equals(data1, data2) { + if (this.allowCellSelection()) + return (data1.rowIndex === data2.rowIndex || data1.rowData === data2.rowData) && (data1.field === data2.field || data1.cellIndex === data2.cellIndex) + else + return this.compareSelectionBy === 'equals' ? (data1 === data2) : ObjectUtils.equals(data1, data2, this.props.dataKey); } findIndexInSelection(data) { - let index = -1; - if (this.props.selection) { - for (let i = 0; i < this.props.selection.length; i++) { - const isEquals = this.props.cellSelection ? this.equalsByCell(data, this.props.selection[i]) : this.equals(data, this.props.selection[i]); - if (isEquals) { - index = i; - break; - } - } - } - - return index; + return this.props.selection ? this.props.selection.findIndex(d => this.equals(data, d)) : -1; } onRowToggle(event) { @@ -541,12 +543,7 @@ export class TableBody extends Component { } findRowIndex(rows, row) { - let index = -1; - if (rows) { - rows.some((r, i) => (ObjectUtils.equals(rows[i], row) ? (index = i, true) : false)); - } - - return index; + return rows ? rows.findIndex(r => ObjectUtils.equals(row, r)) : -1; } isRowExpanded(row) { @@ -700,6 +697,12 @@ export class TableBody extends Component { this.onRowDragEnd(event); } + componentWillUnmount() { + if (this.props.dragSelection) { + this.unbindDragSelectionEvents(); + } + } + renderRowGroupHeader(rowData, index) { let content = null; @@ -801,9 +804,9 @@ export class TableBody extends Component { onDrop={this.onRowDrop} virtualScroll={this.props.virtualScroll} virtualRowHeight={this.props.virtualRowHeight} editMode={this.props.editMode} editing={editing} isRowEditingControlled={!!this.props.onRowEditChange} rowEditorValidator={this.props.rowEditorValidator} onRowEditInit={this.props.onRowEditInit} onRowEditSave={this.props.onRowEditSave} onRowEditCancel={this.props.onRowEditCancel} onRowEditingToggle={this.onRowEditingToggle} - showRowReorderElement={this.props.showRowReorderElement} showSelectionElement={this.props.showSelectionElement} metaKeySelection={this.props.metaKeySelection} onSelectionChange={this.props.onSelectionChange} - selectionModeInColumn={this.props.selectionModeInColumn} rowSelectionMode={this.props.rowSelectionMode} dragSelection={this.props.dragSelection} - selection={this.props.selection} cellSelection={this.props.cellSelection} onCellClick={this.onCellClick}> + showRowReorderElement={this.props.showRowReorderElement} showSelectionElement={this.props.showSelectionElement} onSelectionChange={this.props.onSelectionChange} + selectionModeInColumn={this.props.selectionModeInColumn} dragSelection={this.props.dragSelection} selection={this.props.selection} + allowRowSelection={this.allowRowSelection()} allowCellSelection={this.allowCellSelection()} onCellClick={this.onCellClick}> {this.props.children}