ant-design/components/affix/utils.ts

107 lines
2.9 KiB
TypeScript
Raw Normal View History

2019-03-03 10:04:21 +08:00
import addEventListener from 'rc-util/lib/Dom/addEventListener';
2023-02-22 10:42:25 +08:00
import type { InternalAffixClass } from '.';
2019-03-03 10:04:21 +08:00
export type BindElement = HTMLElement | Window | null | undefined;
export function getTargetRect(target: BindElement): DOMRect {
return target !== window
? (target as HTMLElement).getBoundingClientRect()
: ({ top: 0, bottom: window.innerHeight } as DOMRect);
}
2023-02-24 09:04:03 +08:00
export function getFixedTop(placeholderRect: DOMRect, targetRect: DOMRect, offsetTop?: number) {
if (offsetTop !== undefined && targetRect.top > placeholderRect.top - offsetTop) {
return offsetTop + targetRect.top;
}
return undefined;
}
2019-05-07 14:57:32 +08:00
export function getFixedBottom(
2023-02-24 09:04:03 +08:00
placeholderRect: DOMRect,
targetRect: DOMRect,
offsetBottom?: number,
2019-05-07 14:57:32 +08:00
) {
2023-02-24 09:04:03 +08:00
if (offsetBottom !== undefined && targetRect.bottom < placeholderRect.bottom + offsetBottom) {
const targetBottomOffset = window.innerHeight - targetRect.bottom;
return offsetBottom + targetBottomOffset;
}
return undefined;
}
2019-03-03 10:04:21 +08:00
// ======================== Observer ========================
const TRIGGER_EVENTS = [
'resize',
'scroll',
'touchstart',
'touchmove',
'touchend',
'pageshow',
'load',
];
interface ObserverEntity {
target: HTMLElement | Window;
affixList: any[];
2019-03-03 10:04:21 +08:00
eventHandlers: { [eventName: string]: any };
}
let observerEntities: ObserverEntity[] = [];
export function getObserverEntities() {
// Only used in test env. Can be removed if refactor.
return observerEntities;
}
2023-02-22 10:42:25 +08:00
export function addObserveTarget<T extends InternalAffixClass>(
target: HTMLElement | Window | null,
affix?: T,
): void {
2022-10-14 14:03:01 +08:00
if (!target) {
return;
}
2019-03-03 10:04:21 +08:00
let entity = observerEntities.find((item) => item.target === target);
2019-03-03 10:04:21 +08:00
if (entity) {
entity.affixList.push(affix);
} else {
entity = {
target,
affixList: [affix],
eventHandlers: {},
};
observerEntities.push(entity);
// Add listener
TRIGGER_EVENTS.forEach((eventName) => {
2019-08-05 18:38:10 +08:00
entity!.eventHandlers[eventName] = addEventListener(target, eventName, () => {
entity!.affixList.forEach((targetAffix) => {
2019-08-05 18:38:10 +08:00
targetAffix.lazyUpdatePosition();
2019-03-03 10:04:21 +08:00
});
});
});
}
}
2023-02-22 10:42:25 +08:00
export function removeObserveTarget<T extends InternalAffixClass>(affix: T): void {
const observerEntity = observerEntities.find((oriObserverEntity) => {
const hasAffix = oriObserverEntity.affixList.some((item) => item === affix);
2019-03-03 10:04:21 +08:00
if (hasAffix) {
oriObserverEntity.affixList = oriObserverEntity.affixList.filter((item) => item !== affix);
2019-03-03 10:04:21 +08:00
}
return hasAffix;
});
if (observerEntity && observerEntity.affixList.length === 0) {
observerEntities = observerEntities.filter((item) => item !== observerEntity);
2019-03-03 10:04:21 +08:00
// Remove listener
TRIGGER_EVENTS.forEach((eventName) => {
2019-03-03 10:04:21 +08:00
const handler = observerEntity.eventHandlers[eventName];
if (handler && handler.remove) {
handler.remove();
}
});
}
}