From a1d7e81859f554f3a53680cc35f0f49bf1f77098 Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期四, 14 五月 2026 14:37:02 +0800
Subject: [PATCH] 导入项目

---
 src/utils/domUtils.ts |  289 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 289 insertions(+), 0 deletions(-)

diff --git a/src/utils/domUtils.ts b/src/utils/domUtils.ts
new file mode 100644
index 0000000..dbc1989
--- /dev/null
+++ b/src/utils/domUtils.ts
@@ -0,0 +1,289 @@
+import { isServer } from './is'
+const ieVersion = isServer ? 0 : Number((document as any).documentMode)
+const SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g
+const MOZ_HACK_REGEXP = /^moz([A-Z])/
+
+export interface ViewportOffsetResult {
+  left: number
+  top: number
+  right: number
+  bottom: number
+  rightIncludeBody: number
+  bottomIncludeBody: number
+}
+
+/* istanbul ignore next */
+const trim = function (string: string) {
+  return (string || '').replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, '')
+}
+
+/* istanbul ignore next */
+const camelCase = function (name: string) {
+  return name
+    .replace(SPECIAL_CHARS_REGEXP, function (_, __, letter, offset) {
+      return offset ? letter.toUpperCase() : letter
+    })
+    .replace(MOZ_HACK_REGEXP, 'Moz$1')
+}
+
+/* istanbul ignore next */
+export function hasClass(el: Element, cls: string) {
+  if (!el || !cls) return false
+  if (cls.indexOf(' ') !== -1) {
+    throw new Error('className should not contain space.')
+  }
+  if (el.classList) {
+    return el.classList.contains(cls)
+  } else {
+    return (' ' + el.className + ' ').indexOf(' ' + cls + ' ') > -1
+  }
+}
+
+/* istanbul ignore next */
+export function addClass(el: Element, cls: string) {
+  if (!el) return
+  let curClass = el.className
+  const classes = (cls || '').split(' ')
+
+  for (let i = 0, j = classes.length; i < j; i++) {
+    const clsName = classes[i]
+    if (!clsName) continue
+
+    if (el.classList) {
+      el.classList.add(clsName)
+    } else if (!hasClass(el, clsName)) {
+      curClass += ' ' + clsName
+    }
+  }
+  if (!el.classList) {
+    el.className = curClass
+  }
+}
+
+/* istanbul ignore next */
+export function removeClass(el: Element, cls: string) {
+  if (!el || !cls) return
+  const classes = cls.split(' ')
+  let curClass = ' ' + el.className + ' '
+
+  for (let i = 0, j = classes.length; i < j; i++) {
+    const clsName = classes[i]
+    if (!clsName) continue
+
+    if (el.classList) {
+      el.classList.remove(clsName)
+    } else if (hasClass(el, clsName)) {
+      curClass = curClass.replace(' ' + clsName + ' ', ' ')
+    }
+  }
+  if (!el.classList) {
+    el.className = trim(curClass)
+  }
+}
+
+export function getBoundingClientRect(element: Element): DOMRect | number {
+  if (!element || !element.getBoundingClientRect) {
+    return 0
+  }
+  return element.getBoundingClientRect()
+}
+
+/**
+ * 鑾峰彇褰撳墠鍏冪礌鐨刲eft銆乼op鍋忕Щ
+ *   left锛氬厓绱犳渶宸︿晶璺濈鏂囨。宸︿晶鐨勮窛绂�
+ *   top:鍏冪礌鏈�椤剁璺濈鏂囨。椤剁鐨勮窛绂�
+ *   right:鍏冪礌鏈�鍙充晶璺濈鏂囨。鍙充晶鐨勮窛绂�
+ *   bottom锛氬厓绱犳渶搴曠璺濈鏂囨。搴曠鐨勮窛绂�
+ *   rightIncludeBody锛氬厓绱犳渶宸︿晶璺濈鏂囨。鍙充晶鐨勮窛绂�
+ *   bottomIncludeBody锛氬厓绱犳渶搴曠璺濈鏂囨。鏈�搴曢儴鐨勮窛绂�
+ *
+ * @description:
+ */
+export function getViewportOffset(element: Element): ViewportOffsetResult {
+  const doc = document.documentElement
+
+  const docScrollLeft = doc.scrollLeft
+  const docScrollTop = doc.scrollTop
+  const docClientLeft = doc.clientLeft
+  const docClientTop = doc.clientTop
+
+  const pageXOffset = window.pageXOffset
+  const pageYOffset = window.pageYOffset
+
+  const box = getBoundingClientRect(element)
+
+  const { left: retLeft, top: rectTop, width: rectWidth, height: rectHeight } = box as DOMRect
+
+  const scrollLeft = (pageXOffset || docScrollLeft) - (docClientLeft || 0)
+  const scrollTop = (pageYOffset || docScrollTop) - (docClientTop || 0)
+  const offsetLeft = retLeft + pageXOffset
+  const offsetTop = rectTop + pageYOffset
+
+  const left = offsetLeft - scrollLeft
+  const top = offsetTop - scrollTop
+
+  const clientWidth = window.document.documentElement.clientWidth
+  const clientHeight = window.document.documentElement.clientHeight
+  return {
+    left: left,
+    top: top,
+    right: clientWidth - rectWidth - left,
+    bottom: clientHeight - rectHeight - top,
+    rightIncludeBody: clientWidth - left,
+    bottomIncludeBody: clientHeight - top
+  }
+}
+
+/* istanbul ignore next */
+export const on = function (
+  element: HTMLElement | Document | Window,
+  event: string,
+  handler: EventListenerOrEventListenerObject
+): void {
+  if (element && event && handler) {
+    element.addEventListener(event, handler, false)
+  }
+}
+
+/* istanbul ignore next */
+export const off = function (
+  element: HTMLElement | Document | Window,
+  event: string,
+  handler: any
+): void {
+  if (element && event && handler) {
+    element.removeEventListener(event, handler, false)
+  }
+}
+
+/* istanbul ignore next */
+export const once = function (el: HTMLElement, event: string, fn: EventListener): void {
+  const listener = function (this: any, ...args: unknown[]) {
+    if (fn) {
+      // @ts-ignore
+      fn.apply(this, args)
+    }
+    off(el, event, listener)
+  }
+  on(el, event, listener)
+}
+
+/* istanbul ignore next */
+export const getStyle =
+  ieVersion < 9
+    ? function (element: Element | any, styleName: string) {
+        if (isServer) return
+        if (!element || !styleName) return null
+        styleName = camelCase(styleName)
+        if (styleName === 'float') {
+          styleName = 'styleFloat'
+        }
+        try {
+          switch (styleName) {
+            case 'opacity':
+              try {
+                return element.filters.item('alpha').opacity / 100
+              } catch (e) {
+                return 1.0
+              }
+            default:
+              return element.style[styleName] || element.currentStyle
+                ? element.currentStyle[styleName]
+                : null
+          }
+        } catch (e) {
+          return element.style[styleName]
+        }
+      }
+    : function (element: Element | any, styleName: string) {
+        if (isServer) return
+        if (!element || !styleName) return null
+        styleName = camelCase(styleName)
+        if (styleName === 'float') {
+          styleName = 'cssFloat'
+        }
+        try {
+          const computed = (document as any).defaultView.getComputedStyle(element, '')
+          return element.style[styleName] || computed ? computed[styleName] : null
+        } catch (e) {
+          return element.style[styleName]
+        }
+      }
+
+/* istanbul ignore next */
+export function setStyle(element: Element | any, styleName: any, value: any) {
+  if (!element || !styleName) return
+
+  if (typeof styleName === 'object') {
+    for (const prop in styleName) {
+      if (Object.prototype.hasOwnProperty.call(styleName, prop)) {
+        setStyle(element, prop, styleName[prop])
+      }
+    }
+  } else {
+    styleName = camelCase(styleName)
+    if (styleName === 'opacity' && ieVersion < 9) {
+      element.style.filter = isNaN(value) ? '' : 'alpha(opacity=' + value * 100 + ')'
+    } else {
+      element.style[styleName] = value
+    }
+  }
+}
+
+/* istanbul ignore next */
+export const isScroll = (el: Element, vertical: any) => {
+  if (isServer) return
+
+  const determinedDirection = vertical !== null || vertical !== undefined
+  const overflow = determinedDirection
+    ? vertical
+      ? getStyle(el, 'overflow-y')
+      : getStyle(el, 'overflow-x')
+    : getStyle(el, 'overflow')
+
+  return overflow.match(/(scroll|auto)/)
+}
+
+/* istanbul ignore next */
+export const getScrollContainer = (el: Element, vertical?: any) => {
+  if (isServer) return
+
+  let parent: any = el
+  while (parent) {
+    if ([window, document, document.documentElement].includes(parent)) {
+      return window
+    }
+    if (isScroll(parent, vertical)) {
+      return parent
+    }
+    parent = parent.parentNode
+  }
+
+  return parent
+}
+
+/* istanbul ignore next */
+export const isInContainer = (el: Element, container: any) => {
+  if (isServer || !el || !container) return false
+
+  const elRect = el.getBoundingClientRect()
+  let containerRect
+
+  if ([window, document, document.documentElement, null, undefined].includes(container)) {
+    containerRect = {
+      top: 0,
+      right: window.innerWidth,
+      bottom: window.innerHeight,
+      left: 0
+    }
+  } else {
+    containerRect = container.getBoundingClientRect()
+  }
+
+  return (
+    elRect.top < containerRect.bottom &&
+    elRect.bottom > containerRect.top &&
+    elRect.right > containerRect.left &&
+    elRect.left < containerRect.right
+  )
+}

--
Gitblit v1.8.0