// @ts-nocheck /* eslint-disable no-param-reassign */ /* eslint-disable prefer-destructuring */ import isFunction from 'lodash/isFunction'; import { tryParseInt, removeClass, addClass } from './utils'; export type Options = { /** 是否实时拖动 */ liveDrag?: boolean; /** 默认没列最小宽度 */ defaultMinWidth?: number; /** 拖动竖线是否只有thead */ headerOnly?: boolean; /** 不能拖动的th */ disabledColumns?: number[]; /** 正在拖动callback */ onResizing?: () => void; /** 拖动结束callback */ onResized?: () => void; }; const defaultOptions: Options = { liveDrag: true, defaultMinWidth: 30, headerOnly: true, disabledColumns: [], }; export default class ColResizable { options: Options; domElmTable: HTMLTableElement; domElmThList: HTMLTableCellElement[]; domElmTableTheadThList: HTMLTableCellElement[]; /** 存放拖动标签的容器 */ domElmHandleContainer: HTMLDivElement | null; tableWidth: string; cellSpacing: number; borderLeftWidth: number; lastThIndex: number; thLength: number; domElmHandleList: HTMLTableCellElement[]; disabledColumns: number[]; drag: HTMLTableCellElement | null; constructor(domElmTable: HTMLTableElement, options = {}) { this.options = { ...defaultOptions, ...options }; this.domElmTable = domElmTable; this.onGripMouseDown = this.onGripMouseDown.bind(this); this.onMouseMove = this.onMouseMove.bind(this); this.onMouseUp = this.onMouseUp.bind(this); this.init(); } init() { addClass(this.domElmTable, 'table-col-resizer'); this.domElmHandleList = []; this.domElmTableTheadThList = []; this.tableWidth = `${this.domElmTable.offsetWidth}px`; this.cellSpacing = tryParseInt( getComputedStyle(this.domElmTable).getPropertyValue('border-spacing'), ); this.borderLeftWidth = tryParseInt( getComputedStyle(this.domElmTable).getPropertyValue('border-left-width'), ); this.createGrips(); } createGrips() { const thList = this.domElmTable.querySelectorAll('thead th'); const domElmThList: HTMLTableCellElement[] = []; this.domElmHandleContainer = this.domElmTable.previousSibling as HTMLDivElement; const hasHandleContainer = this.domElmHandleContainer && this.domElmHandleContainer.className === 'col-resize-container'; if (!hasHandleContainer) { this.domElmTable.insertAdjacentHTML('beforebegin', '
'); this.domElmHandleContainer = this.domElmTable.previousSibling as HTMLDivElement; } else { Array.prototype.push.apply(this.domElmHandleList, this.domElmHandleContainer.childNodes); } Array.prototype.push.apply(domElmThList, thList); this.thLength = domElmThList.length; this.lastThIndex = this.thLength - 1; const { disabledColumns = [] } = this.options; domElmThList.forEach((domElmTh, index) => { const disabledColumn = disabledColumns.indexOf(index) !== -1; let domElmHandle; if (!hasHandleContainer && this.domElmHandleContainer) { this.domElmHandleContainer.insertAdjacentHTML( 'beforeend', `
`, ); domElmHandle = this.domElmHandleContainer.lastChild; } else { domElmHandle = this.domElmHandleList[index]; } if (index === this.lastThIndex && !hasHandleContainer) { addClass(domElmHandle as HTML, 'last-handle'); } if (!disabledColumn && !hasHandleContainer) { domElmHandle.addEventListener('mousedown', this.onGripMouseDown); } else if (disabledColumn && !hasHandleContainer) { addClass(domElmHandle, 'disabled-drag'); } domElmHandle.index = index; domElmTh.w = domElmTh.offsetWidth; domElmTh.style.width = `${domElmTh.offsetWidth}px`; if (!hasHandleContainer) { this.domElmHandleList.push(domElmHandle); } this.domElmTableTheadThList.push(domElmTh); }); this.syncGrips(); } syncGrips() { const { headerOnly } = this.options; const theadHight = this.domElmTableTheadThList[0].offsetHeight; let height; if (headerOnly) { height = theadHight; } else { height = this.domElmTable.offsetHeight; } for (let i = 0; i < this.thLength; i += 1) { const domElmTh = this.domElmTableTheadThList[i]; let left; if (i === 0) { left = domElmTh.offsetWidth + this.cellSpacing / 2; } else { const handleColLeft = this.domElmHandleList[i - 1].style.left + this.cellSpacing / 2; left = tryParseInt(handleColLeft) + domElmTh.offsetWidth; } this.domElmHandleList[i].style.left = `${left}px`; this.domElmHandleList[i].style.height = `${height}px`; } const domElmIconList = []; const iconHeight = this.domElmHandleContainer.querySelector( '.col-resize-container .icon', ).offsetHeight; const domElemIcons = this.domElmHandleContainer.querySelectorAll('.col-resize-container .icon'); Array.prototype.push.apply(domElmIconList, domElemIcons); domElmIconList.forEach((el) => { const marginTopNumber = (theadHight - iconHeight) / 2; el.style.marginTop = `${tryParseInt(marginTopNumber)}px`; }); } onGripMouseDown(e) { e.preventDefault(); const { index } = e.currentTarget; const domElmHandle = this.domElmHandleList[index]; addClass(domElmHandle, 'active-drag'); domElmHandle.initPageLeftX = e.pageX; domElmHandle.initLeft = tryParseInt(domElmHandle.style.left); domElmHandle.x = domElmHandle.initLeft; this.drag = domElmHandle; document.addEventListener('mousemove', this.onMouseMove); document.addEventListener('mouseup', this.onMouseUp); return false; } onMouseMove(e) { e.preventDefault(); if (!this.drag) { return false; } const { defaultMinWidth } = this.options; const index = this.drag.index; const minWidth = defaultMinWidth; const pageLeftX = e.pageX; let x = pageLeftX - this.drag.initPageLeftX + this.drag.initLeft; const l = this.cellSpacing * 1.5 + minWidth + this.borderLeftWidth; const min = index ? tryParseInt(this.domElmHandleList[index - 1].style.left) + this.cellSpacing + minWidth : l; const max = tryParseInt(this.domElmHandleList[index + 1].style.left) - this.cellSpacing - minWidth; x = Math.max(min, Math.min(max, x)); const inc = x - this.drag.initLeft; const domElmThNow = this.domElmTableTheadThList[index]; const domElmThElmNext = this.domElmTableTheadThList[index + 1]; const w = domElmThNow.w + inc; const w2 = domElmThElmNext.w - inc; const minWidthOne = tryParseInt( this.domElmTableTheadThList[index].getAttribute('data-min-width'), ); const minWidthTwo = tryParseInt( this.domElmTableTheadThList[index + 1].getAttribute('data-min-width'), ); if (minWidthOne > w) { x = minWidthOne - domElmThNow.w + this.drag.initLeft; } else if (minWidthTwo > w2) { x = domElmThElmNext.w - minWidthTwo + this.drag.initLeft; } this.drag.x = x; this.drag.style.left = `${x}px`; if (this.options.liveDrag) { this.syncCols(index); this.syncGrips(); const { onResizing } = this.options; if (isFunction(onResizing)) { onResizing(e); } } return false; } syncCols(i, isOver) { const inc = this.drag.x - this.drag.initLeft; const domElmThNow = this.domElmTableTheadThList[i]; const domElmThNext = this.domElmTableTheadThList[i + 1]; const w = domElmThNow.w + inc; const w2 = domElmThNext.w - inc; domElmThNow.style.width = `${w}px`; domElmThNext.style.width = `${w2}px`; if (isOver) { domElmThNow.w = w; domElmThNext.w = w2; } } onMouseUp(e) { document.removeEventListener('mouseup', this.onMouseUp); document.removeEventListener('mousemove', this.onMouseMove); if (!this.drag) { return false; } removeClass(this.drag, 'active-drag'); if (!(this.drag.x - this.drag.initLeft === 0)) { const index = this.drag.index; this.syncCols(index, true); this.syncGrips(); const { onResized } = this.options; if (isFunction(onResized)) { onResized(e); } } this.drag = null; return true; } }