526 lines
16 KiB
JavaScript
526 lines
16 KiB
JavaScript
'use strict';
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
|
|
var _getIterator2 = require('babel-runtime/core-js/get-iterator');
|
|
|
|
var _getIterator3 = _interopRequireDefault(_getIterator2);
|
|
|
|
var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray');
|
|
|
|
var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2);
|
|
|
|
var _typeof2 = require('babel-runtime/helpers/typeof');
|
|
|
|
var _typeof3 = _interopRequireDefault(_typeof2);
|
|
|
|
var _extends2 = require('babel-runtime/helpers/extends');
|
|
|
|
var _extends3 = _interopRequireDefault(_extends2);
|
|
|
|
var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
|
|
|
|
var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
|
|
|
|
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
|
|
|
|
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
|
|
|
|
var _createClass2 = require('babel-runtime/helpers/createClass');
|
|
|
|
var _createClass3 = _interopRequireDefault(_createClass2);
|
|
|
|
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
|
|
|
|
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
|
|
|
|
var _inherits2 = require('babel-runtime/helpers/inherits');
|
|
|
|
var _inherits3 = _interopRequireDefault(_inherits2);
|
|
|
|
var _simpleAssign = require('simple-assign');
|
|
|
|
var _simpleAssign2 = _interopRequireDefault(_simpleAssign);
|
|
|
|
var _react = require('react');
|
|
|
|
var _react2 = _interopRequireDefault(_react);
|
|
|
|
var _Checkbox = require('../Checkbox');
|
|
|
|
var _Checkbox2 = _interopRequireDefault(_Checkbox);
|
|
|
|
var _TableRowColumn = require('./TableRowColumn');
|
|
|
|
var _TableRowColumn2 = _interopRequireDefault(_TableRowColumn);
|
|
|
|
var _ClickAwayListener = require('../internal/ClickAwayListener');
|
|
|
|
var _ClickAwayListener2 = _interopRequireDefault(_ClickAwayListener);
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
var TableBody = function (_Component) {
|
|
(0, _inherits3.default)(TableBody, _Component);
|
|
|
|
function TableBody() {
|
|
var _ref;
|
|
|
|
var _temp, _this, _ret;
|
|
|
|
(0, _classCallCheck3.default)(this, TableBody);
|
|
|
|
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
|
|
args[_key] = arguments[_key];
|
|
}
|
|
|
|
return _ret = (_temp = (_this = (0, _possibleConstructorReturn3.default)(this, (_ref = TableBody.__proto__ || (0, _getPrototypeOf2.default)(TableBody)).call.apply(_ref, [this].concat(args))), _this), _this.state = {
|
|
selectedRows: []
|
|
}, _this.handleClickAway = function () {
|
|
if (_this.props.deselectOnClickaway && _this.state.selectedRows.length) {
|
|
_this.setState({
|
|
selectedRows: []
|
|
});
|
|
if (_this.props.onRowSelection) {
|
|
_this.props.onRowSelection([]);
|
|
}
|
|
}
|
|
}, _this.onRowClick = function (event, rowNumber) {
|
|
event.stopPropagation();
|
|
|
|
if (_this.props.selectable) {
|
|
// Prevent text selection while selecting rows.
|
|
window.getSelection().removeAllRanges();
|
|
_this.processRowSelection(event, rowNumber);
|
|
}
|
|
}, _this.onCellClick = function (event, rowNumber, columnNumber) {
|
|
event.stopPropagation();
|
|
if (_this.props.onCellClick) {
|
|
_this.props.onCellClick(rowNumber, _this.getColumnId(columnNumber), event);
|
|
}
|
|
}, _this.onCellHover = function (event, rowNumber, columnNumber) {
|
|
if (_this.props.onCellHover) {
|
|
_this.props.onCellHover(rowNumber, _this.getColumnId(columnNumber), event);
|
|
}
|
|
_this.onRowHover(event, rowNumber);
|
|
}, _this.onCellHoverExit = function (event, rowNumber, columnNumber) {
|
|
if (_this.props.onCellHoverExit) {
|
|
_this.props.onCellHoverExit(rowNumber, _this.getColumnId(columnNumber), event);
|
|
}
|
|
_this.onRowHoverExit(event, rowNumber);
|
|
}, _this.onRowHover = function (event, rowNumber) {
|
|
if (_this.props.onRowHover) {
|
|
_this.props.onRowHover(rowNumber);
|
|
}
|
|
}, _this.onRowHoverExit = function (event, rowNumber) {
|
|
if (_this.props.onRowHoverExit) {
|
|
_this.props.onRowHoverExit(rowNumber);
|
|
}
|
|
}, _temp), (0, _possibleConstructorReturn3.default)(_this, _ret);
|
|
}
|
|
|
|
(0, _createClass3.default)(TableBody, [{
|
|
key: 'componentWillMount',
|
|
value: function componentWillMount() {
|
|
this.setState({ selectedRows: this.calculatePreselectedRows(this.props) });
|
|
}
|
|
}, {
|
|
key: 'componentWillReceiveProps',
|
|
value: function componentWillReceiveProps(nextProps) {
|
|
if (this.props.allRowsSelected !== nextProps.allRowsSelected) {
|
|
if (!nextProps.allRowsSelected) {
|
|
this.setState({
|
|
selectedRows: []
|
|
});
|
|
} else {
|
|
this.setState({
|
|
selectedRows: this.calculatePreselectedRows(nextProps)
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}, {
|
|
key: 'createRows',
|
|
value: function createRows() {
|
|
var _this2 = this;
|
|
|
|
var numChildren = _react2.default.Children.count(this.props.children);
|
|
var rowNumber = 0;
|
|
var handlers = {
|
|
onCellClick: this.onCellClick,
|
|
onCellHover: this.onCellHover,
|
|
onCellHoverExit: this.onCellHoverExit,
|
|
onRowHover: this.onRowHover,
|
|
onRowHoverExit: this.onRowHoverExit,
|
|
onRowClick: this.onRowClick
|
|
};
|
|
|
|
return _react2.default.Children.map(this.props.children, function (child) {
|
|
if (_react2.default.isValidElement(child)) {
|
|
var _ret2 = function () {
|
|
var props = {
|
|
hoverable: _this2.props.showRowHover,
|
|
selected: _this2.isRowSelected(rowNumber),
|
|
striped: _this2.props.stripedRows && rowNumber % 2 === 0,
|
|
rowNumber: rowNumber++
|
|
};
|
|
|
|
if (rowNumber === numChildren) {
|
|
props.displayBorder = false;
|
|
}
|
|
|
|
var children = [_this2.createRowCheckboxColumn(props)];
|
|
|
|
_react2.default.Children.forEach(child.props.children, function (child) {
|
|
children.push(child);
|
|
});
|
|
|
|
return {
|
|
v: _react2.default.cloneElement(child, (0, _extends3.default)({}, props, handlers), children)
|
|
};
|
|
}();
|
|
|
|
if ((typeof _ret2 === 'undefined' ? 'undefined' : (0, _typeof3.default)(_ret2)) === "object") return _ret2.v;
|
|
}
|
|
});
|
|
}
|
|
}, {
|
|
key: 'createRowCheckboxColumn',
|
|
value: function createRowCheckboxColumn(rowProps) {
|
|
if (!this.props.displayRowCheckbox) {
|
|
return null;
|
|
}
|
|
|
|
var key = rowProps.rowNumber + '-cb';
|
|
var disabled = !this.props.selectable;
|
|
var checkbox = _react2.default.createElement(_Checkbox2.default, {
|
|
ref: 'rowSelectCB',
|
|
name: key,
|
|
value: 'selected',
|
|
disabled: disabled,
|
|
checked: rowProps.selected
|
|
});
|
|
|
|
return _react2.default.createElement(
|
|
_TableRowColumn2.default,
|
|
{
|
|
key: key,
|
|
columnNumber: 0,
|
|
style: {
|
|
width: 24,
|
|
cursor: disabled ? 'not-allowed' : 'inherit'
|
|
}
|
|
},
|
|
checkbox
|
|
);
|
|
}
|
|
}, {
|
|
key: 'calculatePreselectedRows',
|
|
value: function calculatePreselectedRows(props) {
|
|
// Determine what rows are 'pre-selected'.
|
|
var preSelectedRows = [];
|
|
|
|
if (props.selectable && props.preScanRows) {
|
|
(function () {
|
|
var index = 0;
|
|
_react2.default.Children.forEach(props.children, function (child) {
|
|
if (_react2.default.isValidElement(child)) {
|
|
if (child.props.selected && (preSelectedRows.length === 0 || props.multiSelectable)) {
|
|
preSelectedRows.push(index);
|
|
}
|
|
|
|
index++;
|
|
}
|
|
});
|
|
})();
|
|
}
|
|
|
|
return preSelectedRows;
|
|
}
|
|
}, {
|
|
key: 'isRowSelected',
|
|
value: function isRowSelected(rowNumber) {
|
|
if (this.props.allRowsSelected) {
|
|
return true;
|
|
}
|
|
|
|
for (var i = 0; i < this.state.selectedRows.length; i++) {
|
|
var selection = this.state.selectedRows[i];
|
|
|
|
if ((typeof selection === 'undefined' ? 'undefined' : (0, _typeof3.default)(selection)) === 'object') {
|
|
if (this.isValueInRange(rowNumber, selection)) return true;
|
|
} else {
|
|
if (selection === rowNumber) return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}, {
|
|
key: 'isValueInRange',
|
|
value: function isValueInRange(value, range) {
|
|
if (!range) return false;
|
|
|
|
if (range.start <= value && value <= range.end || range.end <= value && value <= range.start) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}, {
|
|
key: 'processRowSelection',
|
|
value: function processRowSelection(event, rowNumber) {
|
|
var selectedRows = this.state.selectedRows;
|
|
|
|
if (event.shiftKey && this.props.multiSelectable && selectedRows.length) {
|
|
var lastIndex = selectedRows.length - 1;
|
|
var lastSelection = selectedRows[lastIndex];
|
|
|
|
if ((typeof lastSelection === 'undefined' ? 'undefined' : (0, _typeof3.default)(lastSelection)) === 'object') {
|
|
lastSelection.end = rowNumber;
|
|
} else {
|
|
selectedRows.splice(lastIndex, 1, { start: lastSelection, end: rowNumber });
|
|
}
|
|
} else if ((event.ctrlKey && !event.metaKey || event.metaKey && !event.ctrlKey) && this.props.multiSelectable) {
|
|
var idx = selectedRows.indexOf(rowNumber);
|
|
if (idx < 0) {
|
|
var foundRange = false;
|
|
for (var i = 0; i < selectedRows.length; i++) {
|
|
var range = selectedRows[i];
|
|
if ((typeof range === 'undefined' ? 'undefined' : (0, _typeof3.default)(range)) !== 'object') continue;
|
|
|
|
if (this.isValueInRange(rowNumber, range)) {
|
|
var _selectedRows;
|
|
|
|
foundRange = true;
|
|
var values = this.splitRange(range, rowNumber);
|
|
(_selectedRows = selectedRows).splice.apply(_selectedRows, [i, 1].concat((0, _toConsumableArray3.default)(values)));
|
|
}
|
|
}
|
|
|
|
if (!foundRange) selectedRows.push(rowNumber);
|
|
} else {
|
|
selectedRows.splice(idx, 1);
|
|
}
|
|
} else {
|
|
if (selectedRows.length === 1 && selectedRows[0] === rowNumber) {
|
|
selectedRows = [];
|
|
} else {
|
|
selectedRows = [rowNumber];
|
|
}
|
|
}
|
|
|
|
this.setState({ selectedRows: selectedRows });
|
|
if (this.props.onRowSelection) this.props.onRowSelection(this.flattenRanges(selectedRows));
|
|
}
|
|
}, {
|
|
key: 'splitRange',
|
|
value: function splitRange(range, splitPoint) {
|
|
var splitValues = [];
|
|
var startOffset = range.start - splitPoint;
|
|
var endOffset = range.end - splitPoint;
|
|
|
|
// Process start half
|
|
splitValues.push.apply(splitValues, (0, _toConsumableArray3.default)(this.genRangeOfValues(splitPoint, startOffset)));
|
|
|
|
// Process end half
|
|
splitValues.push.apply(splitValues, (0, _toConsumableArray3.default)(this.genRangeOfValues(splitPoint, endOffset)));
|
|
|
|
return splitValues;
|
|
}
|
|
}, {
|
|
key: 'genRangeOfValues',
|
|
value: function genRangeOfValues(start, offset) {
|
|
var values = [];
|
|
var dir = offset > 0 ? -1 : 1; // This forces offset to approach 0 from either direction.
|
|
while (offset !== 0) {
|
|
values.push(start + offset);
|
|
offset += dir;
|
|
}
|
|
|
|
return values;
|
|
}
|
|
}, {
|
|
key: 'flattenRanges',
|
|
value: function flattenRanges(selectedRows) {
|
|
var rows = [];
|
|
var _iteratorNormalCompletion = true;
|
|
var _didIteratorError = false;
|
|
var _iteratorError = undefined;
|
|
|
|
try {
|
|
for (var _iterator = (0, _getIterator3.default)(selectedRows), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
|
var selection = _step.value;
|
|
|
|
if ((typeof selection === 'undefined' ? 'undefined' : (0, _typeof3.default)(selection)) === 'object') {
|
|
var values = this.genRangeOfValues(selection.end, selection.start - selection.end);
|
|
rows.push.apply(rows, [selection.end].concat((0, _toConsumableArray3.default)(values)));
|
|
} else {
|
|
rows.push(selection);
|
|
}
|
|
}
|
|
} catch (err) {
|
|
_didIteratorError = true;
|
|
_iteratorError = err;
|
|
} finally {
|
|
try {
|
|
if (!_iteratorNormalCompletion && _iterator.return) {
|
|
_iterator.return();
|
|
}
|
|
} finally {
|
|
if (_didIteratorError) {
|
|
throw _iteratorError;
|
|
}
|
|
}
|
|
}
|
|
|
|
return rows.sort();
|
|
}
|
|
}, {
|
|
key: 'getColumnId',
|
|
value: function getColumnId(columnNumber) {
|
|
var columnId = columnNumber;
|
|
if (this.props.displayRowCheckbox) {
|
|
columnId--;
|
|
}
|
|
|
|
return columnId;
|
|
}
|
|
}, {
|
|
key: 'render',
|
|
value: function render() {
|
|
var _props = this.props,
|
|
className = _props.className,
|
|
style = _props.style;
|
|
var prepareStyles = this.context.muiTheme.prepareStyles;
|
|
|
|
|
|
return _react2.default.createElement(
|
|
_ClickAwayListener2.default,
|
|
{ onClickAway: this.handleClickAway },
|
|
_react2.default.createElement(
|
|
'tbody',
|
|
{ className: className, style: prepareStyles((0, _simpleAssign2.default)({}, style)) },
|
|
this.createRows()
|
|
)
|
|
);
|
|
}
|
|
}]);
|
|
return TableBody;
|
|
}(_react.Component);
|
|
|
|
TableBody.muiName = 'TableBody';
|
|
TableBody.defaultProps = {
|
|
allRowsSelected: false,
|
|
deselectOnClickaway: true,
|
|
displayRowCheckbox: true,
|
|
multiSelectable: false,
|
|
preScanRows: true,
|
|
selectable: true,
|
|
style: {}
|
|
};
|
|
TableBody.contextTypes = {
|
|
muiTheme: _react.PropTypes.object.isRequired
|
|
};
|
|
process.env.NODE_ENV !== "production" ? TableBody.propTypes = {
|
|
/**
|
|
* @ignore
|
|
* Set to true to indicate that all rows should be selected.
|
|
*/
|
|
allRowsSelected: _react.PropTypes.bool,
|
|
/**
|
|
* Children passed to table body.
|
|
*/
|
|
children: _react.PropTypes.node,
|
|
/**
|
|
* The css class name of the root element.
|
|
*/
|
|
className: _react.PropTypes.string,
|
|
/**
|
|
* Controls whether or not to deselect all selected
|
|
* rows after clicking outside the table.
|
|
*/
|
|
deselectOnClickaway: _react.PropTypes.bool,
|
|
/**
|
|
* Controls the display of the row checkbox. The default value is true.
|
|
*/
|
|
displayRowCheckbox: _react.PropTypes.bool,
|
|
/**
|
|
* @ignore
|
|
* If true, multiple table rows can be selected.
|
|
* CTRL/CMD+Click and SHIFT+Click are valid actions.
|
|
* The default value is false.
|
|
*/
|
|
multiSelectable: _react.PropTypes.bool,
|
|
/**
|
|
* @ignore
|
|
* Callback function for when a cell is clicked.
|
|
*/
|
|
onCellClick: _react.PropTypes.func,
|
|
/**
|
|
* @ignore
|
|
* Called when a table cell is hovered. rowNumber
|
|
* is the row number of the hovered row and columnId
|
|
* is the column number or the column key of the cell.
|
|
*/
|
|
onCellHover: _react.PropTypes.func,
|
|
/**
|
|
* @ignore
|
|
* Called when a table cell is no longer hovered.
|
|
* rowNumber is the row number of the row and columnId
|
|
* is the column number or the column key of the cell.
|
|
*/
|
|
onCellHoverExit: _react.PropTypes.func,
|
|
/**
|
|
* @ignore
|
|
* Called when a table row is hovered.
|
|
* rowNumber is the row number of the hovered row.
|
|
*/
|
|
onRowHover: _react.PropTypes.func,
|
|
/**
|
|
* @ignore
|
|
* Called when a table row is no longer
|
|
* hovered. rowNumber is the row number of the row
|
|
* that is no longer hovered.
|
|
*/
|
|
onRowHoverExit: _react.PropTypes.func,
|
|
/**
|
|
* @ignore
|
|
* Called when a row is selected. selectedRows is an
|
|
* array of all row selections. IF all rows have been selected,
|
|
* the string "all" will be returned instead to indicate that
|
|
* all rows have been selected.
|
|
*/
|
|
onRowSelection: _react.PropTypes.func,
|
|
/**
|
|
* Controls whether or not the rows are pre-scanned to determine
|
|
* initial state. If your table has a large number of rows and
|
|
* you are experiencing a delay in rendering, turn off this property.
|
|
*/
|
|
preScanRows: _react.PropTypes.bool,
|
|
/**
|
|
* @ignore
|
|
* If true, table rows can be selected. If multiple
|
|
* row selection is desired, enable multiSelectable.
|
|
* The default value is true.
|
|
*/
|
|
selectable: _react.PropTypes.bool,
|
|
/**
|
|
* If true, table rows will be highlighted when
|
|
* the cursor is hovering over the row. The default
|
|
* value is false.
|
|
*/
|
|
showRowHover: _react.PropTypes.bool,
|
|
/**
|
|
* If true, every other table row starting
|
|
* with the first row will be striped. The default value is false.
|
|
*/
|
|
stripedRows: _react.PropTypes.bool,
|
|
/**
|
|
* Override the inline-styles of the root element.
|
|
*/
|
|
style: _react.PropTypes.object
|
|
} : void 0;
|
|
exports.default = TableBody; |