events-helper.ts 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. // @ts-nocheck
  2. import { h, inject, ref } from 'vue'
  3. import { debounce } from 'lodash-unified'
  4. import { getStyle, hasClass } from '@element-plus/utils'
  5. import { useZIndex } from '@element-plus/hooks'
  6. import { createTablePopper, getCell, getColumnByCell } from '../util'
  7. import { TABLE_INJECTION_KEY } from '../tokens'
  8. import type { TableColumnCtx } from '../table-column/defaults'
  9. import type { TableBodyProps } from './defaults'
  10. import type { TableOverflowTooltipOptions } from '../util'
  11. function useEvents<T>(props: Partial<TableBodyProps<T>>) {
  12. const parent = inject(TABLE_INJECTION_KEY)
  13. const tooltipContent = ref('')
  14. const tooltipTrigger = ref(h('div'))
  15. const { nextZIndex } = useZIndex()
  16. const handleEvent = (event: Event, row: T, name: string) => {
  17. const table = parent
  18. const cell = getCell(event)
  19. let column: TableColumnCtx<T>
  20. const namespace = table?.vnode.el?.dataset.prefix
  21. if (cell) {
  22. column = getColumnByCell(
  23. {
  24. columns: props.store.states.columns.value,
  25. },
  26. cell,
  27. namespace
  28. )
  29. if (column) {
  30. table?.emit(`cell-${name}`, row, column, cell, event)
  31. }
  32. }
  33. table?.emit(`row-${name}`, row, column, event)
  34. }
  35. const handleDoubleClick = (event: Event, row: T) => {
  36. handleEvent(event, row, 'dblclick')
  37. }
  38. const handleClick = (event: Event, row: T) => {
  39. props.store.commit('setCurrentRow', row)
  40. handleEvent(event, row, 'click')
  41. }
  42. const handleContextMenu = (event: Event, row: T) => {
  43. handleEvent(event, row, 'contextmenu')
  44. }
  45. const handleMouseEnter = debounce((index: number) => {
  46. props.store.commit('setHoverRow', index)
  47. }, 30)
  48. const handleMouseLeave = debounce(() => {
  49. props.store.commit('setHoverRow', null)
  50. }, 30)
  51. const handleCellMouseEnter = (
  52. event: MouseEvent,
  53. row: T,
  54. tooltipOptions: TableOverflowTooltipOptions
  55. ) => {
  56. const table = parent
  57. const cell = getCell(event)
  58. const namespace = table?.vnode.el?.dataset.prefix
  59. if (cell) {
  60. const column = getColumnByCell(
  61. {
  62. columns: props.store.states.columns.value,
  63. },
  64. cell,
  65. namespace
  66. )
  67. const hoverState = (table.hoverState = { cell, column, row })
  68. table?.emit(
  69. 'cell-mouse-enter',
  70. hoverState.row,
  71. hoverState.column,
  72. hoverState.cell,
  73. event
  74. )
  75. }
  76. if (!tooltipOptions) {
  77. return
  78. }
  79. // 判断是否text-overflow, 如果是就显示tooltip
  80. const cellChild = (event.target as HTMLElement).querySelector(
  81. '.cell'
  82. ) as HTMLElement
  83. if (
  84. !(
  85. hasClass(cellChild, `${namespace}-tooltip`) &&
  86. cellChild.childNodes.length
  87. )
  88. ) {
  89. return
  90. }
  91. // use range width instead of scrollWidth to determine whether the text is overflowing
  92. // to address a potential FireFox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1074543#c3
  93. const range = document.createRange()
  94. range.setStart(cellChild, 0)
  95. range.setEnd(cellChild, cellChild.childNodes.length)
  96. /** detail: https://github.com/element-plus/element-plus/issues/10790
  97. * What went wrong?
  98. * UI > Browser > Zoom, In Blink/WebKit, getBoundingClientRect() sometimes returns inexact values, probably due to lost precision during internal calculations. In the example above:
  99. * - Expected: 188
  100. * - Actual: 188.00000762939453
  101. */
  102. const rangeWidth = Math.round(range.getBoundingClientRect().width)
  103. const padding =
  104. (Number.parseInt(getStyle(cellChild, 'paddingLeft'), 10) || 0) +
  105. (Number.parseInt(getStyle(cellChild, 'paddingRight'), 10) || 0)
  106. if (
  107. rangeWidth + padding > cellChild.offsetWidth ||
  108. cellChild.scrollWidth > cellChild.offsetWidth
  109. ) {
  110. createTablePopper(
  111. parent?.refs.tableWrapper,
  112. cell,
  113. cell.innerText || cell.textContent,
  114. nextZIndex,
  115. tooltipOptions
  116. )
  117. }
  118. }
  119. const handleCellMouseLeave = (event) => {
  120. const cell = getCell(event)
  121. if (!cell) return
  122. const oldHoverState = parent?.hoverState
  123. parent?.emit(
  124. 'cell-mouse-leave',
  125. oldHoverState?.row,
  126. oldHoverState?.column,
  127. oldHoverState?.cell,
  128. event
  129. )
  130. }
  131. return {
  132. handleDoubleClick,
  133. handleClick,
  134. handleContextMenu,
  135. handleMouseEnter,
  136. handleMouseLeave,
  137. handleCellMouseEnter,
  138. handleCellMouseLeave,
  139. tooltipContent,
  140. tooltipTrigger,
  141. }
  142. }
  143. export default useEvents