* MIT License
*
* Copyright (c) 2019 Xu Liangzhan
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
import { getRowid } from './common'
import { hasClass, getDomNode } from '@opentiny/utils'
import { getActualTarget } from '@opentiny/utils'
import { arrayIndexOf } from '../static'
const ATTR_NAME = 'data-rowid'
const CELL_CLS = '.tiny-grid-cell'
const ROW_CLS = '.tiny-grid-body__row'
export const isPx = (val) => val && /^\d+(px)?$/.test(val)
export const isScale = (val) => val && /^\d+%$/.test(val)
export const updateCellTitle = (event: Event, td: HTMLElement) => {
const cellEl = td
? td.querySelector('.tiny-grid-cell-text') || td.querySelector(CELL_CLS)
: (event.currentTarget as HTMLElement)?.querySelector(CELL_CLS)
if (!cellEl) {
return
}
const content = cellEl.innerText
if (cellEl.getAttribute('title') !== content) {
cellEl.setAttribute('title', content)
}
}
export const rowToVisible = ($table, row) => {
$table.$nextTick(() => {
const { $refs, scrollYLoad, rowHeight, headerHeight, footerHeight, _tileInfo, _graphInfo } = $table
const { tableBody: bodyVm } = $refs
const { $el } = bodyVm
const { map } = _tileInfo
const { graphed } = _graphInfo
const trEl = $el.querySelector(`[${ATTR_NAME}="${getRowid($table, row)}"]`)
const visibleStart = headerHeight
const visibleEnd = $el.clientHeight - footerHeight
const scrollTop = $el.scrollTop
let position, trHeight
let flag = false
if (scrollYLoad) {
position = headerHeight + rowHeight * graphed.indexOf(map.get(row)) - scrollTop
trHeight = rowHeight
flag = true
} else if (trEl) {
position = trEl.offsetTop - scrollTop
trHeight = trEl.clientHeight
flag = true
}
if (flag) {
if (position < visibleStart) {
$el.scrollTop = scrollTop - (visibleStart - position)
return
}
position += trHeight
if (position > visibleEnd) {
$el.scrollTop = scrollTop + (position - visibleEnd)
}
}
})
}
export const colToVisible = ($table, column) => {
if (column.fixed) {
return
}
$table.$nextTick(() => {
const { $refs, scrollXLoad, visibleColumn, columnStore } = $table
const { tableBody: bodyVm } = $refs
const { $el } = bodyVm
const { leftList, rightList } = columnStore
const tdEl = $el.querySelector(`.${column.id}`)
const visibleStart = leftList.reduce((p, c) => (p += c.renderWidth), 0)
const visibleEnd = $el.clientWidth - rightList.reduce((p, c) => (p += c.renderWidth), 0)
const scrollLeft = $el.scrollLeft
const colWidth = column.renderWidth
let position
let flag = false
if (scrollXLoad) {
flag = true
position = -scrollLeft
for (const col of visibleColumn) {
if (col === column) break
position += col.renderWidth
}
} else if (tdEl) {
flag = true
position = tdEl.offsetLeft - scrollLeft
}
if (flag) {
if (position < visibleStart) {
$el.scrollLeft = scrollLeft - (visibleStart - position)
return
}
position += colWidth
if (position > visibleEnd) {
$el.scrollLeft = scrollLeft + (position - visibleEnd)
}
}
})
}
export const hasDataTag = (el, value) => {
if (!el || !value) {
return false
}
if (el.host) {
el = el.host
}
if (!el?.getAttribute) {
return false
}
return (' ' + el.getAttribute('data-tag') + ' ').includes(' ' + value + ' ')
}
export const getEventTargetNode = (event, container, queryCls) => {
let targetEl
let target = getActualTarget(event)
while (target && target.nodeType && target !== document) {
if (queryCls && (hasClass(target, queryCls) || hasDataTag(target, queryCls))) {
targetEl = target
} else if (target === container) {
return {
flag: queryCls ? !!targetEl : true,
container,
targetElem: targetEl
}
}
target = target.parentNode
}
return { flag: false }
}
function getNodeOffset(el, container, rest) {
if (el) {
const htmlEl = document.querySelector('html')
const bodyEl = document.body
const parentEl = el.parentNode
rest.top += el.offsetTop
rest.left += el.offsetLeft
if (parentEl && parentEl !== htmlEl && parentEl !== bodyEl) {
rest.top -= parentEl.scrollTop
rest.left -= parentEl.scrollLeft
}
if (container && (el === container || el.offsetParent === container) ? 0 : el.offsetParent) {
return getNodeOffset(el.offsetParent, container, rest)
}
}
return rest
}
* 获取元素相对于 document 的位置
*/
export const getOffsetPos = (el, container) => getNodeOffset(el, container, { left: 0, top: 0 })
export const getAbsolutePos = (el) => {
const bounding = el.getBoundingClientRect()
const { scrollTop, scrollLeft } = getDomNode()
return {
top: scrollTop + bounding.top,
left: scrollLeft + bounding.left
}
}
* 获取单元格节点索引
*/
export const getCellNodeIndex = (cell) => {
const trEl = cell.parentNode
const columnIndex = arrayIndexOf(trEl.children, cell)
const rowIndex = arrayIndexOf(trEl.parentNode.children, trEl)
return { columnIndex, rowIndex }
}
* 获取选中单元格矩阵范围
*/
export const getRowNodes = (trList, cellNode, targetCellNode) => {
const startColIndex = cellNode.columnIndex
const startRowIndex = cellNode.rowIndex
const targetColIndex = targetCellNode.columnIndex
const targetRowIndex = targetCellNode.rowIndex
const rows = []
for (
let rowIndex = Math.min(startRowIndex, targetRowIndex), rowLen = Math.max(startRowIndex, targetRowIndex);
rowIndex <= rowLen;
rowIndex++
) {
const cells = []
const trEl = trList[rowIndex]
for (
let colIndex = Math.min(startColIndex, targetColIndex), colLen = Math.max(startColIndex, targetColIndex);
colIndex <= colLen;
colIndex++
) {
cells.push(trEl.children[colIndex])
}
rows.push(cells)
}
return rows
}
export const getCellIndexs = (cell) => {
const trEl = cell.parentNode
const rowid = trEl.getAttribute(ATTR_NAME)
const columnIndex = [].indexOf.call(trEl.children, cell)
const rowIndex = [].indexOf.call(trEl.parentNode.children, trEl)
return { rowid, rowIndex, columnIndex }
}
export const getCell = ($table, { row, column }) =>
new Promise((resolve) => {
$table.$nextTick(() => {
const bodyElem = $table.$refs[`${column.fixed || 'table'}Body`]
resolve(
(bodyElem || $table.$refs.tableBody).$el.querySelector(
`${ROW_CLS}[${ATTR_NAME}="${getRowid($table, row)}"] .${column.id}`
)
)
})
})
export { getDomNode }