forked from TDesignOteam/tdesign-web-components
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdom.ts
138 lines (121 loc) · 4.03 KB
/
dom.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import isString from 'lodash/isString';
import raf from 'raf';
import { easeInOutCubic, EasingFunction } from './easing';
// 用于判断是否可使用 dom
export const canUseDocument = !!(typeof window !== 'undefined' && window.document && window.document.createElement);
// 获取 css vars
export const getCssVarsValue = (name: string, element?: HTMLElement) => {
if (!canUseDocument) return;
const el = element || document.documentElement;
return getComputedStyle(el).getPropertyValue(name);
};
function isWindow(obj: any) {
return obj && obj === obj.window;
}
type ScrollTarget = HTMLElement | Window | Document;
export function getScroll(target: ScrollTarget, isLeft?: boolean): number {
// node环境或者target为空
if (typeof window === 'undefined' || !target) {
return 0;
}
const method = isLeft ? 'scrollLeft' : 'scrollTop';
let result = 0;
if (isWindow(target)) {
result = (target as Window)[isLeft ? 'pageXOffset' : 'pageYOffset'];
} else if (target instanceof Document) {
result = target.documentElement[method];
} else if (target) {
result = (target as HTMLElement)[method];
}
return result;
}
interface ScrollTopOptions {
container?: ScrollTarget;
duration?: number;
easing?: EasingFunction;
}
export const scrollTo = (target: number, opt: ScrollTopOptions) => {
const { container = window, duration = 450, easing = easeInOutCubic } = opt;
const scrollTop = getScroll(container);
const startTime = Date.now();
return new Promise((res) => {
const fnc = () => {
const timestamp = Date.now();
const time = timestamp - startTime;
const nextScrollTop = easing(Math.min(time, duration), scrollTop, target, duration);
if (isWindow(container)) {
(container as Window).scrollTo(window.pageXOffset, nextScrollTop);
} else if (container instanceof HTMLDocument || container.constructor.name === 'HTMLDocument') {
(container as HTMLDocument).documentElement.scrollTop = nextScrollTop;
} else {
(container as HTMLElement).scrollTop = nextScrollTop;
}
if (time < duration) {
raf(fnc);
} else {
// 由于上面步骤设置了 scrollTop, 滚动事件可能未触发完毕
// 此时应该在下一帧再执行 res
raf(res);
}
};
raf(fnc);
});
};
export const getAttach = (node: any): HTMLElement => {
const attachNode = typeof node === 'function' ? node() : node;
if (!attachNode) {
return document.body;
}
if (isString(attachNode)) {
return document.querySelector(attachNode);
}
if (attachNode instanceof HTMLElement) {
return attachNode;
}
return document.body;
};
export const addClass = function (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) {
// eslint-disable-next-line
el.className = curClass;
}
};
const trim = (str: string): string => (str || '').replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, '');
export const removeClass = function (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) {
// eslint-disable-next-line
el.className = trim(curClass);
}
};
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);
}
return ` ${el.className} `.indexOf(` ${cls} `) > -1;
}