Skip to content

Commit

Permalink
fix(rxjs): no longer requires dom lib (#3566)
Browse files Browse the repository at this point in the history
Adds interfaces to cover what is used from DOM in `fromEvent` so that types are carried through, but `dom` lib isn not required by default even if you are not using `fromEvent`

fixes: #3558
  • Loading branch information
benlesh authored Apr 13, 2018
1 parent f6318d6 commit 8b33ee2
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 35 deletions.
12 changes: 6 additions & 6 deletions compat/observable/FromEventObservable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ import { EventTargetLike } from 'rxjs/internal-compatibility';

export class FromEventObservable<T> extends Observable<T> {
/* tslint:disable:max-line-length */
static create<T>(target: EventTargetLike, eventName: string): Observable<T>;
static create<T>(target: EventTargetLike, eventName: string, selector: ((...args: any[]) => T)): Observable<T>;
static create<T>(target: EventTargetLike, eventName: string, options: EventListenerOptions): Observable<T>;
static create<T>(target: EventTargetLike, eventName: string, options: EventListenerOptions, selector: ((...args: any[]) => T)): Observable<T>;
static create<T>(target: EventTargetLike<T>, eventName: string): Observable<T>;
static create<T>(target: EventTargetLike<T>, eventName: string, selector: ((...args: any[]) => T)): Observable<T>;
static create<T>(target: EventTargetLike<T>, eventName: string, options: EventListenerOptions): Observable<T>;
static create<T>(target: EventTargetLike<T>, eventName: string, options: EventListenerOptions, selector: ((...args: any[]) => T)): Observable<T>;
/* tslint:enable:max-line-length */

static create<T>(target: EventTargetLike,
static create<T>(target: EventTargetLike<T>,
eventName: string,
options?: EventListenerOptions | ((...args: any[]) => T),
selector?: ((...args: any[]) => T)): Observable<T> {
return fromEvent(target, eventName, options as EventListenerOptions, selector);
}
}
}
62 changes: 33 additions & 29 deletions src/internal/observable/fromEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,38 @@ export interface NodeStyleEventEmitter {

export type NodeEventHandler = (...args: any[]) => void;

export type JQueryStyleEventEmitter = {
export interface JQueryStyleEventEmitter {
on: (eventName: string, handler: Function) => void;
off: (eventName: string, handler: Function) => void;
};
}

export interface HasEventTargetAddRemove<E> {
addEventListener(type: string, listener: ((evt: E) => void) | null, options?: boolean | AddEventListenerOptions): void;
removeEventListener(type: string, listener?: ((evt: E) => void) | null, options?: EventListenerOptions | boolean): void;
}

export type EventTargetLike<T> = HasEventTargetAddRemove<T> | NodeStyleEventEmitter | JQueryStyleEventEmitter;

export type EventTargetLike = EventTarget | NodeStyleEventEmitter | JQueryStyleEventEmitter | NodeList | HTMLCollection;
export type FromEventTarget<T> = EventTargetLike<T> | ArrayLike<EventTargetLike<T>>;

export type EventListenerOptions = {
export interface EventListenerOptions {
capture?: boolean;
passive?: boolean;
once?: boolean;
} | boolean;
}

export interface AddEventListenerOptions extends EventListenerOptions {
once?: boolean;
passive?: boolean;
}

/* tslint:disable:max-line-length */
export function fromEvent<T>(target: EventTargetLike, eventName: string): Observable<T>;
export function fromEvent<T>(target: FromEventTarget<T>, eventName: string): Observable<T>;
/** @deprecated resultSelector no longer supported, pipe to map instead */
export function fromEvent<T>(target: EventTargetLike, eventName: string, resultSelector: (...args: any[]) => T): Observable<T>;
export function fromEvent<T>(target: EventTargetLike, eventName: string, options: EventListenerOptions): Observable<T>;
export function fromEvent<T>(target: FromEventTarget<T>, eventName: string, resultSelector: (...args: any[]) => T): Observable<T>;
export function fromEvent<T>(target: FromEventTarget<T>, eventName: string, options: EventListenerOptions): Observable<T>;
/** @deprecated resultSelector no longer supported, pipe to map instead */
export function fromEvent<T>(target: EventTargetLike, eventName: string, options: EventListenerOptions, resultSelector: (...args: any[]) => T): Observable<T>;
export function fromEvent<T>(target: FromEventTarget<T>, eventName: string, options: EventListenerOptions, resultSelector: (...args: any[]) => T): Observable<T>;
/* tslint:enable:max-line-length */

/**
Expand Down Expand Up @@ -138,7 +150,7 @@ export function fromEvent<T>(target: EventTargetLike, eventName: string, options
* @see {@link bindNodeCallback}
* @see {@link fromEventPattern}
*
* @param {EventTargetLike} target The DOM EventTarget, Node.js
* @param {FromEventTarget<T>} target The DOM EventTarget, Node.js
* EventEmitter, JQuery-like event target, NodeList or HTMLCollection to attach the event handler to.
* @param {string} eventName The event name of interest, being emitted by the
* `target`.
Expand All @@ -147,7 +159,7 @@ export function fromEvent<T>(target: EventTargetLike, eventName: string, options
* @name fromEvent
*/
export function fromEvent<T>(
target: EventTargetLike,
target: FromEventTarget<T>,
eventName: string,
options?: EventListenerOptions | ((...args: any[]) => T),
resultSelector?: ((...args: any[]) => T)
Expand Down Expand Up @@ -177,18 +189,18 @@ export function fromEvent<T>(
});
}

function setupSubscription<T>(sourceObj: EventTargetLike, eventName: string,
handler: Function, subscriber: Subscriber<T>,
function setupSubscription<T>(sourceObj: FromEventTarget<T>, eventName: string,
handler: (...args: any[]) => void, subscriber: Subscriber<T>,
options?: EventListenerOptions) {
let unsubscribe: () => void;
if (isNodeList(sourceObj) || isHTMLCollection(sourceObj)) {
for (let i = 0, len = sourceObj.length; i < len; i++) {
if (sourceObj && (sourceObj as any).length) {
for (let i = 0, len = (sourceObj as any).length; i < len; i++) {
setupSubscription(sourceObj[i], eventName, handler, subscriber, options);
}
} else if (isEventTarget(sourceObj)) {
const source = sourceObj;
sourceObj.addEventListener(eventName, handler as EventListener, options);
unsubscribe = () => source.removeEventListener(eventName, handler as EventListener, options);
sourceObj.addEventListener(eventName, handler, options);
unsubscribe = () => source.removeEventListener(eventName, handler, options);
} else if (isJQueryStyleEventEmitter(sourceObj)) {
const source = sourceObj;
sourceObj.on(eventName, handler);
Expand All @@ -205,21 +217,13 @@ function setupSubscription<T>(sourceObj: EventTargetLike, eventName: string,
}

function isNodeStyleEventEmitter(sourceObj: any): sourceObj is NodeStyleEventEmitter {
return !!sourceObj && typeof sourceObj.addListener === 'function' && typeof sourceObj.removeListener === 'function';
return sourceObj && typeof sourceObj.addListener === 'function' && typeof sourceObj.removeListener === 'function';
}

function isJQueryStyleEventEmitter(sourceObj: any): sourceObj is JQueryStyleEventEmitter {
return !!sourceObj && typeof sourceObj.on === 'function' && typeof sourceObj.off === 'function';
}

function isNodeList(sourceObj: any): sourceObj is NodeList {
return !!sourceObj && toString.call(sourceObj) === '[object NodeList]';
}

function isHTMLCollection(sourceObj: any): sourceObj is HTMLCollection {
return !!sourceObj && toString.call(sourceObj) === '[object HTMLCollection]';
return sourceObj && typeof sourceObj.on === 'function' && typeof sourceObj.off === 'function';
}

function isEventTarget(sourceObj: any): sourceObj is EventTarget {
return !!sourceObj && typeof sourceObj.addEventListener === 'function' && typeof sourceObj.removeEventListener === 'function';
function isEventTarget(sourceObj: any): sourceObj is HasEventTargetAddRemove<any> {
return sourceObj && typeof sourceObj.addEventListener === 'function' && typeof sourceObj.removeEventListener === 'function';
}

0 comments on commit 8b33ee2

Please sign in to comment.