| import { Observable } from '../Observable'; | 
| import { isArray } from '../util/isArray'; | 
| import { isFunction } from '../util/isFunction'; | 
| import { Subscriber } from '../Subscriber'; | 
| import { map } from '../operators/map'; | 
|   | 
| const toString: Function = Object.prototype.toString; | 
|   | 
| export interface NodeStyleEventEmitter { | 
|   addListener: (eventName: string | symbol, handler: NodeEventHandler) => this; | 
|   removeListener: (eventName: string | symbol, handler: NodeEventHandler) => this; | 
| } | 
|   | 
| export type NodeEventHandler = (...args: any[]) => void; | 
|   | 
| // For APIs that implement `addListener` and `removeListener` methods that may | 
| // not use the same arguments or return EventEmitter values | 
| // such as React Native | 
| export interface NodeCompatibleEventEmitter { | 
|   addListener: (eventName: string, handler: NodeEventHandler) => void | {}; | 
|   removeListener: (eventName: string, handler: NodeEventHandler) => void | {}; | 
| } | 
|   | 
| 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 | NodeCompatibleEventEmitter | JQueryStyleEventEmitter; | 
|   | 
| export type FromEventTarget<T> = EventTargetLike<T> | ArrayLike<EventTargetLike<T>>; | 
|   | 
| export interface EventListenerOptions { | 
|   capture?: boolean; | 
|   passive?: boolean; | 
|   once?: boolean; | 
| } | 
|   | 
| export interface AddEventListenerOptions extends EventListenerOptions { | 
|   once?: boolean; | 
|   passive?: boolean; | 
| } | 
|   | 
| /* tslint:disable:max-line-length */ | 
| 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: 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: FromEventTarget<T>, eventName: string, options: EventListenerOptions, resultSelector: (...args: any[]) => T): Observable<T>; | 
| /* tslint:enable:max-line-length */ | 
|   | 
| /** | 
|  * Creates an Observable that emits events of a specific type coming from the | 
|  * given event target. | 
|  * | 
|  * <span class="informal">Creates an Observable from DOM events, or Node.js | 
|  * EventEmitter events or others.</span> | 
|  * | 
|  *  | 
|  * | 
|  * `fromEvent` accepts as a first argument event target, which is an object with methods | 
|  * for registering event handler functions. As a second argument it takes string that indicates | 
|  * type of event we want to listen for. `fromEvent` supports selected types of event targets, | 
|  * which are described in detail below. If your event target does not match any of the ones listed, | 
|  * you should use {@link fromEventPattern}, which can be used on arbitrary APIs. | 
|  * When it comes to APIs supported by `fromEvent`, their methods for adding and removing event | 
|  * handler functions have different names, but they all accept a string describing event type | 
|  * and function itself, which will be called whenever said event happens. | 
|  * | 
|  * Every time resulting Observable is subscribed, event handler function will be registered | 
|  * to event target on given event type. When that event fires, value | 
|  * passed as a first argument to registered function will be emitted by output Observable. | 
|  * When Observable is unsubscribed, function will be unregistered from event target. | 
|  * | 
|  * Note that if event target calls registered function with more than one argument, second | 
|  * and following arguments will not appear in resulting stream. In order to get access to them, | 
|  * you can pass to `fromEvent` optional project function, which will be called with all arguments | 
|  * passed to event handler. Output Observable will then emit value returned by project function, | 
|  * instead of the usual value. | 
|  * | 
|  * Remember that event targets listed below are checked via duck typing. It means that | 
|  * no matter what kind of object you have and no matter what environment you work in, | 
|  * you can safely use `fromEvent` on that object if it exposes described methods (provided | 
|  * of course they behave as was described above). So for example if Node.js library exposes | 
|  * event target which has the same method names as DOM EventTarget, `fromEvent` is still | 
|  * a good choice. | 
|  * | 
|  * If the API you use is more callback then event handler oriented (subscribed | 
|  * callback function fires only once and thus there is no need to manually | 
|  * unregister it), you should use {@link bindCallback} or {@link bindNodeCallback} | 
|  * instead. | 
|  * | 
|  * `fromEvent` supports following types of event targets: | 
|  * | 
|  * **DOM EventTarget** | 
|  * | 
|  * This is an object with `addEventListener` and `removeEventListener` methods. | 
|  * | 
|  * In the browser, `addEventListener` accepts - apart from event type string and event | 
|  * handler function arguments - optional third parameter, which is either an object or boolean, | 
|  * both used for additional configuration how and when passed function will be called. When | 
|  * `fromEvent` is used with event target of that type, you can provide this values | 
|  * as third parameter as well. | 
|  * | 
|  * **Node.js EventEmitter** | 
|  * | 
|  * An object with `addListener` and `removeListener` methods. | 
|  * | 
|  * **JQuery-style event target** | 
|  * | 
|  * An object with `on` and `off` methods | 
|  * | 
|  * **DOM NodeList** | 
|  * | 
|  * List of DOM Nodes, returned for example by `document.querySelectorAll` or `Node.childNodes`. | 
|  * | 
|  * Although this collection is not event target in itself, `fromEvent` will iterate over all Nodes | 
|  * it contains and install event handler function in every of them. When returned Observable | 
|  * is unsubscribed, function will be removed from all Nodes. | 
|  * | 
|  * **DOM HtmlCollection** | 
|  * | 
|  * Just as in case of NodeList it is a collection of DOM nodes. Here as well event handler function is | 
|  * installed and removed in each of elements. | 
|  * | 
|  * | 
|  * ## Examples | 
|  * ### Emits clicks happening on the DOM document | 
|  * ```ts | 
|  * import { fromEvent } from 'rxjs'; | 
|  * | 
|  * const clicks = fromEvent(document, 'click'); | 
|  * clicks.subscribe(x => console.log(x)); | 
|  * | 
|  * // Results in: | 
|  * // MouseEvent object logged to console every time a click | 
|  * // occurs on the document. | 
|  * ``` | 
|  * | 
|  * ### Use addEventListener with capture option | 
|  * ```ts | 
|  * import { fromEvent } from 'rxjs'; | 
|  * | 
|  * const clicksInDocument = fromEvent(document, 'click', true); // note optional configuration parameter | 
|  *                                                              // which will be passed to addEventListener | 
|  * const clicksInDiv = fromEvent(someDivInDocument, 'click'); | 
|  * | 
|  * clicksInDocument.subscribe(() => console.log('document')); | 
|  * clicksInDiv.subscribe(() => console.log('div')); | 
|  * | 
|  * // By default events bubble UP in DOM tree, so normally | 
|  * // when we would click on div in document | 
|  * // "div" would be logged first and then "document". | 
|  * // Since we specified optional `capture` option, document | 
|  * // will catch event when it goes DOWN DOM tree, so console | 
|  * // will log "document" and then "div". | 
|  * ``` | 
|  * | 
|  * @see {@link bindCallback} | 
|  * @see {@link bindNodeCallback} | 
|  * @see {@link fromEventPattern} | 
|  * | 
|  * @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`. | 
|  * @param {EventListenerOptions} [options] Options to pass through to addEventListener | 
|  * @return {Observable<T>} | 
|  * @name fromEvent | 
|  */ | 
| export function fromEvent<T>( | 
|   target: FromEventTarget<T>, | 
|   eventName: string, | 
|   options?: EventListenerOptions | ((...args: any[]) => T), | 
|   resultSelector?: ((...args: any[]) => T) | 
| ): Observable<T> { | 
|   | 
|   if (isFunction(options)) { | 
|     // DEPRECATED PATH | 
|     resultSelector = options; | 
|     options = undefined; | 
|   } | 
|   if (resultSelector) { | 
|     // DEPRECATED PATH | 
|     return fromEvent<T>(target, eventName, <EventListenerOptions | undefined>options).pipe( | 
|       map(args => isArray(args) ? resultSelector(...args) : resultSelector(args)) | 
|     ); | 
|   } | 
|   | 
|   return new Observable<T>(subscriber => { | 
|     function handler(e: T) { | 
|       if (arguments.length > 1) { | 
|         subscriber.next(Array.prototype.slice.call(arguments)); | 
|       } else { | 
|         subscriber.next(e); | 
|       } | 
|     } | 
|     setupSubscription(target, eventName, handler, subscriber, options as EventListenerOptions); | 
|   }); | 
| } | 
|   | 
| function setupSubscription<T>(sourceObj: FromEventTarget<T>, eventName: string, | 
|                               handler: (...args: any[]) => void, subscriber: Subscriber<T>, | 
|                               options?: EventListenerOptions) { | 
|   let unsubscribe: () => void; | 
|   if (isEventTarget(sourceObj)) { | 
|     const source = sourceObj; | 
|     sourceObj.addEventListener(eventName, handler, options); | 
|     unsubscribe = () => source.removeEventListener(eventName, handler, options); | 
|   } else if (isJQueryStyleEventEmitter(sourceObj)) { | 
|     const source = sourceObj; | 
|     sourceObj.on(eventName, handler); | 
|     unsubscribe = () => source.off(eventName, handler); | 
|   } else if (isNodeStyleEventEmitter(sourceObj)) { | 
|     const source = sourceObj; | 
|     sourceObj.addListener(eventName, handler as NodeEventHandler); | 
|     unsubscribe = () => source.removeListener(eventName, handler as NodeEventHandler); | 
|   } else 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 { | 
|     throw new TypeError('Invalid event target'); | 
|   } | 
|   | 
|   subscriber.add(unsubscribe); | 
| } | 
|   | 
| function isNodeStyleEventEmitter(sourceObj: any): sourceObj is NodeStyleEventEmitter { | 
|   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 isEventTarget(sourceObj: any): sourceObj is HasEventTargetAddRemove<any> { | 
|   return sourceObj && typeof sourceObj.addEventListener === 'function' && typeof sourceObj.removeEventListener === 'function'; | 
| } |