2020-02-02 15:20:49 +08:00
|
|
|
import sort from './vdom';
|
2020-01-30 20:59:37 +08:00
|
|
|
import {
|
2020-02-06 16:43:18 +08:00
|
|
|
setAttribute,
|
|
|
|
|
removeAttribute,
|
|
|
|
|
hasAttribute,
|
2020-02-06 18:51:14 +08:00
|
|
|
getAttribute,
|
2020-01-30 20:59:37 +08:00
|
|
|
appendChild,
|
2020-01-31 16:30:30 +08:00
|
|
|
appendChildren,
|
2020-01-30 20:59:37 +08:00
|
|
|
removeChild,
|
|
|
|
|
createElement,
|
|
|
|
|
querySelector,
|
2020-02-07 21:13:37 +08:00
|
|
|
insertBefore,
|
2020-02-07 14:34:40 +08:00
|
|
|
querySelectorAll,
|
|
|
|
|
offsetHeight,
|
|
|
|
|
offsetWidth,
|
|
|
|
|
styled
|
2020-01-30 20:59:37 +08:00
|
|
|
} from './node-ops';
|
2020-02-02 15:20:49 +08:00
|
|
|
import createFixed from './fixed';
|
2020-01-13 16:25:20 +08:00
|
|
|
import {
|
|
|
|
|
throttle,
|
2020-01-16 14:25:41 +08:00
|
|
|
debounce,
|
2020-02-06 18:51:14 +08:00
|
|
|
getAttrNumber,
|
2020-02-07 21:13:37 +08:00
|
|
|
createCheckbox,
|
2020-02-19 14:56:29 +08:00
|
|
|
createExpandTrigger,
|
2020-01-30 20:59:37 +08:00
|
|
|
refactorCell,
|
2020-01-31 16:30:30 +08:00
|
|
|
replaceColGroup,
|
2020-02-05 11:12:40 +08:00
|
|
|
createTableWrapper,
|
2020-02-07 14:34:40 +08:00
|
|
|
getEmptyIndexInArray,
|
2020-01-13 16:25:20 +08:00
|
|
|
} from './utils';
|
2020-01-31 16:30:30 +08:00
|
|
|
import scrollBarWidth from './scrollbar-width';
|
2020-01-13 16:25:20 +08:00
|
|
|
|
2020-01-16 17:17:57 +08:00
|
|
|
export default function initMixin(Table) {
|
2020-01-28 22:13:48 +08:00
|
|
|
Table.prototype._init = function(options = {}) {
|
2020-01-13 16:25:20 +08:00
|
|
|
if (!options.selector) {
|
2020-02-05 11:12:40 +08:00
|
|
|
return console.error("Smart Table init need a selector")
|
2020-01-13 16:25:20 +08:00
|
|
|
}
|
2020-02-05 11:12:40 +08:00
|
|
|
const selector = String(options.selector).trim()
|
|
|
|
|
const root = querySelector(document, selector)
|
|
|
|
|
if (!root) return console.error("Smart Table " + selector + " not found")
|
|
|
|
|
const table = querySelector(root, "table")
|
|
|
|
|
if (!table) return console.error("Smart Table init need a table")
|
2020-01-30 20:59:37 +08:00
|
|
|
const thead = querySelector(table, "thead")
|
2020-02-05 11:12:40 +08:00
|
|
|
if (!thead) return console.error("Smart Table init need a thead")
|
2020-01-30 20:59:37 +08:00
|
|
|
const tbody = querySelector(table, "tbody")
|
2020-02-05 11:12:40 +08:00
|
|
|
if (!tbody) return console.error("Smart Table init need a tbody")
|
2020-01-30 20:59:37 +08:00
|
|
|
|
2020-02-05 11:12:40 +08:00
|
|
|
root.classList.add("smart-table")
|
|
|
|
|
options.size && root.classList.add("stb-cust-" + options.size)
|
|
|
|
|
options.align && root.classList.add("stb-cust-" + options.align)
|
2020-02-06 16:43:18 +08:00
|
|
|
hasAttribute(table, "stripe") && tbody.classList.add("stripe")
|
|
|
|
|
|
2020-02-06 18:51:14 +08:00
|
|
|
options.expand ? (querySelectorAll(thead, 'th[sort]').forEach(column => {
|
2020-02-06 16:43:18 +08:00
|
|
|
removeAttribute(column, "sort")
|
|
|
|
|
}), querySelectorAll(thead, 'th[fixed]').forEach(column => {
|
|
|
|
|
removeAttribute(column, "fixed")
|
2020-02-06 18:51:14 +08:00
|
|
|
})) : (querySelectorAll(tbody, 'tr[expand]').forEach(column => {
|
|
|
|
|
removeAttribute(column, "expand")
|
|
|
|
|
}), querySelectorAll(thead, 'tr[expand-parent]').forEach(column => {
|
|
|
|
|
removeAttribute(column, "expand-parent")
|
2020-02-06 16:43:18 +08:00
|
|
|
}))
|
2020-01-13 16:25:20 +08:00
|
|
|
|
2020-02-05 11:12:40 +08:00
|
|
|
const vm = this;
|
2020-01-30 20:59:37 +08:00
|
|
|
vm.$root = root
|
2020-02-05 11:12:40 +08:00
|
|
|
vm.$thead = thead
|
|
|
|
|
vm.$tbody = tbody
|
|
|
|
|
vm.options = options
|
|
|
|
|
vm.gutterWidth = scrollBarWidth()
|
|
|
|
|
vm.style = {
|
2020-02-07 17:32:19 +08:00
|
|
|
radioBgColor: options.radioBgColor || '#D1E7FF',
|
2020-02-05 11:12:40 +08:00
|
|
|
hoverBgColor: options.hoverBgColor || '#EFF8FF'
|
2020-01-13 16:25:20 +08:00
|
|
|
}
|
2020-02-05 17:10:11 +08:00
|
|
|
vm.size = {}
|
2020-02-07 21:13:37 +08:00
|
|
|
vm.hasCheckbox = !options.expand && options.selection === 'checkbox'
|
2020-02-19 14:56:29 +08:00
|
|
|
vm.hasExpandCb = !!options.expandCallback
|
|
|
|
|
|
|
|
|
|
vm.hasExpandCb && appendExpandTrigger(vm)
|
2020-02-07 21:13:37 +08:00
|
|
|
|
|
|
|
|
vm.hasCheckbox && appendCheckbox(vm)
|
2020-01-20 11:28:19 +08:00
|
|
|
|
2020-01-13 16:25:20 +08:00
|
|
|
//初始化thead 并获取props
|
2020-02-05 17:10:11 +08:00
|
|
|
initProps(vm)
|
2020-02-05 11:12:40 +08:00
|
|
|
layout(vm, table)
|
2020-01-13 16:25:20 +08:00
|
|
|
|
2020-02-06 16:43:18 +08:00
|
|
|
if (!options.expand) {
|
|
|
|
|
//初始化fixed元素及宽度
|
|
|
|
|
initFixed(vm)
|
|
|
|
|
createFixed(vm, thead, tbody)
|
|
|
|
|
}
|
2020-01-13 16:25:20 +08:00
|
|
|
|
|
|
|
|
//获取tbody的data数据
|
2020-02-05 17:10:11 +08:00
|
|
|
initData(vm, tbody)
|
2020-02-06 16:43:18 +08:00
|
|
|
options.expand && initExpand(vm, tbody)
|
2020-02-05 17:10:11 +08:00
|
|
|
bindEvents(vm)
|
2020-01-13 16:25:20 +08:00
|
|
|
|
2020-02-05 17:10:11 +08:00
|
|
|
const th = createElement("th");
|
2020-02-07 14:34:40 +08:00
|
|
|
styled(th, { display: 'none' })
|
2020-02-06 16:43:18 +08:00
|
|
|
setAttribute(th, "width", vm.gutterWidth);
|
|
|
|
|
setAttribute(th, "rowspan", vm.props.shapes.length);
|
2020-02-05 17:10:11 +08:00
|
|
|
appendChild(querySelector(vm.$thead, "tr"), th);
|
|
|
|
|
vm.$scrollTH = th;
|
2020-01-31 16:30:30 +08:00
|
|
|
if (vm.scrollY) {
|
2020-02-07 14:34:40 +08:00
|
|
|
styled(vm.$scrollTH, { display: 'table-cell' })
|
2020-02-05 17:10:11 +08:00
|
|
|
resize(vm)
|
2020-01-13 16:25:20 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-19 14:56:29 +08:00
|
|
|
function appendExpandTrigger(vm) {
|
|
|
|
|
const { $thead, $tbody } = vm;
|
|
|
|
|
let theadRow = querySelector($thead, "tr");
|
|
|
|
|
let th = theadRow.querySelector("th");
|
|
|
|
|
let cell = createExpandTrigger("th", getAttrNumber(th, "rowspan", 1));
|
|
|
|
|
hasAttribute(th, "fixed") && setAttribute(cell, "fixed")
|
|
|
|
|
insertBefore(theadRow, cell, th)
|
|
|
|
|
querySelectorAll($tbody, "tr").forEach(row => {
|
|
|
|
|
let td = row.querySelector("td")
|
|
|
|
|
insertBefore(row, createExpandTrigger("td", getAttrNumber(td, "rowspan", 1)), td)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-07 21:13:37 +08:00
|
|
|
function appendCheckbox(vm) {
|
|
|
|
|
const { $thead, $tbody } = vm;
|
|
|
|
|
let theadRow = querySelector($thead, "tr");
|
|
|
|
|
let th = theadRow.querySelector("th");
|
2020-02-19 14:56:29 +08:00
|
|
|
let cell = createCheckbox("th", getAttrNumber(th, "rowspan", 1));
|
|
|
|
|
hasAttribute(th, "fixed") && setAttribute(cell, "fixed")
|
|
|
|
|
insertBefore(theadRow, cell, th)
|
2020-02-07 21:13:37 +08:00
|
|
|
querySelectorAll($tbody, "tr").forEach(row => {
|
|
|
|
|
let td = row.querySelector("td")
|
|
|
|
|
insertBefore(row, createCheckbox("td", getAttrNumber(td, "rowspan", 1)), td)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-05 11:12:40 +08:00
|
|
|
function layout(vm, table) {
|
|
|
|
|
const { $root, $thead, $tbody, options } = vm;
|
2020-02-07 21:13:37 +08:00
|
|
|
const { height } = options;
|
|
|
|
|
|
2020-02-05 11:12:40 +08:00
|
|
|
querySelectorAll($thead, "th").forEach(cell => refactorCell(cell))
|
|
|
|
|
querySelectorAll($tbody, "td").forEach(cell => refactorCell(cell))
|
|
|
|
|
|
|
|
|
|
//初始化colgroup数据数组
|
|
|
|
|
initColgroupData(vm);
|
|
|
|
|
|
|
|
|
|
//初始化table 拆分table的thead和tbody
|
|
|
|
|
vm.$theadWrapper = createTableWrapper("stb_header-wrapper", vm, "header", $thead);
|
|
|
|
|
vm.$tbodyWrapper = createTableWrapper("stb_body-wrapper", vm, "body", $tbody);
|
|
|
|
|
appendChildren($root, [vm.$theadWrapper, vm.$tbodyWrapper]);
|
|
|
|
|
|
2020-02-07 14:34:40 +08:00
|
|
|
const theadHeight = offsetHeight($thead);
|
|
|
|
|
const custHeight = (typeof height === 'function' ? height.call() : height) || offsetHeight($root);
|
|
|
|
|
const tbodyWrapperHeight = custHeight > theadHeight ? (custHeight - theadHeight - 1) : (theadHeight + 150)
|
|
|
|
|
styled(vm.$tbodyWrapper, { height: tbodyWrapperHeight + "px" })
|
2020-02-05 11:12:40 +08:00
|
|
|
|
|
|
|
|
vm.size.tbodyWrapperHeight = tbodyWrapperHeight;
|
|
|
|
|
|
|
|
|
|
//垂直方向是否有滚动条
|
2020-02-07 14:34:40 +08:00
|
|
|
vm.scrollY = offsetHeight(vm.$tbody) > tbodyWrapperHeight;
|
2020-02-05 11:12:40 +08:00
|
|
|
//删除空余的table节点
|
|
|
|
|
removeChild(table.parentNode, table);
|
2020-01-13 16:25:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//根据表格中的tbody第一行 查出每列的宽度并记录
|
2020-02-05 11:12:40 +08:00
|
|
|
function initColgroupData(vm) {
|
|
|
|
|
const { $root, props } = vm;
|
2020-02-07 14:34:40 +08:00
|
|
|
const rootWidth = offsetWidth($root) - 1;
|
|
|
|
|
const clientWidth = rootWidth - (vm.scrollY ? vm.gutterWidth : 0);
|
2020-01-13 16:25:20 +08:00
|
|
|
let arr = [];
|
2020-02-05 11:12:40 +08:00
|
|
|
let totalWidth = 0;
|
|
|
|
|
props.shapes.forEach(shape => {
|
|
|
|
|
shape.forEach((column, cIndex) => {
|
|
|
|
|
if (column) {
|
2020-02-06 18:51:14 +08:00
|
|
|
let colspan = getAttrNumber(column, 'colspan', 1)
|
2020-02-05 11:12:40 +08:00
|
|
|
if (colspan === 1) {
|
2020-02-06 18:51:14 +08:00
|
|
|
arr[cIndex] = getAttrNumber(column, 'width', 0)
|
2020-02-05 11:12:40 +08:00
|
|
|
}
|
2020-01-17 15:02:45 +08:00
|
|
|
}
|
|
|
|
|
})
|
2020-02-05 11:12:40 +08:00
|
|
|
})
|
|
|
|
|
let zeroLen = 0;
|
|
|
|
|
arr.forEach(item => {
|
|
|
|
|
totalWidth += item
|
|
|
|
|
item === 0 && zeroLen++
|
|
|
|
|
})
|
|
|
|
|
if (zeroLen) {
|
2020-02-05 17:10:11 +08:00
|
|
|
const per = Math.floor((clientWidth - totalWidth) / zeroLen)
|
|
|
|
|
const min = per > 80 ? per : 80;
|
2020-02-05 11:12:40 +08:00
|
|
|
let lastZeroIndex = 0;
|
|
|
|
|
totalWidth = 0;
|
|
|
|
|
arr = arr.map((item, index) => {
|
|
|
|
|
if (item === 0) {
|
2020-02-19 14:56:29 +08:00
|
|
|
if ((vm.hasCheckbox || vm.hasExpandCb) && index === 0) {
|
|
|
|
|
item = 55;
|
2020-02-07 21:13:37 +08:00
|
|
|
} else {
|
|
|
|
|
item = min;
|
|
|
|
|
}
|
2020-02-05 11:12:40 +08:00
|
|
|
lastZeroIndex = index;
|
2020-01-17 15:02:45 +08:00
|
|
|
}
|
2020-02-05 11:12:40 +08:00
|
|
|
totalWidth += item
|
|
|
|
|
return item
|
2020-01-17 15:02:45 +08:00
|
|
|
})
|
2020-02-05 11:12:40 +08:00
|
|
|
if (clientWidth > totalWidth) {
|
|
|
|
|
arr[lastZeroIndex] = arr[lastZeroIndex] + clientWidth - totalWidth;
|
|
|
|
|
totalWidth = clientWidth
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
totalWidth = arr.reduce((item, sum) => sum + item, 0)
|
|
|
|
|
}
|
|
|
|
|
vm.colgroup = arr;
|
2020-02-07 14:34:40 +08:00
|
|
|
vm.size.rootWidth = rootWidth
|
2020-02-05 17:10:11 +08:00
|
|
|
vm.size.tableWidth = totalWidth
|
|
|
|
|
vm.scrollX = vm.size.tableWidth > vm.size.rootWidth;
|
2020-01-13 16:25:20 +08:00
|
|
|
}
|
|
|
|
|
|
2020-02-05 11:12:40 +08:00
|
|
|
function bindResizeEvents(vm) {
|
2020-02-05 17:10:11 +08:00
|
|
|
window.addEventListener("resize", () => resize(vm), {
|
|
|
|
|
passive: true
|
|
|
|
|
})
|
2020-02-05 11:12:40 +08:00
|
|
|
}
|
|
|
|
|
|
2020-01-16 17:17:57 +08:00
|
|
|
function bindEvents(vm) {
|
2020-02-06 16:43:18 +08:00
|
|
|
bindScrollEvents(vm);
|
2020-02-07 17:32:19 +08:00
|
|
|
bindRowEvents(vm);
|
2020-02-19 14:56:29 +08:00
|
|
|
vm.options.expand ? bindExpandTreeEvents(vm) : bindSortEvents(vm);
|
2020-02-06 16:43:18 +08:00
|
|
|
bindResizeEvents(vm);
|
2020-01-16 14:25:41 +08:00
|
|
|
}
|
|
|
|
|
|
2020-02-05 17:10:11 +08:00
|
|
|
function resize(vm) {
|
|
|
|
|
debounce(500, () => {
|
|
|
|
|
const { fixedLeft, fixedRight } = vm.props;
|
|
|
|
|
initColgroupData(vm)
|
|
|
|
|
replaceColGroup(vm)
|
|
|
|
|
|
2020-02-07 14:34:40 +08:00
|
|
|
vm.scrollY = offsetHeight(vm.$tbody) > vm.size.tbodyWrapperHeight;
|
|
|
|
|
styled(vm.$scrollTH, {
|
|
|
|
|
display: vm.scrollY ? 'table-cell' : 'none'
|
|
|
|
|
})
|
2020-02-05 17:10:11 +08:00
|
|
|
|
2020-02-07 14:34:40 +08:00
|
|
|
let height = (offsetHeight(vm.$root) - (vm.scrollX ? vm.gutterWidth : 2));
|
|
|
|
|
const tableHeight = offsetHeight(vm.$thead) + offsetHeight(vm.$tbody);
|
2020-02-05 17:10:11 +08:00
|
|
|
height = tableHeight > height ? height : tableHeight
|
|
|
|
|
|
|
|
|
|
const bodyWrapperHeight = vm.size.tbodyWrapperHeight - (vm.scrollX ? vm.gutterWidth : 0);
|
2020-02-07 14:34:40 +08:00
|
|
|
const bodyWrapperTop = offsetHeight(vm.$thead);
|
2020-02-05 17:10:11 +08:00
|
|
|
let fixedLeftWidth = 0;
|
|
|
|
|
let fixedRightWidth = 0;
|
|
|
|
|
if (vm.$fixedLeft && fixedLeft.thead.length) {
|
|
|
|
|
fixedLeft.thead.forEach((item, index) => {
|
|
|
|
|
fixedLeftWidth += vm.colgroup[index]
|
|
|
|
|
})
|
2020-02-07 14:34:40 +08:00
|
|
|
styled(vm.$fixedLeftBody, {
|
|
|
|
|
height: bodyWrapperHeight + "px",
|
|
|
|
|
top: bodyWrapperTop + "px"
|
|
|
|
|
})
|
|
|
|
|
styled(vm.$fixedLeft, {
|
|
|
|
|
width: fixedLeftWidth + "px",
|
|
|
|
|
height: height + "px"
|
|
|
|
|
})
|
2020-02-05 17:10:11 +08:00
|
|
|
}
|
|
|
|
|
if (vm.$fixedRight && fixedRight.thead.length) {
|
|
|
|
|
fixedRight.thead.forEach((item, index) => {
|
|
|
|
|
fixedRightWidth += vm.colgroup[vm.colgroup.length - index - 1]
|
|
|
|
|
})
|
2020-02-07 14:34:40 +08:00
|
|
|
styled(vm.$fixedRightBody, {
|
|
|
|
|
height: bodyWrapperHeight + "px",
|
|
|
|
|
top: bodyWrapperTop + "px"
|
|
|
|
|
})
|
|
|
|
|
styled(vm.$fixedRight, {
|
|
|
|
|
width: fixedRightWidth + "px",
|
|
|
|
|
height: height + "px",
|
|
|
|
|
right: (vm.scrollY ? vm.gutterWidth : 0) + "px"
|
|
|
|
|
})
|
|
|
|
|
styled(vm.$rightPatch, {
|
|
|
|
|
display: vm.scrollY ? 'block' : 'none',
|
|
|
|
|
height: offsetHeight(vm.$thead) + "px"
|
|
|
|
|
})
|
2020-02-05 17:10:11 +08:00
|
|
|
}
|
|
|
|
|
})()
|
2020-01-13 16:25:20 +08:00
|
|
|
}
|
|
|
|
|
|
2020-01-16 17:17:57 +08:00
|
|
|
function syncPostion(vm) {
|
2020-01-13 16:25:20 +08:00
|
|
|
throttle(20, () => {
|
|
|
|
|
vm.$theadWrapper.scrollLeft = vm.$tbodyWrapper.scrollLeft;
|
2020-02-05 17:10:11 +08:00
|
|
|
if (vm.$fixedLeftBody) {
|
|
|
|
|
vm.$fixedLeftBody.scrollTop = vm.$tbodyWrapper.scrollTop;
|
2020-01-13 16:25:20 +08:00
|
|
|
}
|
2020-02-05 17:10:11 +08:00
|
|
|
if (vm.$fixedRightBody) {
|
|
|
|
|
vm.$fixedRightBody.scrollTop = vm.$tbodyWrapper.scrollTop;
|
2020-01-13 16:25:20 +08:00
|
|
|
}
|
|
|
|
|
})()
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-19 14:56:29 +08:00
|
|
|
function bindExpandTreeEvents(vm) {
|
2020-02-06 16:43:18 +08:00
|
|
|
function seek(arr) {
|
|
|
|
|
arr.forEach(item => {
|
|
|
|
|
if (item.expand) {
|
2020-02-06 18:51:14 +08:00
|
|
|
querySelector(item.$el, "td").addEventListener('click', () => {
|
|
|
|
|
expanding(item, !hasAttribute(item.$el, "expanded"))
|
2020-02-06 16:43:18 +08:00
|
|
|
})
|
2020-02-06 18:51:14 +08:00
|
|
|
item.children && seek(item.children)
|
2020-02-06 16:43:18 +08:00
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
2020-02-06 18:51:14 +08:00
|
|
|
function expanding(item, expanded) {
|
|
|
|
|
expanded ? setAttribute(item.$el, "expanded") : removeAttribute(item.$el, "expanded");
|
|
|
|
|
item.children && (item.children.forEach(child => {
|
2020-02-07 14:34:40 +08:00
|
|
|
styled(child.$el, { display: expanded ? '' : 'none' })
|
2020-02-06 18:51:14 +08:00
|
|
|
expanding(child, expanded)
|
|
|
|
|
}))
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-02-06 16:43:18 +08:00
|
|
|
seek(vm.expandData)
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-02 15:20:49 +08:00
|
|
|
function bindScrollEvents(vm) {
|
|
|
|
|
vm.$tbodyWrapper.addEventListener("scroll", () => syncPostion(vm), {
|
|
|
|
|
passive: true
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-07 17:32:19 +08:00
|
|
|
function bindRowEvents(vm) {
|
2020-02-19 14:56:29 +08:00
|
|
|
let { selection, selectionKey } = vm.options;
|
|
|
|
|
selectionKey = selectionKey || 0;
|
|
|
|
|
vm.hasExpandCb && (selectionKey++)
|
2020-02-07 21:13:37 +08:00
|
|
|
const totalCheckbox = querySelector(vm.$fixedLeft || vm.$thead, "th>.stb_cell>label.std-checkbox");
|
2020-02-07 17:32:19 +08:00
|
|
|
[].concat(vm.data, vm.unsortData).forEach(row => {
|
|
|
|
|
addHoverEvent(vm, row.$el, [row.$fixedLeftEl, row.$fixedRightEl])
|
|
|
|
|
row.$fixedLeftEl && addHoverEvent(vm, row.$fixedLeftEl, [row.$el, row.$fixedRightEl])
|
|
|
|
|
row.$fixedRightEl && addHoverEvent(vm, row.$fixedRightEl, [row.$el, row.$fixedLeftEl])
|
2020-02-19 14:56:29 +08:00
|
|
|
const value = row['field-' + selectionKey]
|
2020-02-07 21:13:37 +08:00
|
|
|
if (selection) {
|
|
|
|
|
switch (selection) {
|
|
|
|
|
case 'radio':
|
|
|
|
|
addRadioEvent(vm, row.$el, [row.$fixedLeftEl, row.$fixedRightEl], value)
|
|
|
|
|
row.$fixedLeftEl && addRadioEvent(vm, row.$fixedLeftEl, [row.$el, row.$fixedRightEl], value)
|
|
|
|
|
row.$fixedRightEl && addRadioEvent(vm, row.$fixedRightEl, [row.$el, row.$fixedLeftEl], value)
|
|
|
|
|
break
|
|
|
|
|
case 'checkbox':
|
|
|
|
|
addCheckboxEvent(vm, row.$fixedLeftEl || row.$el, totalCheckbox, value)
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-02-19 14:56:29 +08:00
|
|
|
vm.hasExpandCb && addExpandTriggerEvent(vm, row.$fixedLeftEl || row.$el, value)
|
2020-02-07 21:13:37 +08:00
|
|
|
})
|
|
|
|
|
if (vm.hasCheckbox) {
|
|
|
|
|
addTotalCheckboxEvent(vm, totalCheckbox)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-19 14:56:29 +08:00
|
|
|
function addExpandTriggerEvent(vm, el, value) {
|
|
|
|
|
const { options } = vm;
|
|
|
|
|
const trigger = querySelector(el, ".expand-cell>.stb_cell")
|
|
|
|
|
if (!trigger) return;
|
|
|
|
|
trigger.addEventListener('click', ($event) => {
|
|
|
|
|
options.expandCallback.call(this, {
|
|
|
|
|
open: function(content, needParse) {
|
|
|
|
|
console.log(content, needParse)
|
|
|
|
|
}
|
|
|
|
|
}, value)
|
|
|
|
|
$event.stopPropagation();
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-02-07 21:13:37 +08:00
|
|
|
function addCheckboxEvent(vm, row, totalCheckbox, value) {
|
|
|
|
|
const trigger = querySelector(row, "label.std-checkbox")
|
|
|
|
|
if (!trigger || !totalCheckbox) return;
|
|
|
|
|
trigger.addEventListener('click', () => {
|
|
|
|
|
let { selected } = vm;
|
|
|
|
|
selected = selected || [];
|
|
|
|
|
const target = !hasAttribute(trigger, "checked");
|
|
|
|
|
target ? setAttribute(trigger, 'checked', true) : removeAttribute(trigger, 'checked')
|
|
|
|
|
target ? selected.push(value) : selected.splice(selected.indexOf(value), 1)
|
|
|
|
|
const len = selected.length;
|
2020-02-08 14:16:16 +08:00
|
|
|
len ? setAttribute(vm.$root, 'selected', JSON.stringify(selected)) : removeAttribute(vm.$root, 'selected');
|
2020-02-07 21:13:37 +08:00
|
|
|
if (len === (vm.data.length + vm.unsortData.length)) {
|
|
|
|
|
setAttribute(totalCheckbox, 'checked', true)
|
|
|
|
|
} else {
|
|
|
|
|
removeAttribute(totalCheckbox, 'checked')
|
2020-02-07 17:32:19 +08:00
|
|
|
}
|
2020-02-07 21:13:37 +08:00
|
|
|
vm.selected = selected;
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function addTotalCheckboxEvent(vm, totalCheckbox) {
|
|
|
|
|
if (!totalCheckbox) return;
|
|
|
|
|
const { selectionKey } = vm.options;
|
|
|
|
|
totalCheckbox.addEventListener('click', () => {
|
|
|
|
|
let { selected } = vm;
|
|
|
|
|
selected = [];
|
|
|
|
|
const target = !hasAttribute(totalCheckbox, "checked");
|
|
|
|
|
target ? setAttribute(totalCheckbox, 'checked', true) : removeAttribute(totalCheckbox, 'checked');
|
|
|
|
|
[].concat(vm.data, vm.unsortData).forEach(row => {
|
|
|
|
|
let trigger = querySelector(row.$fixedLeftEl || row.$el, "label.std-checkbox")
|
|
|
|
|
target ? setAttribute(trigger, 'checked', true) : removeAttribute(trigger, 'checked')
|
|
|
|
|
target && selected.push(row['field-' + (selectionKey || 0)])
|
|
|
|
|
})
|
|
|
|
|
const len = selected.length;
|
2020-02-08 14:16:16 +08:00
|
|
|
len ? setAttribute(vm.$root, 'selected', JSON.stringify(selected)) : removeAttribute(vm.$root, 'selected');
|
2020-02-07 21:13:37 +08:00
|
|
|
vm.selected = selected;
|
2020-02-07 17:32:19 +08:00
|
|
|
})
|
|
|
|
|
}
|
2020-02-05 17:10:11 +08:00
|
|
|
|
2020-02-07 17:32:19 +08:00
|
|
|
function addRadioEvent(vm, trigger, relates, radioValue) {
|
|
|
|
|
if (!trigger) return;
|
|
|
|
|
trigger.addEventListener('click', () => {
|
|
|
|
|
let { selected } = vm;
|
2020-02-07 17:50:49 +08:00
|
|
|
let target = false;
|
|
|
|
|
if (selected === radioValue && !hasAttribute(trigger, "checked")) return;
|
2020-02-07 17:32:19 +08:00
|
|
|
if (selected !== radioValue) {
|
|
|
|
|
querySelectorAll(vm.$root, 'tr[checked]>td').forEach(item => styled(item, { background: '' }))
|
|
|
|
|
querySelectorAll(vm.$root, 'tr[checked]').forEach(item => removeAttribute(item, "checked"))
|
2020-02-07 17:50:49 +08:00
|
|
|
target = true;
|
2020-02-07 17:32:19 +08:00
|
|
|
} else {
|
|
|
|
|
if (hasAttribute(trigger, "checked")) {
|
2020-02-07 17:50:49 +08:00
|
|
|
target = false;
|
2020-02-07 17:32:19 +08:00
|
|
|
}
|
|
|
|
|
}
|
2020-02-07 17:50:49 +08:00
|
|
|
selected = target ? radioValue : null;
|
|
|
|
|
target ? setAttribute(trigger, "checked", true) : removeAttribute(trigger, "checked");
|
|
|
|
|
trigger.querySelectorAll("td").forEach(column => {
|
|
|
|
|
styled(column, { background: target ? vm.style.radioBgColor : '' })
|
|
|
|
|
})
|
|
|
|
|
relates.forEach(item => {
|
|
|
|
|
if (item) {
|
|
|
|
|
target ? setAttribute(item, "checked", true) : removeAttribute(item, "checked")
|
|
|
|
|
item.querySelectorAll("td").forEach(column => {
|
|
|
|
|
styled(column, { background: target ? vm.style.radioBgColor : '' })
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
})
|
2020-02-08 14:16:16 +08:00
|
|
|
target ? setAttribute(vm.$root, 'selected', JSON.stringify(selected)) : removeAttribute(vm.$root, 'selected');
|
2020-02-07 17:32:19 +08:00
|
|
|
vm.selected = selected;
|
2020-02-05 17:10:11 +08:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-07 17:32:19 +08:00
|
|
|
function addHoverEvent(vm, trigger, relates) {
|
2020-02-05 17:10:11 +08:00
|
|
|
if (!trigger) return;
|
|
|
|
|
trigger.addEventListener('mouseenter', () => {
|
2020-02-07 14:34:40 +08:00
|
|
|
styled(trigger, { background: vm.style.hoverBgColor })
|
2020-02-05 17:10:11 +08:00
|
|
|
relates.forEach(el => {
|
2020-02-07 14:34:40 +08:00
|
|
|
el && styled(el, { background: vm.style.hoverBgColor })
|
2020-02-02 15:20:49 +08:00
|
|
|
})
|
2020-02-05 17:10:11 +08:00
|
|
|
})
|
|
|
|
|
trigger.addEventListener('mouseleave', () => {
|
2020-02-07 14:34:40 +08:00
|
|
|
styled(trigger, { background: '' })
|
2020-02-05 17:10:11 +08:00
|
|
|
relates.forEach(el => {
|
2020-02-07 14:34:40 +08:00
|
|
|
el && styled(el, { background: '' })
|
2020-02-02 15:20:49 +08:00
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function bindSortEvents(vm) {
|
2020-01-30 20:59:37 +08:00
|
|
|
let els = Array.from(querySelectorAll(vm.$root, "th[sort]"));
|
2020-01-13 16:25:20 +08:00
|
|
|
if (els.length === 0) return;
|
|
|
|
|
els.forEach(el => {
|
|
|
|
|
el.addEventListener("click", $event => {
|
|
|
|
|
$event.stopPropagation();
|
|
|
|
|
let sortType = "ASC";
|
2020-02-06 18:51:14 +08:00
|
|
|
let sortOrder = getAttribute(el, "sort") || "string";
|
2020-01-13 16:25:20 +08:00
|
|
|
if (el.classList.contains("asc")) {
|
|
|
|
|
el.classList.remove("asc");
|
|
|
|
|
el.classList.add("desc");
|
|
|
|
|
sortType = "DESC"
|
|
|
|
|
} else {
|
|
|
|
|
el.classList.remove("desc");
|
|
|
|
|
el.classList.add("asc");
|
|
|
|
|
}
|
|
|
|
|
els = els.map(item => {
|
|
|
|
|
if (el != item) {
|
|
|
|
|
item.classList.remove("asc", "desc")
|
|
|
|
|
}
|
|
|
|
|
return item
|
|
|
|
|
})
|
2020-02-06 18:51:14 +08:00
|
|
|
sort(vm, getAttribute(el, "sortkey"), sortType, sortOrder)
|
2020-01-13 16:25:20 +08:00
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-05 17:10:11 +08:00
|
|
|
function initProps(vm) {
|
2020-01-13 16:25:20 +08:00
|
|
|
let props = {};
|
|
|
|
|
//创建表头单元格二维数组
|
|
|
|
|
let shapes = [];
|
2020-02-05 17:10:11 +08:00
|
|
|
let rows = querySelectorAll(vm.$thead, "tr");
|
2020-01-13 16:25:20 +08:00
|
|
|
rows.forEach((row, index) => {
|
|
|
|
|
let shape = shapes[index] || [];
|
2020-01-30 20:59:37 +08:00
|
|
|
let columns = querySelectorAll(row, "th");
|
2020-01-13 16:25:20 +08:00
|
|
|
columns.forEach((column) => {
|
2020-02-06 18:51:14 +08:00
|
|
|
let rowspan = getAttrNumber(column, "rowspan", 1);
|
|
|
|
|
let colspan = getAttrNumber(column, "colspan", 1);
|
2020-01-13 16:25:20 +08:00
|
|
|
let insertIndex = getEmptyIndexInArray(shape) || shape.length;
|
|
|
|
|
shape[insertIndex] = column;
|
|
|
|
|
|
2020-02-06 16:43:18 +08:00
|
|
|
if (hasAttribute(column, "sort")) {
|
|
|
|
|
setAttribute(column, "sortkey", "field-" + insertIndex);
|
2020-01-13 16:25:20 +08:00
|
|
|
}
|
|
|
|
|
if (colspan > 1) {
|
|
|
|
|
for (let i = 1; i < colspan; i++) {
|
|
|
|
|
shape[insertIndex + i] = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rowspan > 1) {
|
|
|
|
|
for (let i = 1; i < rowspan; i++) {
|
|
|
|
|
let next = shapes[index + i] || [];
|
|
|
|
|
for (let j = 0; j < colspan; j++) {
|
|
|
|
|
next[insertIndex + j] = 0;
|
|
|
|
|
}
|
|
|
|
|
shapes[index + i] = next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
shapes[index] = shape;
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
props.shapes = shapes;
|
2020-02-05 17:10:11 +08:00
|
|
|
vm.props = props;
|
2020-01-13 16:25:20 +08:00
|
|
|
}
|
|
|
|
|
|
2020-02-05 17:10:11 +08:00
|
|
|
function initFixed(vm) {
|
2020-01-13 16:25:20 +08:00
|
|
|
let {
|
|
|
|
|
colgroup,
|
|
|
|
|
props
|
|
|
|
|
} = vm;
|
2020-02-02 15:20:49 +08:00
|
|
|
const colgroupLen = colgroup.length;
|
2020-01-13 16:25:20 +08:00
|
|
|
let fixedLeft = {
|
|
|
|
|
thead: [],
|
|
|
|
|
tbody: [],
|
|
|
|
|
width: 0
|
|
|
|
|
};
|
|
|
|
|
let fixedRight = {
|
|
|
|
|
thead: [],
|
|
|
|
|
tbody: [],
|
|
|
|
|
width: 0
|
|
|
|
|
};
|
2020-02-05 17:10:11 +08:00
|
|
|
const columns = querySelectorAll(vm.$thead, "tr:first-child>th");
|
2020-01-13 16:25:20 +08:00
|
|
|
const len = columns.length;
|
|
|
|
|
let lastLeftIndex = 0;
|
|
|
|
|
if (len !== 0) {
|
2020-02-06 16:43:18 +08:00
|
|
|
if (hasAttribute(columns[0], "fixed")) {
|
2020-01-13 16:25:20 +08:00
|
|
|
//判断左边固定项 不判断最后一项做为左固定项目
|
|
|
|
|
for (let i = 0; i < len - 1; i++) {
|
2020-02-06 16:43:18 +08:00
|
|
|
if (hasAttribute(columns[i], "fixed")) {
|
2020-01-13 16:25:20 +08:00
|
|
|
lastLeftIndex = i;
|
|
|
|
|
fixedLeft.thead.push("field-" + i);
|
2020-02-06 18:51:14 +08:00
|
|
|
let colspan = getAttrNumber(columns[i], "colspan", 1);
|
2020-01-13 16:25:20 +08:00
|
|
|
for (let j = 0; j < colspan; j++) {
|
|
|
|
|
fixedLeft.tbody.push("field-" + (i + j));
|
2020-02-05 17:10:11 +08:00
|
|
|
fixedLeft.width += colgroup[i + j];
|
2020-01-13 16:25:20 +08:00
|
|
|
}
|
2020-02-05 17:10:11 +08:00
|
|
|
} else {
|
|
|
|
|
break;
|
2020-01-13 16:25:20 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-02-06 16:43:18 +08:00
|
|
|
if (hasAttribute(columns[len - 1], "fixed")) {
|
2020-01-13 16:25:20 +08:00
|
|
|
//判断右边边固定项 不判断第一项做为右边固定项目
|
|
|
|
|
let rightCnt = 0;
|
|
|
|
|
for (let i = len - 1; i > 0; i--) {
|
2020-02-06 16:43:18 +08:00
|
|
|
if (hasAttribute(columns[i], "fixed")) {
|
2020-01-13 16:25:20 +08:00
|
|
|
//左右固定项目重叠时 跳出
|
|
|
|
|
if (i === lastLeftIndex) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
fixedRight.thead.push("field-" + i);
|
2020-02-06 18:51:14 +08:00
|
|
|
let colspan = getAttrNumber(columns[i], "colspan", 1);
|
2020-01-13 16:25:20 +08:00
|
|
|
for (let j = 0; j < colspan; j++) {
|
|
|
|
|
rightCnt++;
|
2020-02-02 15:20:49 +08:00
|
|
|
fixedRight.tbody.push("field-" + (colgroupLen - rightCnt))
|
2020-02-05 17:10:11 +08:00
|
|
|
fixedRight.width += colgroup[colgroupLen - rightCnt];
|
2020-01-13 16:25:20 +08:00
|
|
|
}
|
2020-02-05 17:10:11 +08:00
|
|
|
} else {
|
|
|
|
|
break;
|
2020-01-13 16:25:20 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
props.fixedLeft = fixedLeft;
|
|
|
|
|
props.fixedRight = fixedRight;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-06 16:43:18 +08:00
|
|
|
function initExpand(vm, tbody) {
|
2020-02-06 18:51:14 +08:00
|
|
|
const expandAll = vm.options.defaultExpandAll;
|
2020-02-06 16:43:18 +08:00
|
|
|
let data = [];
|
|
|
|
|
let parents = [];
|
|
|
|
|
querySelectorAll(tbody, "tr").forEach(row => {
|
2020-02-06 18:51:14 +08:00
|
|
|
let paddingLength = parents.length;
|
2020-02-06 16:43:18 +08:00
|
|
|
let expand = hasAttribute(row, "expand");
|
2020-02-06 18:51:14 +08:00
|
|
|
let hasParent = hasAttribute(row, "expand-parent");
|
|
|
|
|
let node = { $el: row, id: getAttribute(row, "expand"), expand: expand };
|
2020-02-06 16:43:18 +08:00
|
|
|
if (expand) {
|
2020-02-06 18:51:14 +08:00
|
|
|
if (expandAll) {
|
2020-02-06 16:43:18 +08:00
|
|
|
setAttribute(row, 'expanded')
|
|
|
|
|
} else {
|
|
|
|
|
removeAttribute(row, 'expanded')
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-02-06 18:51:14 +08:00
|
|
|
if (expand && !hasParent) {
|
2020-02-06 16:43:18 +08:00
|
|
|
node.children = [];
|
|
|
|
|
parents = [node];
|
|
|
|
|
data.push(node);
|
2020-02-06 18:51:14 +08:00
|
|
|
} else if (hasParent) {
|
|
|
|
|
let parentId = getAttribute(row, "expand-parent");
|
|
|
|
|
let arr = [];
|
|
|
|
|
for (let i = 0; i < parents.length; i++) {
|
|
|
|
|
arr.push(parents[i])
|
|
|
|
|
if (parents[i].id === parentId) {
|
|
|
|
|
break
|
|
|
|
|
}
|
2020-02-06 16:43:18 +08:00
|
|
|
}
|
2020-02-06 18:51:14 +08:00
|
|
|
parents = arr;
|
|
|
|
|
paddingLength = parents.length;
|
|
|
|
|
let parent = parents[parents.length - 1];
|
|
|
|
|
parent && parent.children.push(node);
|
|
|
|
|
if (expand) {
|
|
|
|
|
parents.push(node)
|
|
|
|
|
node.children = [];
|
2020-02-06 16:43:18 +08:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
data.push(node)
|
|
|
|
|
}
|
2020-02-06 18:51:14 +08:00
|
|
|
if (hasParent) {
|
2020-02-08 12:11:25 +08:00
|
|
|
styled(querySelector(row, "td"), { paddingLeft: 32 * paddingLength + "px" })
|
2020-02-07 14:34:40 +08:00
|
|
|
styled(row, { display: expandAll ? '' : 'none' })
|
2020-02-06 18:51:14 +08:00
|
|
|
}
|
2020-02-06 16:43:18 +08:00
|
|
|
})
|
|
|
|
|
vm.expandData = data;
|
2020-02-07 14:34:40 +08:00
|
|
|
styled(vm.$tbodyWrapper, { height: '' })
|
2020-02-06 16:43:18 +08:00
|
|
|
}
|
|
|
|
|
|
2020-01-16 17:17:57 +08:00
|
|
|
function initData(vm, tbody) {
|
2020-02-05 17:10:11 +08:00
|
|
|
let fixedLeftRows = vm.$fixedLeftBody && querySelectorAll(vm.$fixedLeftBody, "tbody tr");
|
|
|
|
|
let fixedRightRows = vm.$fixedRightBody && querySelectorAll(vm.$fixedRightBody, "tbody tr");
|
2020-01-13 16:25:20 +08:00
|
|
|
let data = [];
|
2020-02-05 17:10:11 +08:00
|
|
|
let unsortData = [];
|
2020-01-30 20:59:37 +08:00
|
|
|
querySelectorAll(tbody, "tr").forEach((row, index) => {
|
2020-02-05 17:10:11 +08:00
|
|
|
let rowData = {
|
|
|
|
|
$el: row,
|
|
|
|
|
$fixedLeftEl: fixedLeftRows && fixedLeftRows[index],
|
|
|
|
|
$fixedRightEl: fixedRightRows && fixedRightRows[index],
|
|
|
|
|
$key: '$$rowkey' + index
|
|
|
|
|
};
|
|
|
|
|
querySelectorAll(row, "td .stb_cell").forEach((cell, index) => {
|
|
|
|
|
rowData["field-" + index] = cell.innerHTML;
|
|
|
|
|
})
|
2020-02-06 16:43:18 +08:00
|
|
|
if (!hasAttribute(row, "unsort")) {
|
2020-01-13 16:25:20 +08:00
|
|
|
data.push(rowData)
|
2020-02-05 17:10:11 +08:00
|
|
|
} else {
|
|
|
|
|
unsortData.push(rowData)
|
2020-01-13 16:25:20 +08:00
|
|
|
}
|
|
|
|
|
})
|
2020-02-05 17:10:11 +08:00
|
|
|
vm.data = data;
|
|
|
|
|
vm.unsortData = unsortData;
|
2020-01-28 22:13:48 +08:00
|
|
|
}
|