UNPKG

table-dragger

Version:
246 lines (214 loc) 7.46 kB
/** * Created by lijun on 2016/12/8. */ import dragula from 'dragula-with-animation'; import classes from './classes'; import { insertBeforeSibling, getScrollBarWidth, css, remove, getLongestRow, empty, touchy, getTouchyEvent, } from './util'; let bodyPaddingRight; let bodyOverflow; export default class Dragger { constructor ({ originTable, mode }) { const { dragger, cellIndex, el: originEl, options } = originTable; const fakeTables = this.fakeTables = buildTables(originEl, mode); bodyPaddingRight = parseInt(document.body.style.paddingRight, 0) || 0; bodyOverflow = document.body.style.overflow; this.options = options; this.mode = mode; this.originTable = originTable; this.dragger = dragger; this.index = mode === 'column' ? cellIndex.x : cellIndex.y; ['destroy', 'onDrag', 'onDragend', 'onShadow', 'onOut'].forEach((m) => { this[m] = this[m].bind(this); }); this.el = fakeTables.reduce((previous, current) => { const li = document.createElement('li'); li.appendChild(current); return previous.appendChild(li) && previous; }, document.createElement('ul')); this.drake = dragula([this.el], { animation: 300, staticClass: classes.static, direction: mode === 'column' ? 'horizontal' : 'vertical', }) .on('drag', this.onDrag) .on('dragend', this.onDragend) .on('shadow', this.onShadow) .on('out', this.onOut); this.renderEl(); this.dispatchMousedown(); } onDrag () { css(document.body, { overflow: 'hidden' }); const barWidth = getScrollBarWidth(); console.log(barWidth,'barWidth'); if (barWidth) { css(document.body, { 'padding-right': `${barWidth + bodyPaddingRight}px` }); } touchy(document, 'remove', 'mouseup', this.destroy); this.dragger.emit('drag', this.originTable.el, this.options.mode); } onDragend (droppedItem) { const { originTable: { el: originEl }, dragger, index, mode, el } = this; css(document.body, { overflow: bodyOverflow, 'padding-right': `${bodyPaddingRight}px` }); this.dragger.dragging = false; const from = index; const to = Array.from(el.children).indexOf(droppedItem); this.destroy(); dragger.emit('drop', from, to, originEl, mode); } onShadow (draggingItem) { const { originTable: { el: originEl }, dragger, index, el, mode } = this; const from = index; const to = Array.from(el.children).indexOf(draggingItem); dragger.emit('shadowMove', from, to, originEl, mode); } onOut () { this.dragger.dragging = false; this.dragger.emit('out', this.originTable.el, this.mode); } destroy () { remove(document, 'mouseup', this.destroy); this.el.parentElement.classList.remove(classes.dragging); this.el.parentElement.removeChild(this.el); setTimeout(() => { this.drake.destroy(); }, 0); } dispatchMousedown () { const { el, index } = this; el.children[index].dispatchEvent(getTouchyEvent()); } renderEl () { const { mode, el, originTable: { el: originEl } } = this; this.sizeFakes(); css(el, { position: 'absolute', top: `${originEl.offsetTop}px`, left: `${originEl.offsetLeft}px`, }); insertBeforeSibling({ target: el, origin: originEl }); // render every wrapper of table(element li) const spacing = window.getComputedStyle(originEl).getPropertyValue('border-spacing').split(' ')[0]; const attr = mode === 'column' ? 'margin-right' : 'margin-bottom'; const length = el.children.length; Array.from(el.children).forEach((li, dex) => { /* eslint-disable no-param-reassign*/ const table = li && li.querySelector('table'); if (this.options.onlyBody && mode === 'row' && !Array.from(table.children).some(o => o.nodeName === 'TBODY')) { li.classList.add(classes.static); } if (spacing && dex < (length - 1)) { li.style[attr] = `-${spacing}`; } }); el.parentElement.classList.add(classes.dragging); el.classList.add(classes.draggableTable); el.classList.add(`sindu_${mode}`); } sizeFakes () { return this.mode === 'column' ? this.sizeColumnFake() : this.sizeRowFake(); } sizeColumnFake () { const { fakeTables, originTable: { el: originEl } } = this; // calculate width of every column Array.from(getLongestRow(originEl).children).forEach( (cell, index) => { const w = cell.getBoundingClientRect().width; const t = fakeTables[index]; css(t, { width: `${w}px` }); css(t.rows[0].children[0], { width: `${w}px` }); } ); // calculate height of every cell const rowHeights = Array.from(originEl.rows) .map(row => row.children[0].getBoundingClientRect().height); fakeTables.forEach((t) => { /* eslint-disable no-param-reassign*/ Array.from(t.rows).forEach((row, index) => { css(row, { height: `${rowHeights[index]}px` }); }); }); } sizeRowFake () { const { fakeTables, originTable: { el: originEl } } = this; const cells = getLongestRow(originEl).children; const w = originEl.getBoundingClientRect().width; // 行排列时计算每一行各个cell宽度 /* eslint-disable no-param-reassign*/ fakeTables.forEach((t) => { css(t, { width: `${w}px` }); Array.from(t.rows[0].children).forEach((cell, i) => { css(cell, { width: `${cells[i].getBoundingClientRect().width}px` }); }); }); // fakeTables.forEach((table, index) => { // /* eslint-disable no-param-reassign*/ // table.style.height = `${originEl.rows[index].getBoundingClientRect().height}px`; // }); } } // input:clone(originTable) function origin2DragItem (liTable) { css(liTable, { 'table-layout': 'fixed', width: 'initial', height: 'initial', padding: 0, margin: 0 }); ['width', 'height', 'id'].forEach((p) => { liTable.removeAttribute(p); }); liTable.classList.remove(classes.originTable); Array.from(liTable.querySelectorAll('col')).forEach((col) => { col.removeAttribute('width'); css(col, { width: 'initial' }); }); } function getColumnAsTableByIndex (table, index) { const cTable = table.cloneNode(true); origin2DragItem(cTable); const cols = cTable.querySelectorAll('col'); if (cols.length) { Array.from(cols).forEach((col, dex) => { if (dex !== index) { col.parentElement.removeChild(col); } }); } Array.from(cTable.rows).forEach((row) => { const target = row.children[index]; empty(row); if (target) { row.appendChild(target); } }); return cTable; } function buildRowTables (table) { return Array.from(table.rows).map((row) => { const cTable = table.cloneNode(true); origin2DragItem(cTable); Array.from(cTable.children).forEach((c) => { const { nodeName } = c; if (nodeName !== 'COL' && nodeName !== 'COLGROUP') { cTable.removeChild(c); } }); const organ = row.parentNode.cloneNode(); organ.innerHTML = ''; organ.appendChild(row.cloneNode(true)); cTable.appendChild(organ); return cTable; }); } function buildColumnTables (table) { return Array.from(getLongestRow(table).children).map((cell, index) => getColumnAsTableByIndex(table, index)); } function buildTables (table, mode) { return mode === 'column' ? buildColumnTables(table) : buildRowTables(table); }