UNPKG

@beisen/ethos

Version:

beisencloud pc react components

849 lines (706 loc) 25.3 kB
'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); } });