You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

282 lines
8.7 KiB
JavaScript

class AutoScrollTable {
loadingText = "正在加载..."
constructor(el, columns, {
width = null,
headWidth = null,
init = true,
loadingSplash = true,
caption = null,
} = {},lineNum = 5) {
this.lineNum = lineNum
this.el = el
this.columns = columns
this.width = width
this.headWidth = headWidth
this.loadingSplash = loadingSplash
this.caption = caption
this.scrollInfo = null
this.loaded = false
this.initialized = false
this.loadingText = "暂无数据"
if (init) {
this.init()
}
}
init() {
this.el.style.overflowY = "scroll"
this.el.classList.add("hide-scrollbar")
let html = ""
html += `<table class="autoscroll-table">`
if (this.caption) {
html += `<caption class="autoscroll-table_caption">${this.caption}</caption>`
}
html += `<thead class="autoscroll-table_thead"><tr>`
if (this.columns && this.columns.length > 0) {
for (let item of this.columns) {
html += `<th>${item}</th>`
}
}
html += `</tr></thead>`
html += `<tbody class="autoscroll-table_shadow"><tr><td>&nbsp;</td></tr></tbody>`
// html += `<tbody class="autoscroll-table_shadow"><tr><td>&nbsp;</td></tr></tbody>`
html += `<tbody class="autoscroll-table_tbody autoscroll-table_tbody1"></tbody>`
html += `<tbody class="autoscroll-table_tbody autoscroll-table_tbody2"></tbody>`
html += `</table>`
html += `<div class="loading-splash">${this.loadingText}</div>`
this.el.innerHTML = html
const thead = this.el.querySelector(".autoscroll-table .autoscroll-table_thead");
let tbody = this.el.querySelector(".autoscroll-table .autoscroll-table_tbody1");
const shadow = this.el.querySelector(".autoscroll-table .autoscroll-table_shadow")
thead.style.width = window.getComputedStyle(tbody).width
thead.style.overflow = 'hidden'
shadow.style.opacity = 0
this.addFill()
this.resize()
if (this.loadingSplash) {
this.loading()
}
this.el.addEventListener('scroll', ev => {
if (this.el.scrollTop > 0) {
thead.classList.add("thead-scroll-override")
} else {
thead.classList.remove("thead-scroll-override")
}
})
this.initialized = true
return this
}
addFill() {
let tbody = this.el.querySelector(".autoscroll-table .autoscroll-table_tbody1");
if (!tbody.children.length) {
tbody.innerHTML += "<tr></tr>"
}
for (let item of this.columns) {
tbody.children[0].innerHTML += '<td>&nbsp;</td>'
}
}
loadData(data, fields = null, {
append = false,
autoScroll = false,
scrollToEnd = false,
includeHead = false,
} = {}) {
if (!fields) {
fields = Object.keys(data[0])
} else if (typeof fields === 'number') {
let f = []
for (let i = 0; i < fields; i++) {
f.push(i)
}
fields = f
}
const tbody = this.el.querySelectorAll(".autoscroll-table .autoscroll-table_tbody")
if (!this.loaded) {
const loadingSplash = this.el.querySelector(".loading-splash")
loadingSplash.style.display = "none"
this.loaded = true
}
if (!append) {
this.clear()
}
if (includeHead) {
const rawRow = data.shift()
let row = []
for (let field of Object.values(fields)) {
row.push(rawRow[field])
}
this.columns = row
const thead = this.el.querySelector(".autoscroll-table .autoscroll-table_thead")
let html = ""
for (let item of Object.values(this.columns)) {
html += `<th>${item}</th>`
}
thead.querySelector("tr").innerHTML = html
}
for (let item of Object.values(data)) {
let html = `<tr>`
for (let field of fields) {
html += `<td>${item[field]}</td>`
}
html += '</tr>'
tbody.forEach(value => value.innerHTML += html)
}
if (autoScroll) {
this.startAutoScroll()
} else {
const l2 = this.el.querySelector(".autoscroll-table .autoscroll-table_tbody2")
l2.style.display = 'none'
if (scrollToEnd) {
this.scrollToEnd()
}
}
if (this.width) {
tbody.forEach(value => {
for (let i = 0; i < value.children.length; i++) {
const child = value.children[i]
for (let j = 0; j < child.children.length; j++) {
if (j < this.width.length && this.width[j]) {
child.children[j].style.width = this.width[j]
}
}
}
})
}
if (!data || data.length && data.length === 0) {
this.addFill()
}
this.resize()
setTimeout(() => this.resize(), 300)
setTimeout(() => this.resize(), 500)
setTimeout(() => this.resize(), 1000)
}
scrollToEnd() {
const l1 = this.el.querySelector(".autoscroll-table .autoscroll-table_tbody1")
this.el.scrollTop = l1.scrollHeight
}
clear() {
const tbody = this.el.querySelectorAll(".autoscroll-table .autoscroll-table_tbody")
for (let tb of tbody) {
tb.innerHTML = ""
}
}
startAutoScroll() {
if (this.scrollInfo) {
return
}
const l1 = this.el.querySelector(".autoscroll-table .autoscroll-table_tbody1")
const l2 = this.el.querySelector(".autoscroll-table .autoscroll-table_tbody2")
function scrollTimeout() {
this.scrollInfo = setInterval(scrollUp, 50);
}
const scrollUp = () => {
this.el.scrollTop = (this.el.scrollTop + 1) % (l1.offsetHeight * 1.004)
}
const startScroll = () => {
if (l1.offsetHeight <= this.el.offsetHeight) {
l2.style.display = 'none'
return
}
l2.style.display = 'table-row-group'
scrollTimeout.call(this);//数值越大,滚动速度越慢
this.el.onmouseover = () => {
this.stop()
}
}
this.el.onmouseout = () => {
scrollTimeout.call(this)
}
startScroll()
}
stop() {
clearInterval(this.scrollInfo)
this.scrollInfo = null
}
resize() {
const parent = this.el.querySelector(".autoscroll-table").parentNode
const thead = this.el.querySelector(".autoscroll-table .autoscroll-table_thead");
const theadRow = thead.children[0]
let tbody = this.el.querySelector(".autoscroll-table .autoscroll-table_tbody1");
// let tbody2 = this.el.querySelector(".autoscroll-table .autoscroll-table_tbody2");
const shadow = this.el.querySelector(".autoscroll-table .autoscroll-table_shadow")
const caption = this.el.querySelector(".autoscroll-table .autoscroll-table_caption")
const firstRow = tbody.children[0]
if (firstRow && firstRow.children.length > 0) {
for (let i = 0; i < theadRow.children.length; i++) {
if (this.headWidth && this.headWidth.length > i) {
theadRow.children[i].style.width = this.headWidth[i]
} else {
if (firstRow.children.length > i) {
theadRow.children[i].style.width = window.getComputedStyle(firstRow.children[i]).width
}
}
}
}
thead.style.width = window.getComputedStyle(tbody).width
let tr = this.el.querySelectorAll(".autoscroll-table .autoscroll-table_tbody1 tr")
tr.forEach(val => {
val.style.lineHeight = `${(parseFloat(window.getComputedStyle(parent).height) - parseFloat(window.getComputedStyle(theadRow).height))/this.lineNum - 1.5}px`
})
shadow.style.display ='none'
thead.style.top = '0'
if (caption) {
caption.style.width = thead.style.width
const captionHeight = parseFloat(window.getComputedStyle(caption).height)
thead.style.top = '0'
shadow.style.height = `${parseFloat(shadow.style.height) + captionHeight}px`
}
}
loading() {
this.el.querySelector(".loading-splash").style.display = "block"
this.loaded = false
}
}