@beisen/ethos
Version:
beisencloud pc react components
849 lines (706 loc) • 25.3 kB
JavaScript
'use strict';
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
var _typeof2 = require('babel-runtime/helpers/typeof');
var _typeof3 = _interopRequireDefault(_typeof2);
var _commonFunc = require('../../common-func');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var React = require('react');
var Region = require('region');
var ReactDOM = require('react-dom');
var ReactMenu = React.createFactory(require('react-menus'));
var assign = require('object-assign');
var clone = require('clone');
var asArray = require('../utils/asArray');
var findIndexBy = require('../utils/findIndexBy');
var findIndexByName = require('../utils/findIndexByName');
var Cell = require('../Cell');
var setupColumnDrag = require('./setupColumnDrag');
var setupColumnResize = require('./setupColumnResize');
var ToolTip = require('../../tool-tip');
var normalize = require('react-style-normalizer');
function emptyFn() {}
function getColumnSortInfo(column, sortInfo) {
sortInfo = asArray(sortInfo);
var index = findIndexBy(sortInfo, function (info) {
return info.name === column.name;
});
return sortInfo[index];
}
function removeColumnSort(column, sortInfo) {
sortInfo = asArray(sortInfo);
var index = findIndexBy(sortInfo, function (info) {
return info.name === column.name;
});
if (~index) {
sortInfo.splice(index, 1);
}
return sortInfo;
}
function getDropState() {
return {
dragLeft: null,
dragColumn: null,
dragColumnIndex: null,
dragging: false,
dropIndex: null,
shiftIndexes: null,
shiftSize: null
};
}
module.exports = React.createClass({
displayName: 'ReactDataGrid.Header',
propTypes: {
columns: React.PropTypes.array
},
shouldComponentUpdate: function shouldComponentUpdate(nextProps, nextState) {
return true;
},
onDrop: function onDrop(event) {
var state = this.state;
var props = this.props;
if (state.dragging) {
// event.stopPropagation()
// wuzhe----ie10兼容
if (event.stopPropagation) {
// this code is for Mozilla and Opera
event.stopPropagation();
} else if (window.event) {
// this code is for IE
window.event.cancelBubble = true;
}
}
var dragIndex = state.dragColumnIndex;
var dropIndex = state.dropIndex;
if (dropIndex != null) {
//since we need the indexes in the array of all columns
//not only in the array of the visible columns
//we need to search them and make this transform
var dragColumn = props.columns[dragIndex];
var dropColumn = props.columns[dropIndex];
dragIndex = findIndexByName(props.allColumns, dragColumn.name);
dropIndex = findIndexByName(props.allColumns, dropColumn.name);
this.props.onDropColumn(dragIndex, dropIndex);
}
this.setState(getDropState());
},
getDefaultProps: function getDefaultProps() {
return {
defaultClassName: 'z-header-wrapper',
draggingClassName: 'z-dragging',
cellClassName: 'z-column-header',
mainClassName: 'main',
defaultStyle: {},
sortInfo: null,
scrollLeft: 0,
scrollTop: 0
};
},
getInitialState: function getInitialState() {
return {
mouseOver: true,
dragging: false,
shiftSize: null,
dragColumn: null,
shiftIndexes: null,
resizeHover: false
};
},
render: function render() {
var props = this.prepareProps(this.props);
var state = this.state;
var cellMap = {};
var length = props.columns.length;
var cells = props.columns.map(function (col, index) {
var isFirst,
isLast = false;
if (index == length - 1) {
isLast = true;
}
//当第一列是checkbox时则禁止拖拽
if (index == 0 && (0, _typeof3.default)(col.title) == "object") {
col.resizable = false;
}
var isHide = false;
var cell = this.renderCell(props, state, col, index, isLast, null, true, isFirst);
cellMap[col.name] = cell;
return cell;
}, this);
//wuzhe----渲染左固定列的表头的cell
var fixLeftColumns = props.columns.filter(function (item) {
return item.fixed == "left" || item.fixed === true || item.fixed === "";
});
//wuzhe----默认给左边的固定列的表头部分加上阴影,在外部通过类控制该阴影的显示与隐藏
var fixLeftClass = 'z-header fixHeadLeft';
var sty = {};
var styleR = {};
if (props.backStyle && props.backStyle.backgroundColor) {
sty['backgroundColor'] = props.backStyle.backgroundColor;
styleR['backgroundColor'] = props.backStyle.backgroundColor;
}
var fixLeftPart = "";
if (fixLeftColumns.length != 0) {
var fixLeftCellMap = {};
var fixleftcells = fixLeftColumns.map(function (col, index) {
var fixCell = this.renderCell(props, state, col, index);
fixLeftCellMap[col.name] = fixCell;
return fixCell;
}, this);
fixLeftPart = React.createElement(
'div',
{ className: fixLeftClass, style: sty },
React.createElement(
'div',
{ className: 'showShadow' },
fixleftcells
)
);
}
//wuzhe----渲染右固定列的表头的cell
var fixRightColumns = props.columns.filter(function (item, index) {
//wuzhe----记录该列数据在原数据中的index,因为后来宽度是依据index在原数据中获得的
item['formerIndex'] = index;
return item.fixed == "right";
});
//wuzhe----默认给右边的固定列的表头部分加上阴影,在外部通过类控制该阴影的显示与隐藏
var fixRightClass = 'z-header fixHeadRight fixRightShadow';
var fixRightPart = "";
if (fixRightColumns.length != 0) {
var fixRightCellMap = {};
var fixrightcells = fixRightColumns.map(function (col, index) {
var selfIndex = col['formerIndex'];
var fixCell = this.renderCell(props, state, col, selfIndex, props.haspadding);
fixRightCellMap[col.name] = fixCell;
return fixCell;
}, this);
if (props.hasMover) {
// styleR['right'] = props.hasMover - 2 + "px";
} else {
//防止最后一列拖拽被遮挡的问题
// styleR['right'] = "2px";
}
fixRightPart = React.createElement(
'div',
{ className: fixRightClass, style: styleR },
fixrightcells
);
}
if (props.columnGroups && props.columnGroups.length) {
cells = props.columnGroups.map(function (colGroup) {
var cellProps = {};
var columns = [];
var cells = colGroup.columns.map(function (colName) {
var col = props.columnMap[colName];
columns.push(col);
return cellMap[colName];
});
return React.createElement(
Cell,
cellProps,
cells
);
}, this);
}
var style = normalize(props.style);
// wuzhe--verticalScrollbar:
//wuzhe----为兼容ie9,添加msTransform属性,并给表头宽度
var headerStyle = normalize({
paddingRight: props.scrollbarSize,
// transform : 'translate3d(' + -props.scrollLeft + 'px, ' + -props.scrollTop + 'px, 0px)',
// msTransform : 'translate(' + -props.scrollLeft + 'px, ' + -props.scrollTop + 'px)',
width: props.headWidth + 'px'
});
return React.createElement(
'div',
{ style: style, className: props.className, ref: 'tableHeader' },
fixLeftPart,
fixRightPart,
React.createElement(
'div',
{ className: 'z-hader-content', style: { "overflow": "hidden" } },
React.createElement(
'div',
{ className: 'z-header main', style: headerStyle },
cells
)
),
React.createElement(
'div',
{ className: 'header-right-corner-container' },
props.rightCornerComp
)
);
},
mouseInSizer: function mouseInSizer(e) {
var _this = this;
if (!this.state.resizeHover) {
//此处的判断是为了不重复显示样式
document.onmouseup = function () {
_this.setState({ resizeHover: false });
};
var offset = e.target.getBoundingClientRect().right;
var parsent = this.getParentNode(e.target, "react-datagrid");
if (parent) {
offset -= parsent.getBoundingClientRect().left;
}
this.props.showLine(offset - 1);
}
},
getParentNode: function getParentNode(targ, classN) {
var retNode = null;
if (targ.parentElement.className.indexOf(classN) != -1) {
retNode = targ.parentElement;
} else {
retNode = this.getParentNode(targ.parentElement, classN);
}
return retNode;
},
mouseOuterSizer: function mouseOuterSizer(e) {
if (!this.state.resizeHover) {
var domNode = ReactDOM.findDOMNode(this);
var hoverDom = domNode.querySelector(".resize-hover");
if (hoverDom) {
hoverDom.className = hoverDom.className.substr(0, hoverDom.className.indexOf("resize-hover") - 1);
}
this.props.showLine(-10000);
}
},
renderCell: function renderCell(props, state, column, index, isLast, owidth, showflag, isFirst) {
var resizing = props.resizing;
var text = column.title;
var className = props.cellClassName || '';
var style = {
left: 0
};
if (showflag && column.fixed == 'right') {
style['display'] = "none";
}
var menu = this.renderColumnMenu(props, state, column, index);
if (state.dragColumn && state.shiftIndexes && state.shiftIndexes[index]) {
style.left = state.shiftSize;
}
if (state.dragColumn === column) {
className += ' z-drag z-over';
style.zIndex = 1;
style.left = state.dragLeft || 0;
}
var filterIcon = props.filterIcon || React.createElement(
'svg',
{ version: '1.1', style: { transform: 'translate3d(0,0,0)', height: '100%', width: '100%', padding: '0px 2px' }, viewBox: '0 0 3 4' },
React.createElement('polygon', { points: '0,0 1,2 1,4 2,4 2,2 3,0 ', style: { fill: props.filterIconColor, strokeWidth: 0, fillRule: 'nonZero' } })
);
var filter = column.filterable ? React.createElement(
'div',
{ className: 'z-show-filter', onMouseUp: this.handleFilterMouseUp.bind(this, column) },
filterIcon
) : null;
var right = 0;
if (this.dragColumn && this.dragColumn.title == column.title) {
right = this.state.offset;
}
var resizer = column.resizable && !isFirst ? React.createElement(
'div',
{ className: "resize-area", onMouseDown: this.handleResizeMouseDown.bind(this, column) },
React.createElement('span', { style: { right: right + "px" }, className: 'z-column-resize', onMouseLeave: this.mouseOuterSizer, onMouseEnter: this.mouseInSizer, onMouseDown: this.handleResizeMouseDown.bind(this, column) })
) : null;
if (column.sortable) {
var sortInfo = getColumnSortInfo(column, props.sortInfo);
var boxClassName = "sortBox";
if (sortInfo && sortInfo.dir) {
className += sortInfo.dir === -1 || sortInfo.dir === 'desc' ? ' z-desc' : ' z-asc';
if (sortInfo.dir === -1 || sortInfo.dir === 'desc') {
// wuzhe----倒序排序时
text = React.createElement(
'div',
{ className: boxClassName },
React.createElement(
ToolTip,
{ title: (0, _commonFunc.decode)(text) },
React.createElement(
'span',
{ className: 'titleText' },
(0, _commonFunc.decode)(text)
)
),
React.createElement(
'div',
{ onClick: this.sortClick.bind(this, column), className: 'sortArea' },
React.createElement('span', { className: 'pc-sys-sequencedown-nomal-svg icon-top' }),
React.createElement('span', { className: 'pc-sys-seqdown-active-svg' })
)
);
} else {
// wuzhe----顺序排序时
text = React.createElement(
'div',
{ className: boxClassName },
React.createElement(
ToolTip,
{ title: (0, _commonFunc.decode)(text) },
React.createElement(
'span',
{ className: 'titleText' },
(0, _commonFunc.decode)(text)
)
),
React.createElement(
'div',
{ onClick: this.sortClick.bind(this, column), className: 'sortArea' },
React.createElement('span', { className: 'pc-sys-seqdown-active-svg icon-top' }),
React.createElement('span', { className: 'pc-sys-sequencedown-nomal-svg' })
)
);
}
} else {
// wuzhe----没点排序时
text = React.createElement(
'div',
{ className: boxClassName },
React.createElement(
ToolTip,
{ title: (0, _commonFunc.decode)(text) },
React.createElement(
'span',
{ className: 'titleText' },
(0, _commonFunc.decode)(text)
)
),
React.createElement(
'div',
{ onClick: this.sortClick.bind(this, column), className: 'sortArea' },
React.createElement('span', { className: 'pc-sys-sequencedown-nomal-svg icon-top' }),
React.createElement('span', { className: 'pc-sys-sequencedown-nomal-svg' })
)
);
}
className += ' z-sortable';
}
if (filter) {
className += ' z-filterable';
}
if (state.mouseOver === column.name && !resizing) {
className += ' z-over';
}
if (props.menuColumn === column.name) {
className += ' z-active';
}
className += ' z-unselectable';
var events = {};
isLast = isLast ? isLast : false;
events.onMouseDown = this.handleMouseDown.bind(this, column);
events.onMouseUp = this.handleMouseUp.bind(this, column);
//juan add 新增若有expand列,则隐藏列头
if (props.columns[index].name === "expand") {
className += ' hideExpandTitle';
}
return React.createElement(
Cell,
(0, _extends3.default)({
key: column.name,
contentPadding: props.cellPadding,
columns: props.columns || [],
index: index,
right: right,
isLast: isLast,
column: props.columns[index],
className: className,
style: style,
text: text,
header: true,
onMouseOut: this.handleMouseOut.bind(this, column),
onMouseOver: this.handleMouseOver.bind(this, column)
}, events),
filter,
menu,
resizer
);
},
sortClick: function sortClick(column, event) {
if (column.sortable) {
this.toggleSort(column);
}
},
toggleSort: function toggleSort(column) {
var sortInfo = asArray(clone(this.props.sortInfo));
var columnSortInfo = getColumnSortInfo(column, sortInfo);
if (!columnSortInfo) {
columnSortInfo = {
name: column.name,
type: column.type,
fn: column.sortFn
};
sortInfo.push(columnSortInfo);
}
if (typeof column.toggleSort === 'function') {
column.toggleSort(columnSortInfo, sortInfo);
} else {
var dir = columnSortInfo.dir;
//var newDir = dir==='asc'?"desc":"asc";
var dirSign = dir === 'asc' ? 1 : dir === 'desc' ? -1 : dir;
var newDir = dirSign === 1 ? -1 : dirSign === -1 ? 0 : 1;
columnSortInfo.dir = newDir;
if (!newDir) {
sortInfo = removeColumnSort(column, sortInfo);
}
};
(this.props.onSortChange || emptyFn)(columnSortInfo);
//;(this.props.onSortChange || emptyFn)(sortInfo)
},
componentDidMount: function componentDidMount() {
window.addEventListener('keydown', this.windowKeyDown = this.onWindowKeyDown);
window.addEventListener('keyup', this.windowKeyUp = this.onWindowKeyUp);
},
onWindowKeyDown: function onWindowKeyDown(event) {
//只有按住shift时列高亮才能多选,否则只能单列高亮,shift的keycode为16
if (event.keyCode === 16) {
this.keyDown = true;
}
},
onWindowKeyUp: function onWindowKeyUp(event) {
if (event.keyCode === 16) {
this.keyDown = false;
}
},
componentWillUnmount: function componentWillUnmount() {
window.removeEventListener('keydown', this.windowKeyDown);
window.removeEventListener('keyup', this.windowKeyUp);
},
toggleHighLight: function toggleHighLight(column, event) {
if (event.target.className == 'sortArea' || event.target.className.indexOf('pc-sys') > -1 || column.name == 'checkboxPro' || column.name == 'operator' || this.props.isLookUpv1) return;
var hlList = document.getElementsByName(column.name);
var parentNode;
if (this.refs && this.refs.tableHeader && this.refs.tableHeader.parentNode && this.refs.tableHeader.parentNode.parentNode) {
parentNode = this.refs.tableHeader.parentNode.parentNode;
var filterDom = [];
for (var s = 0; s < hlList.length; s++) {
if (parentNode.contains(hlList[s])) {
filterDom.push(hlList[s]);
}
}
hlList = filterDom;
}
if (this.props.isLookUpV2) {
var arr = [];
for (var i = 0, len = hlList.length; i < len; i++) {
arr.push(hlList[i]);
}
for (var j = 0, flag = true, len = arr.length; j < len; flag ? j++ : j) {
if (arr[j] && arr[j].className.indexOf('LookUpV2') < 0) {
arr.splice(j, 1);
flag = false;
} else {
flag = true;
}
}
var hlList = [];
for (var i = 0, len = arr.length; i < len; i++) {
hlList.push(arr[i]);
}
}
if (event.currentTarget.style.backgroundColor.indexOf('rgba') < 0) {
if (!this.keyDown) {
//判断按下shift时才能多列高亮
var hasHlList = document.getElementsByClassName("highLightCell");
var headerList = document.getElementsByClassName("z-column-header");
if (hasHlList && headerList) {
for (var h = 0; h < headerList.length; h++) {
headerList[h].style.backgroundColor = "";
}
while (hasHlList.length > 0) {
hasHlList[0].className = hasHlList[0].className.replace("highLightCell", "");
}
}
}
event.currentTarget.style.backgroundColor = 'rgba(150,208,250,0.35)';
for (var i = 0; i < hlList.length; i++) {
hlList[i].className = hlList[i].className + ' highLightCell';
}
} else {
event.currentTarget.style.backgroundColor = '';
for (var i = 0; i < hlList.length; i++) {
var index = hlList[i].className.indexOf('highLightCell');
hlList[i].className = hlList[i].className.substring(0, index);
}
}
},
renderColumnMenu: function renderColumnMenu(props, state, column, index) {
if (!props.withColumnMenu) {
return;
}
var menuIcon = props.menuIcon || React.createElement(
'svg',
{ version: '1.1', style: { transform: 'translate3d(0,0,0)', height: '100%', width: '100%', padding: '0px 2px' }, viewBox: '0 0 3 4' },
React.createElement('polygon', { points: '0,0 1.5,3 3,0 ', style: { fill: props.menuIconColor, strokeWidth: 0, fillRule: 'nonZero' } })
);
return React.createElement(
'div',
{ className: 'z-show-menu', onMouseUp: this.handleShowMenuMouseUp.bind(this, props, column, index) },
menuIcon
);
},
handleShowMenuMouseUp: function handleShowMenuMouseUp(props, column, index, event) {
event.nativeEvent.stopSort = true;
this.showMenu(column, event);
},
showMenu: function showMenu(column, event) {
var menuItem = function (column) {
var visibility = this.props.columnVisibility;
var visible = column.visible;
if (column.name in visibility) {
visible = visibility[column.name];
}
return {
cls: visible ? 'z-selected' : '',
selected: visible ? React.createElement(
'span',
{ style: { fontSize: '0.95em' } },
'\u2713'
) : '',
label: column.title,
fn: this.toggleColumn.bind(this, column)
};
}.bind(this);
function menu(eventTarget, props) {
var columns = props.gridColumns;
props.columns = ['selected', 'label'];
props.items = columns.map(menuItem);
props.alignTo = eventTarget;
props.alignPositions = ['tl-bl', 'tr-br', 'bl-tl', 'br-tr'];
props.style = {
position: 'absolute'
};
var factory = this.props.columnMenuFactory || ReactMenu;
var result = factory(props);
return result === undefined ? ReactMenu(props) : result;
}
this.props.showMenu(menu.bind(this, event.currentTarget), {
menuColumn: column.name
});
},
showFilterMenu: function showFilterMenu(column, event) {
function menu(eventTarget, props) {
var defaultFactory = this.props.filterMenuFactory;
var factory = column.filterMenuFactory || defaultFactory;
props.columns = ['component'];
props.column = column;
props.alignTo = eventTarget;
props.alignPositions = ['tl-bl', 'tr-br', 'bl-tl', 'br-tr'];
props.style = {
position: 'absolute'
};
var result = factory(props);
return result === undefined ? defaultFactory(props) : result;
}
this.props.showMenu(menu.bind(this, event.currentTarget), {
menuColumn: column.name
});
},
toggleColumn: function toggleColumn(column) {
this.props.toggleColumn(column);
},
hideMenu: function hideMenu() {
this.props.showColumnMenu(null, null);
},
handleResizeMouseDown: function handleResizeMouseDown(column, event) {
setupColumnResize(this, this.props, column, event);
/*
zhongjiahao solve column drag sensitive
*/
//setupColumnResize(this, this.props, column, event)
//in order to prevent setupColumnDrag in handleMouseDown
// event.stopPropagation()
//we are doing setupColumnDrag protection using the resizing flag on native event
if (event.nativeEvent) {
event.nativeEvent.resizing = true;
}
//tag
this.setState({ resizeHover: true });
},
handleFilterMouseUp: function handleFilterMouseUp(column, event) {
event.nativeEvent.stopSort = true;
this.showFilterMenu(column, event);
},
handleMouseUp: function handleMouseUp(column, event) {
if (this.state.dragging) {
return;
}
if (this.state.resizing) {
return;
}
if (event && event.nativeEvent && event.nativeEvent.stopSort) {
return;
}
this.toggleHighLight(column, event);
},
handleMouseOut: function handleMouseOut(column) {
this.setState({
mouseOver: false
});
},
handleMouseOver: function handleMouseOver(column) {
this.setState({
mouseOver: column.name
});
},
handleMouseDown: function handleMouseDown(column, event) {
if (event && event.nativeEvent && event.nativeEvent.resizing) {
return;
}
if (!this.props.reorderColumns) {
return;
}
setupColumnDrag(this, this.props, column, event);
},
onResizeDragStart: function onResizeDragStart(config) {
this.setState({
resizing: true
});
this.dragColumn = config.resizeColumn;
this.props.onColumnResizeDragStart(config);
},
onResizeDrag: function onResizeDrag(config, e) {
var offset = 0 - config.resizeProxyDiff;
//防止header的渲染次数过多,直接操作dom赋值
this.setResizeDomStyle("block");
this.props.onColumnResizeDrag(config);
},
onResizeDrop: function onResizeDrop(config, resizeInfo, event) {
this.dragColumn = null;
this.setState({
resizing: false
});
this.setResizeDomStyle("none");
this.props.onColumnResizeDrop(config, resizeInfo);
this.mouseOuterSizer();
},
setResizeDomStyle: function setResizeDomStyle(display) {
var domNode = ReactDOM.findDOMNode(this);
var resizeDom = domNode.parentNode.parentNode.getElementsByClassName("z-resize-proxy")[0];
var resizeBlock = domNode.parentNode.parentNode.getElementsByClassName("z-resize-block")[0];
resizeDom.style.display = display;
resizeBlock.style.display = display;
},
prepareProps: function prepareProps(thisProps) {
var props = {};
assign(props, thisProps);
this.prepareClassName(props);
this.prepareStyle(props);
var columnMap = {};
(props.columns || []).forEach(function (col) {
columnMap[col.name] = col;
});
props.columnMap = columnMap;
return props;
},
prepareClassName: function prepareClassName(props) {
props.className = props.className || '';
props.className += ' ' + props.defaultClassName;
if (this.state.dragging) {
props.className += ' ' + props.draggingClassName;
}
},
prepareStyle: function prepareStyle(props) {
var style = props.style = {};
assign(style, props.defaultStyle);
}
});