123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532 |
- // Copyright (c) Microsoft, All rights reserved. See License.txt in the project root for license information.
- ;(function (factory) {
- var objectTypes = {
- 'function': true,
- 'object': true
- };
- function checkGlobal(value) {
- return (value && value.Object === Object) ? value : null;
- }
- var freeExports = (objectTypes[typeof exports] && exports && !exports.nodeType) ? exports : null;
- var freeModule = (objectTypes[typeof module] && module && !module.nodeType) ? module : null;
- var freeGlobal = checkGlobal(freeExports && freeModule && typeof global === 'object' && global);
- var freeSelf = checkGlobal(objectTypes[typeof self] && self);
- var freeWindow = checkGlobal(objectTypes[typeof window] && window);
- var moduleExports = (freeModule && freeModule.exports === freeExports) ? freeExports : null;
- var thisGlobal = checkGlobal(objectTypes[typeof this] && this);
- var root = freeGlobal || ((freeWindow !== (thisGlobal && thisGlobal.window)) && freeWindow) || freeSelf || thisGlobal || Function('return this')();
- // Because of build optimizers
- if (typeof define === 'function' && define.amd) {
- define(['./rx.binding', 'exports'], function (Rx, exports) {
- root.Rx = factory(root, exports, Rx);
- return root.Rx;
- });
- } else if (typeof module === 'object' && module && module.exports === freeExports) {
- module.exports = factory(root, module.exports, require('./rx'));
- } else {
- root.Rx = factory(root, {}, root.Rx);
- }
- }.call(this, function (root, exp, Rx, undefined) {
- // Aliases
- var Observable = Rx.Observable,
- observableFromPromise = Observable.fromPromise,
- observableThrow = Observable.throwError,
- AnonymousObservable = Rx.AnonymousObservable,
- ObservableBase = Rx.ObservableBase,
- AsyncSubject = Rx.AsyncSubject,
- disposableCreate = Rx.Disposable.create,
- CompositeDisposable = Rx.CompositeDisposable,
- immediateScheduler = Rx.Scheduler.immediate,
- defaultScheduler = Rx.Scheduler['default'],
- inherits = Rx.internals.inherits,
- isScheduler = Rx.Scheduler.isScheduler,
- isPromise = Rx.helpers.isPromise,
- isFunction = Rx.helpers.isFunction,
- isIterable = Rx.helpers.isIterable,
- isArrayLike = Rx.helpers.isArrayLike;
- var errorObj = {e: {}};
-
- function tryCatcherGen(tryCatchTarget) {
- return function tryCatcher() {
- try {
- return tryCatchTarget.apply(this, arguments);
- } catch (e) {
- errorObj.e = e;
- return errorObj;
- }
- };
- }
- var tryCatch = Rx.internals.tryCatch = function tryCatch(fn) {
- if (!isFunction(fn)) { throw new TypeError('fn must be a function'); }
- return tryCatcherGen(fn);
- };
- function thrower(e) {
- throw e;
- }
- Observable.wrap = function (fn) {
- function createObservable() {
- return Observable.spawn.call(this, fn.apply(this, arguments));
- }
- createObservable.__generatorFunction__ = fn;
- return createObservable;
- };
- var spawn = Observable.spawn = function () {
- var gen = arguments[0], self = this, args = [];
- for (var i = 1, len = arguments.length; i < len; i++) { args.push(arguments[i]); }
- return new AnonymousObservable(function (o) {
- var g = new CompositeDisposable();
- if (isFunction(gen)) { gen = gen.apply(self, args); }
- if (!gen || !isFunction(gen.next)) {
- o.onNext(gen);
- return o.onCompleted();
- }
- function processGenerator(res) {
- var ret = tryCatch(gen.next).call(gen, res);
- if (ret === errorObj) { return o.onError(ret.e); }
- next(ret);
- }
- processGenerator();
- function onError(err) {
- var ret = tryCatch(gen.next).call(gen, err);
- if (ret === errorObj) { return o.onError(ret.e); }
- next(ret);
- }
- function next(ret) {
- if (ret.done) {
- o.onNext(ret.value);
- o.onCompleted();
- return;
- }
- var obs = toObservable.call(self, ret.value);
- var value = null;
- var hasValue = false;
- if (Observable.isObservable(obs)) {
- g.add(obs.subscribe(function(val) {
- hasValue = true;
- value = val;
- }, onError, function() {
- hasValue && processGenerator(value);
- }));
- } else {
- onError(new TypeError('type not supported'));
- }
- }
- return g;
- });
- };
- function toObservable(obj) {
- if (!obj) { return obj; }
- if (Observable.isObservable(obj)) { return obj; }
- if (isPromise(obj)) { return Observable.fromPromise(obj); }
- if (isGeneratorFunction(obj) || isGenerator(obj)) { return spawn.call(this, obj); }
- if (isFunction(obj)) { return thunkToObservable.call(this, obj); }
- if (isArrayLike(obj) || isIterable(obj)) { return arrayToObservable.call(this, obj); }
- if (isObject(obj)) {return objectToObservable.call(this, obj);}
- return obj;
- }
- function arrayToObservable (obj) {
- return Observable.from(obj).concatMap(function(o) {
- if(Observable.isObservable(o) || isObject(o)) {
- return toObservable.call(null, o);
- } else {
- return Rx.Observable.just(o);
- }
- }).toArray();
- }
- function objectToObservable (obj) {
- var results = new obj.constructor(), keys = Object.keys(obj), observables = [];
- for (var i = 0, len = keys.length; i < len; i++) {
- var key = keys[i];
- var observable = toObservable.call(this, obj[key]);
- if(observable && Observable.isObservable(observable)) {
- defer(observable, key);
- } else {
- results[key] = obj[key];
- }
- }
- return Observable.forkJoin.apply(Observable, observables).map(function() {
- return results;
- });
- function defer (observable, key) {
- results[key] = undefined;
- observables.push(observable.map(function (next) {
- results[key] = next;
- }));
- }
- }
- function thunkToObservable(fn) {
- var self = this;
- return new AnonymousObservable(function (o) {
- fn.call(self, function () {
- var err = arguments[0], res = arguments[1];
- if (err) { return o.onError(err); }
- if (arguments.length > 2) {
- var args = [];
- for (var i = 1, len = arguments.length; i < len; i++) { args.push(arguments[i]); }
- res = args;
- }
- o.onNext(res);
- o.onCompleted();
- });
- });
- }
- function isGenerator(obj) {
- return isFunction (obj.next) && isFunction (obj['throw']);
- }
- function isGeneratorFunction(obj) {
- var ctor = obj.constructor;
- if (!ctor) { return false; }
- if (ctor.name === 'GeneratorFunction' || ctor.displayName === 'GeneratorFunction') { return true; }
- return isGenerator(ctor.prototype);
- }
- function isObject(val) {
- return Object == val.constructor;
- }
- /**
- * Invokes the specified function asynchronously on the specified scheduler, surfacing the result through an observable sequence.
- *
- * @example
- * var res = Rx.Observable.start(function () { console.log('hello'); });
- * var res = Rx.Observable.start(function () { console.log('hello'); }, Rx.Scheduler.timeout);
- * var res = Rx.Observable.start(function () { this.log('hello'); }, Rx.Scheduler.timeout, console);
- *
- * @param {Function} func Function to run asynchronously.
- * @param {Scheduler} [scheduler] Scheduler to run the function on. If not specified, defaults to Scheduler.timeout.
- * @param [context] The context for the func parameter to be executed. If not specified, defaults to undefined.
- * @returns {Observable} An observable sequence exposing the function's result value, or an exception.
- *
- * Remarks
- * * The function is called immediately, not during the subscription of the resulting sequence.
- * * Multiple subscriptions to the resulting sequence can observe the function's result.
- */
- Observable.start = function (func, context, scheduler) {
- return observableToAsync(func, context, scheduler)();
- };
- /**
- * Converts the function into an asynchronous function. Each invocation of the resulting asynchronous function causes an invocation of the original synchronous function on the specified scheduler.
- * @param {Function} function Function to convert to an asynchronous function.
- * @param {Scheduler} [scheduler] Scheduler to run the function on. If not specified, defaults to Scheduler.timeout.
- * @param {Mixed} [context] The context for the func parameter to be executed. If not specified, defaults to undefined.
- * @returns {Function} Asynchronous function.
- */
- var observableToAsync = Observable.toAsync = function (func, context, scheduler) {
- isScheduler(scheduler) || (scheduler = defaultScheduler);
- return function () {
- var args = arguments,
- subject = new AsyncSubject();
- scheduler.schedule(null, function () {
- var result;
- try {
- result = func.apply(context, args);
- } catch (e) {
- subject.onError(e);
- return;
- }
- subject.onNext(result);
- subject.onCompleted();
- });
- return subject.asObservable();
- };
- };
- function createCbObservable(fn, ctx, selector, args) {
- var o = new AsyncSubject();
- args.push(createCbHandler(o, ctx, selector));
- fn.apply(ctx, args);
- return o.asObservable();
- }
- function createCbHandler(o, ctx, selector) {
- return function handler () {
- var len = arguments.length, results = new Array(len);
- for(var i = 0; i < len; i++) { results[i] = arguments[i]; }
- if (isFunction(selector)) {
- results = tryCatch(selector).apply(ctx, results);
- if (results === errorObj) { return o.onError(results.e); }
- o.onNext(results);
- } else {
- if (results.length <= 1) {
- o.onNext(results[0]);
- } else {
- o.onNext(results);
- }
- }
- o.onCompleted();
- };
- }
- /**
- * Converts a callback function to an observable sequence.
- *
- * @param {Function} fn Function with a callback as the last parameter to convert to an Observable sequence.
- * @param {Mixed} [ctx] The context for the func parameter to be executed. If not specified, defaults to undefined.
- * @param {Function} [selector] A selector which takes the arguments from the callback to produce a single item to yield on next.
- * @returns {Function} A function, when executed with the required parameters minus the callback, produces an Observable sequence with a single value of the arguments to the callback as an array.
- */
- Observable.fromCallback = function (fn, ctx, selector) {
- return function () {
- typeof ctx === 'undefined' && (ctx = this);
- var len = arguments.length, args = new Array(len)
- for(var i = 0; i < len; i++) { args[i] = arguments[i]; }
- return createCbObservable(fn, ctx, selector, args);
- };
- };
- function createNodeObservable(fn, ctx, selector, args) {
- var o = new AsyncSubject();
- args.push(createNodeHandler(o, ctx, selector));
- fn.apply(ctx, args);
- return o.asObservable();
- }
- function createNodeHandler(o, ctx, selector) {
- return function handler () {
- var err = arguments[0];
- if (err) { return o.onError(err); }
- var len = arguments.length, results = [];
- for(var i = 1; i < len; i++) { results[i - 1] = arguments[i]; }
- if (isFunction(selector)) {
- var results = tryCatch(selector).apply(ctx, results);
- if (results === errorObj) { return o.onError(results.e); }
- o.onNext(results);
- } else {
- if (results.length <= 1) {
- o.onNext(results[0]);
- } else {
- o.onNext(results);
- }
- }
- o.onCompleted();
- };
- }
- /**
- * Converts a Node.js callback style function to an observable sequence. This must be in function (err, ...) format.
- * @param {Function} fn The function to call
- * @param {Mixed} [ctx] The context for the func parameter to be executed. If not specified, defaults to undefined.
- * @param {Function} [selector] A selector which takes the arguments from the callback minus the error to produce a single item to yield on next.
- * @returns {Function} An async function which when applied, returns an observable sequence with the callback arguments as an array.
- */
- Observable.fromNodeCallback = function (fn, ctx, selector) {
- return function () {
- typeof ctx === 'undefined' && (ctx = this);
- var len = arguments.length, args = new Array(len);
- for(var i = 0; i < len; i++) { args[i] = arguments[i]; }
- return createNodeObservable(fn, ctx, selector, args);
- };
- };
- function isNodeList(el) {
- if (root.StaticNodeList) {
- // IE8 Specific
- // instanceof is slower than Object#toString, but Object#toString will not work as intended in IE8
- return el instanceof root.StaticNodeList || el instanceof root.NodeList;
- } else {
- return Object.prototype.toString.call(el) === '[object NodeList]';
- }
- }
- function ListenDisposable(e, n, fn) {
- this._e = e;
- this._n = n;
- this._fn = fn;
- this._e.addEventListener(this._n, this._fn, false);
- this.isDisposed = false;
- }
- ListenDisposable.prototype.dispose = function () {
- if (!this.isDisposed) {
- this._e.removeEventListener(this._n, this._fn, false);
- this.isDisposed = true;
- }
- };
- function createEventListener (el, eventName, handler) {
- var disposables = new CompositeDisposable();
- // Asume NodeList or HTMLCollection
- var elemToString = Object.prototype.toString.call(el);
- if (isNodeList(el) || elemToString === '[object HTMLCollection]') {
- for (var i = 0, len = el.length; i < len; i++) {
- disposables.add(createEventListener(el.item(i), eventName, handler));
- }
- } else if (el) {
- disposables.add(new ListenDisposable(el, eventName, handler));
- }
- return disposables;
- }
- /**
- * Configuration option to determine whether to use native events only
- */
- Rx.config.useNativeEvents = false;
- var EventObservable = (function(__super__) {
- inherits(EventObservable, __super__);
- function EventObservable(el, name, fn) {
- this._el = el;
- this._n = name;
- this._fn = fn;
- __super__.call(this);
- }
- function createHandler(o, fn) {
- return function handler () {
- var results = arguments[0];
- if (isFunction(fn)) {
- results = tryCatch(fn).apply(null, arguments);
- if (results === errorObj) { return o.onError(results.e); }
- }
- o.onNext(results);
- };
- }
- EventObservable.prototype.subscribeCore = function (o) {
- return createEventListener(
- this._el,
- this._n,
- createHandler(o, this._fn));
- };
- return EventObservable;
- }(ObservableBase));
- /**
- * Creates an observable sequence by adding an event listener to the matching DOMElement or each item in the NodeList.
- * @param {Object} element The DOMElement or NodeList to attach a listener.
- * @param {String} eventName The event name to attach the observable sequence.
- * @param {Function} [selector] A selector which takes the arguments from the event handler to produce a single item to yield on next.
- * @returns {Observable} An observable sequence of events from the specified element and the specified event.
- */
- Observable.fromEvent = function (element, eventName, selector) {
- // Node.js specific
- if (element.addListener) {
- return fromEventPattern(
- function (h) { element.addListener(eventName, h); },
- function (h) { element.removeListener(eventName, h); },
- selector);
- }
- // Use only if non-native events are allowed
- if (!Rx.config.useNativeEvents) {
- // Handles jq, Angular.js, Zepto, Marionette, Ember.js
- if (typeof element.on === 'function' && typeof element.off === 'function') {
- return fromEventPattern(
- function (h) { element.on(eventName, h); },
- function (h) { element.off(eventName, h); },
- selector);
- }
- }
- return new EventObservable(element, eventName, selector).publish().refCount();
- };
- var EventPatternObservable = (function(__super__) {
- inherits(EventPatternObservable, __super__);
- function EventPatternObservable(add, del, fn) {
- this._add = add;
- this._del = del;
- this._fn = fn;
- __super__.call(this);
- }
- function createHandler(o, fn) {
- return function handler () {
- var results = arguments[0];
- if (isFunction(fn)) {
- results = tryCatch(fn).apply(null, arguments);
- if (results === errorObj) { return o.onError(results.e); }
- }
- o.onNext(results);
- };
- }
- EventPatternObservable.prototype.subscribeCore = function (o) {
- var fn = createHandler(o, this._fn);
- var returnValue = this._add(fn);
- return new EventPatternDisposable(this._del, fn, returnValue);
- };
- function EventPatternDisposable(del, fn, ret) {
- this._del = del;
- this._fn = fn;
- this._ret = ret;
- this.isDisposed = false;
- }
- EventPatternDisposable.prototype.dispose = function () {
- if(!this.isDisposed) {
- isFunction(this._del) && this._del(this._fn, this._ret);
- this.isDisposed = true;
- }
- };
- return EventPatternObservable;
- }(ObservableBase));
- /**
- * Creates an observable sequence from an event emitter via an addHandler/removeHandler pair.
- * @param {Function} addHandler The function to add a handler to the emitter.
- * @param {Function} [removeHandler] The optional function to remove a handler from an emitter.
- * @param {Function} [selector] A selector which takes the arguments from the event handler to produce a single item to yield on next.
- * @returns {Observable} An observable sequence which wraps an event from an event emitter
- */
- var fromEventPattern = Observable.fromEventPattern = function (addHandler, removeHandler, selector) {
- return new EventPatternObservable(addHandler, removeHandler, selector).publish().refCount();
- };
- /**
- * Invokes the asynchronous function, surfacing the result through an observable sequence.
- * @param {Function} functionAsync Asynchronous function which returns a Promise to run.
- * @returns {Observable} An observable sequence exposing the function's result value, or an exception.
- */
- Observable.startAsync = function (functionAsync) {
- var promise = tryCatch(functionAsync)();
- if (promise === errorObj) { return observableThrow(promise.e); }
- return observableFromPromise(promise);
- };
- return Rx;
- }));
|