bee-table/src/TableHeader.js

352 lines
13 KiB
JavaScript
Raw Normal View History

import React, { Component } from 'react';
import PropTypes from 'prop-types';
2016-12-26 16:52:39 +08:00
import shallowequal from 'shallowequal';
import { throttle, debounce } from 'throttle-debounce';
import { tryParseInt, ObjectAssign } from './utils';
import FilterType from './FilterType';
2016-12-26 16:52:39 +08:00
2017-01-11 17:01:50 +08:00
const propTypes = {
clsPrefix: PropTypes.string,
rowStyle: PropTypes.object,
rows: PropTypes.array,
2017-01-11 17:01:50 +08:00
}
2018-06-25 00:39:18 +08:00
const grap = 16;//偏移数值
class TableHeader extends Component {
2018-05-08 16:41:14 +08:00
constructor(props) {
2018-05-07 10:58:24 +08:00
super(props);
2018-05-09 14:51:01 +08:00
this.currentObj = null;
2018-05-13 15:02:53 +08:00
this.state = {
border: false
2018-05-13 15:02:53 +08:00
}
//拖拽宽度处理
if (!props.dragborder) return;
2018-05-11 09:29:43 +08:00
this.border = false;
2018-05-13 16:28:08 +08:00
this.theadKey = new Date().getTime();
2018-05-11 09:29:43 +08:00
this.drag = {
initPageLeftX: 0,
initLeft: 0,
x: 0,
width: 0,
2018-05-11 09:29:43 +08:00
}
2018-06-25 00:39:18 +08:00
// let _da = {};
// Object.assign(_da,this.props.rows[0]);
// this.drag.data = JSON.parse(JSON.stringify(this.props.rows[0]));
// let a = this.props.rows[0];
2018-06-25 00:39:18 +08:00
let _row = [];
this.props.rows[0].forEach(item => {
let newItem = item.key != "checkbox" ? ObjectAssign(item) : item;
2018-06-25 00:39:18 +08:00
_row.push(newItem);
});
this.drag.data = _row;//JSON.parse(JSON.stringify(this.props.rows[0]));
}
static defaultProps = {
contentWidthDiff: 0
2018-05-07 10:58:24 +08:00
}
2018-05-08 16:41:14 +08:00
2016-12-26 16:52:39 +08:00
shouldComponentUpdate(nextProps) {
return !shallowequal(nextProps, this.props);
2017-01-11 17:01:50 +08:00
}
2018-05-09 14:51:01 +08:00
onDragStart = (event, data) => {
2018-05-09 14:51:01 +08:00
event.dataTransfer.effectAllowed = "move";
event.dataTransfer.setData("Text", data.key);
2018-05-09 14:51:01 +08:00
this.currentObj = data;
event.dataTransfer.setDragImage(event.target, 0, 0);
this.props.onDragStart(event, data);
2018-05-09 14:51:01 +08:00
}
onDragOver = (event, data) => {
if (!this.currentObj || this.currentObj.key == data.key) return;
2018-05-09 14:51:01 +08:00
event.preventDefault();
this.props.onDragOver(event, data);
2018-05-09 14:51:01 +08:00
}
onDragEnter = (event, data) => {
if (!this.currentObj || this.currentObj.key == data.key) return;
this.props.onDragEnter(event, data);
2018-05-09 14:51:01 +08:00
}
onDrop = (event, data) => {
if (!this.currentObj || this.currentObj.key == data.key) return;
this.props.onDrop(event, data);
2018-05-09 14:51:01 +08:00
}
2018-05-11 09:29:43 +08:00
onMouseOver = (event, data) => {
//如果是固定列没有拖拽功能
if (this.border || data.fixed) return;
const { clsPrefix } = this.props;
2018-05-13 14:35:05 +08:00
event.target.className = `${clsPrefix}-thead-th-drag-gap th-drag-gap-hover`;
2018-05-11 09:29:43 +08:00
}
onMouseMove = (event, data) => {
//如果是固定列没有拖拽功能
if (this.border || data.fixed) return;
// const {clsPrefix} = this.props;
// event.target.className = `${clsPrefix}-thead-th-drag-gap th-drag-gap-hover`;
}
onMouseOut = (event, data) => {
if (this.border) return;
const { clsPrefix } = this.props;
2018-05-11 09:29:43 +08:00
event.target.className = `${clsPrefix}-thead-th-drag-gap th-drag-gap`;
}
onMouseDown = (event, data) => {
2018-05-11 09:29:43 +08:00
this.border = true;
const { clsPrefix, contentTable } = this.props;
2018-05-11 09:29:43 +08:00
this.drag.initPageLeftX = event.pageX;
this.drag.initLeft = tryParseInt(event.target.style.left);
this.drag.x = this.drag.initLeft;
this.drag.currIndex = this.props.rows[0].findIndex(da => da.key == data.key);
let contentTableDom = document.getElementById("u-table-drag-thead-" + this.theadKey).parentNode;
2018-09-19 10:46:14 +08:00
const styleWidth = contentTableDom.style.width;
if (styleWidth && (typeof (styleWidth) == 'number' || styleWidth.includes('px'))) {
this.contentTableWidth = parseInt(styleWidth);
} else {
this.contentTableWidth = parseInt(contentTableDom.scrollWidth)
2018-09-19 10:46:14 +08:00
}
2018-09-30 11:02:04 +08:00
const dragColWidth = this.drag.data[this.drag.currIndex].width;
if (typeof (dragColWidth) == 'string' && dragColWidth.indexOf('%') > -1) {
this.drag.width = this.contentTableWidth * parseInt(dragColWidth) / 100
} else {
2018-09-30 11:02:04 +08:00
this.drag.width = parseInt(this.drag.data[this.drag.currIndex].width);
}
2018-05-11 09:29:43 +08:00
}
onMouseUp = (event, data) => {
2018-05-11 09:29:43 +08:00
this.border = false;
const { clsPrefix } = this.props;
2018-05-11 09:29:43 +08:00
event.target.className = `${clsPrefix}-thead-th-drag-gap th-drag-gap`;
2018-05-11 16:51:53 +08:00
}
onThMouseUp = (event, data) => {
2018-05-11 16:51:53 +08:00
this.border = false;
const { clsPrefix } = this.props;
2018-09-19 10:46:14 +08:00
let eventDom = event.target;
let optDom;
if (eventDom.classList.contains('.th-drag-gap-hover')) {
2018-09-19 10:46:14 +08:00
optDom = eventDom;
} else {
2018-09-19 10:46:14 +08:00
optDom = eventDom.querySelector(`.${clsPrefix}-thead-th-drag-gap`);
}
if (optDom) {
2018-09-19 10:46:14 +08:00
optDom.classList.remove('th-drag-gap-hover');
optDom.classList.add('th-drag-gap');
}
2018-05-11 16:51:53 +08:00
}
onThMouseMove = (event, data) => {
if (!this.border) return;
2018-09-19 10:46:14 +08:00
//固定表头拖拽
const { dragborderKey, contentTable } = this.props;
let x = (event.pageX - this.drag.initPageLeftX) + this.drag.initLeft - 0;
let contentTableDom = document.getElementById("u-table-drag-thead-" + this.theadKey).parentNode;
if (!this.contentTableWidth) {
2018-09-19 10:46:14 +08:00
const styleWidth = contentTableDom.style.width;
if (styleWidth && (typeof (styleWidth) == 'number' || styleWidth.includes('px'))) {
2018-09-19 10:46:14 +08:00
this.contentTableWidth = parseInt(styleWidth);
} else {
2018-09-19 10:46:14 +08:00
this.contentTableWidth = parseInt(contentTableDom.scrollWidth)
}
}
const newTableWidth = this.contentTableWidth + x;
const newWidth = this.drag.width + x;
if (newWidth < this.props.minColumnWidth) {
//清楚样式
let moveDom = event.target.querySelector('.th-drag-gap-hover');
moveDom && moveDom.classList.remove('th-drag-gap-hover');
// event.target.classList.remove('th-drag-gap-hover');
return
}
2018-05-11 16:51:53 +08:00
//设置hiden的left
2018-05-13 16:28:08 +08:00
//"u-table-drag-hide-table"
let currentHideDom = document.getElementById("u-table-drag-hide-table-" + dragborderKey).getElementsByTagName("div")[this.drag.currIndex];
currentHideDom.style.left = (this.drag.initPageLeftX + x - grap) + "px";
2018-06-25 00:40:21 +08:00
2018-06-25 00:39:18 +08:00
//获取最小宽度,不让拖动
// let minWidth = 0;
// for(let i=0;i<=this.drag.currIndex;i++){
// minWidth += this.drag.data[i].width;
// }
2018-06-25 00:39:18 +08:00
// //判断最小值后在赋值 todo
// let currLeft = this.drag.initPageLeftX+x-grap;
// console.log("currLeft minWidth ",currLeft + " "+minWidth);
// if(currLeft <= minWidth){
// return;
// }
// currentHideDom.style.left = currLeft+"px";
2018-05-13 14:35:05 +08:00
//设置当前的宽度
let currentData = this.drag.data[this.drag.currIndex];
currentData.width = newWidth;
let currentDom = document.getElementById("u-table-drag-thead-" + this.theadKey).getElementsByTagName("th")[this.drag.currIndex];
currentDom.style.width = newWidth + "px";
// this.contentTableWidth = newTableWidth;
contentTableDom.style.width = newTableWidth + 'px';
this.drag.x = x;
let contentColDomArr = contentTableDom.querySelectorAll('colgroup col')
contentColDomArr[this.drag.currIndex].style.width = newWidth + "px";
2018-09-19 10:46:14 +08:00
//固定表头时,表头和表体分开,拖拽时表体的宽度也需要一起联动
const siblingDom = contentTableDom.parentNode.nextElementSibling;
if (siblingDom) {
2018-09-19 10:46:14 +08:00
const bodyTableDom = siblingDom.querySelector('table')
//2、是的话将表头对应的表格的宽度给表体对应的表格的宽度
bodyTableDom.style.width = newTableWidth + 'px';
2018-09-19 10:46:14 +08:00
//3、对应的col也要跟这变
let colDomArr = bodyTableDom.querySelectorAll('colgroup col')
colDomArr[this.drag.currIndex].style.width = newWidth + "px";
2018-09-19 10:46:14 +08:00
//4、设置overflow属性
}
}
2018-09-19 10:46:14 +08:00
/**
* @description 过滤输入后的回调函数
*/
handlerFilterTextChange = (key, val) => {
let { onFilterRowsChange } = this.props;
if (onFilterRowsChange) {
onFilterRowsChange(key, val);
}
2018-05-11 09:29:43 +08:00
}
/**
* @description 过滤输入后的回调函数
*/
handlerFilterDropChange = (key, val) => {
let { onFilterRowsDropChange } = this.props;
if (onFilterRowsDropChange) {
onFilterRowsDropChange(key, val.key);
}
}
/**
* @description 过滤渲染的组件类型
*/
filterRenderType = (type, dataIndex, index) => {
const { clsPrefix, rows, filterDelay } = this.props;
switch (type) {
//文本输入
case 'text':
return <FilterType
rendertype={type}
clsPrefix={clsPrefix}
className={`${clsPrefix} filter-text`}
onChange={debounce(filterDelay || 300, this.handlerFilterTextChange.bind(this, dataIndex))}
onSelectDropdown={this.handlerFilterDropChange.bind(this, dataIndex)}
filterDropdown={rows[1][index]['filterdropdown']}
/>
//下拉框选择
case 'dropdown':
let selectDataSource = [];
if (rows.length > 0) {
let hash = {};
//处理下拉重复对象组装dropdown
selectDataSource = Array.from(rows[1][0].datasource, x => ({ key: x[dataIndex], value: x[dataIndex] }));
selectDataSource = selectDataSource.reduceRight((item, next) => {
hash[next.key] ? '' : hash[next.key] = true && item.push(next);
return item
}, []);
}
return <FilterType
rendertype={type}
className={`${clsPrefix} filter-dropdown`}
data={selectDataSource}
onChange={this.handlerFilterTextChange.bind(this, dataIndex)}
onSelectDropdown={this.handlerFilterDropChange.bind(this, dataIndex)}
2018-09-25 11:07:47 +08:00
filterDropdown={rows[1][index]['filterdropdown']}
/>
//日期
case 'date':
return <FilterType
rendertype={type}
className={`filter-date`}
onClick={() => { }}
format={rows[1][index]['format'] || "YYYY-MM-DD"}
onChange={this.handlerFilterTextChange.bind(this, dataIndex)}
onSelectDropdown={this.handlerFilterDropChange.bind(this, dataIndex)}
2018-09-25 11:07:47 +08:00
filterDropdown={rows[1][index]['filterdropdown']}
/>
default:
//不匹配类型默认文本输入
return <div></div>
}
}
2016-12-26 16:52:39 +08:00
render() {
const { clsPrefix, rowStyle, onDragStart, onDragOver, onDrop, draggable, rows, filterable, onFilterRowsChange,
onMouseDown, onMouseMove, onMouseUp, dragborder, onMouseOut, contentWidthDiff, fixed, lastShowIndex
} = this.props;
let attr = dragborder ? { id: `u-table-drag-thead-${this.theadKey}` } : {}
2016-12-26 16:52:39 +08:00
return (
2018-05-14 09:58:50 +08:00
<thead className={`${clsPrefix}-thead`} {...attr}>
2016-12-26 16:52:39 +08:00
{
rows.map((row, index) => (
<tr key={index} style={rowStyle}>
{row.map((da, i, arr) => {
let thHover = da.drgHover ? ` ${clsPrefix}-thead th-drag-hover` : "";
2018-05-11 11:30:56 +08:00
delete da.drgHover;
let fixedStyle = '';
2018-09-30 11:02:04 +08:00
let canDotDrag = '';
if (!fixed && da.fixed) {
fixedStyle = `${clsPrefix}-row-fixed-columns-in-body`;
}
if (lastShowIndex == i) {
da.width = parseInt(da.width) + contentWidthDiff;
2018-09-30 11:02:04 +08:00
canDotDrag = 'th-can-not-drag'
}
if (filterable && index == rows.length - 1) {
da.children = this.filterRenderType(da['filtertype'], da.dataindex, i);
}
if (draggable) {
return (<th {...da}
onDragStart={(event) => { this.onDragStart(event, da) }}
onDragOver={(event) => { this.onDragOver(event, da) }}
onDrop={(event) => { this.onDrop(event, da) }}
onDragEnter={(event) => { this.onDragEnter(event, da) }}
2018-05-11 09:29:43 +08:00
draggable={draggable}
className={`${da.className} ${clsPrefix}-thead th-drag ${thHover} ${fixedStyle}`}
2018-05-11 11:30:56 +08:00
key={da.key} />)
} else if (dragborder) {
return (<th
style={{ width: da.width }}
onMouseMove={(event) => { this.onThMouseMove(event, da) }}
onMouseUp={(event) => { this.onThMouseUp(event, da) }}
2018-09-30 11:02:04 +08:00
className={`${da.className} ${clsPrefix}-thead-th ${canDotDrag} ${fixedStyle}`}
2018-05-11 09:29:43 +08:00
key={i} >
{da.children}
<div ref={el => this.gap = el}
onMouseMove={(event) => { this.onMouseMove(event, da) }}
onMouseOut={(event) => { this.onMouseOut(event, da) }}
onMouseDown={(event) => { this.onMouseDown(event, da) }}
onMouseUp={(event) => { this.onMouseUp(event, da) }}
onMouseOver={(event) => { this.onMouseOver(event, da) }}
2018-05-11 09:29:43 +08:00
className={`${clsPrefix}-thead-th-drag-gap `}></div>
</th>)
} else {
let th;
th = da.onClick ? (<th {...da} className={`${da.className} ${fixedStyle}`} key={i} onClick={(event) => { da.onClick(da, event) }} />) : (<th {...da} key={i} className={`${da.className} ${fixedStyle}`} />);
2018-05-11 11:30:56 +08:00
return (th);
2018-05-11 09:29:43 +08:00
}
})}
2016-12-26 16:52:39 +08:00
</tr>
))
}
</thead>
);
2017-01-11 17:01:50 +08:00
}
};
TableHeader.propTypes = propTypes;
export default TableHeader;