Skip to content

Commit

Permalink
feat(esl-event-listener): separate intersection events
Browse files Browse the repository at this point in the history
  • Loading branch information
fshovchko committed Apr 11, 2024
1 parent 6c265e5 commit 370d33b
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 14 deletions.
28 changes: 22 additions & 6 deletions src/modules/esl-event-listener/core/targets/intersection.event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ import {overrideEvent} from '../../../esl-utils/dom/events/misc';
* Based on the {@link IntersectionObserverEntry} object.
*/
export class ESLIntersectionEvent extends Event implements IntersectionObserverEntry {
public static readonly type = 'intersects';
public static readonly OUT_TYPE = 'intersects:out';
public static readonly IN_TYPE = 'intersects:in';
public static readonly BASE_TYPE = 'intersects';

public static readonly type:
typeof ESLIntersectionEvent.BASE_TYPE | typeof ESLIntersectionEvent.IN_TYPE | typeof ESLIntersectionEvent.OUT_TYPE = ESLIntersectionEvent.BASE_TYPE;

/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/IntersectionObserverEntry/target) */
public override readonly target: Element;
Expand All @@ -22,14 +27,25 @@ export class ESLIntersectionEvent extends Event implements IntersectionObserverE
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/IntersectionObserverEntry/time) */
public readonly time: DOMHighResTimeStamp;

protected constructor(target: Element) {
super(ESLIntersectionEvent.type, {bubbles: false, cancelable: false});
protected constructor(target: Element, eventName: typeof ESLIntersectionEvent.type) {
super(eventName, {bubbles: false, cancelable: false});
overrideEvent(this, 'target', target);
}

/** Creates {@link ESLIntersectionEvent} from {@link ESLIntersectionEvent} */
public static fromEntry(entry: IntersectionObserverEntry): ESLIntersectionEvent {
const event = new ESLIntersectionEvent(entry.target);
/** Validates event name. Accepted values are 'intersects:out', 'intersects:in', 'intersects' */
public static isValidEventType(event: string): boolean {
return event === ESLIntersectionEvent.BASE_TYPE || event === ESLIntersectionEvent.IN_TYPE || event === ESLIntersectionEvent.OUT_TYPE;
}

/** Creates {@link ESLIntersectionEvent} from {@link ESLIntersectionEvent}
* @param entry - The intersection observer entry.
* @param eventName - Custom event name ('intersects' by default. Accepted values are 'intersects:out', 'intersects:in', 'intersects').
*/
public static fromEntry(
entry: IntersectionObserverEntry,
eventName: typeof ESLIntersectionEvent.type = ESLIntersectionEvent.BASE_TYPE): ESLIntersectionEvent {
if (!ESLIntersectionEvent.isValidEventType(eventName)) eventName = ESLIntersectionEvent.BASE_TYPE;
const event = new ESLIntersectionEvent(entry.target, eventName);
const {
boundingClientRect,
intersectionRatio,
Expand Down
19 changes: 11 additions & 8 deletions src/modules/esl-event-listener/core/targets/intersection.target.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,32 +50,35 @@ export class ESLIntersectionTarget extends SyntheticEventTarget {
/** Internal method to handle {@link IntersectionObserver} entry change */
protected handleChange(entries: IntersectionObserverEntry[]): void {
entries.forEach(
(entry) => this.dispatchEvent(ESLIntersectionEvent.fromEntry(entry))
(entry) => {
this.dispatchEvent(ESLIntersectionEvent.fromEntry(entry, entry.isIntersecting ? ESLIntersectionEvent.IN_TYPE : ESLIntersectionEvent.OUT_TYPE));
this.dispatchEvent(ESLIntersectionEvent.fromEntry(entry));
}
);
}

/** Subscribes to the observed target {@link Element} changes */
public override addEventListener(callback: EventListener): void;
public override addEventListener(event: typeof ESLIntersectionEvent.type, callback: EventListener): void;
public override addEventListener(event: any, callback: EventListener = event): void {
if (typeof event !== 'string') event = ESLIntersectionEvent.type;
if (event !== ESLIntersectionEvent.type) {
if (typeof event !== 'string') event = ESLIntersectionEvent.BASE_TYPE;
if (!ESLIntersectionEvent.isValidEventType(event)) {
console.warn(`[ESL]: ESLIntersectionTarget does not support '${event}' type`);
return;
}
super.addEventListener(ESLIntersectionEvent.type, callback);
if (this.getEventListeners(ESLIntersectionEvent.type).length > 1) return;
super.addEventListener(event, callback);
if (this.getEventListeners(event).length > 1) return;
this.targets.forEach((target: Element) => this.observer$$.observe(target));
}

/** Unsubscribes from the observed target {@link Element} changes */
public override removeEventListener(callback: EventListener): void;
public override removeEventListener(event: typeof ESLIntersectionEvent.type, callback: EventListener): void;
public override removeEventListener(event: any, callback: EventListener = event): void {
if (typeof event !== 'string') event = ESLIntersectionEvent.type;
if (event !== ESLIntersectionEvent.type) return;
if (typeof event !== 'string') event = ESLIntersectionEvent.BASE_TYPE;
if (!ESLIntersectionEvent.isValidEventType(event)) return;
super.removeEventListener(event, callback);
if (this.hasEventListener(ESLIntersectionEvent.type)) return;
if (this.hasEventListener(event)) return;
this.observer$$.disconnect();
}
}

0 comments on commit 370d33b

Please sign in to comment.