├── .gitignore
├── .jshintrc
├── koans
├── Answers
│ ├── lesson1-observablestreams.js
│ ├── lesson2-ComposableObservations.js
│ ├── lesson3-Time.js
│ ├── lesson4-Events.js
│ └── lesson6-AdvancedStreams.js
├── issue.js
├── lesson1-observablestreams.js
├── lesson2-ComposableObservations.js
├── lesson3-Time.js
├── lesson4-Events.js
└── lesson6-AdvancedStreams.js
├── lib
├── IxJs
│ ├── .gitattributes
│ ├── .gitignore
│ ├── ixjs.js
│ ├── l2o.js
│ └── tests
│ │ ├── L2O.html
│ │ ├── aggregates.js
│ │ ├── creation.js
│ │ └── vendor
│ │ ├── qunit-1.9.0.css
│ │ ├── qunit-1.9.0.js
│ │ └── qunit-clib.js
├── PermutationsAndShuffles.cs.linq
├── PermutationsAndShuffles.js
├── ixjs.js
├── jquery-1.5.1.js
├── koanutils.js
├── l2o.js
├── qunit.css
├── qunit.js
├── rx-vsdoc.js
├── rx.aggregates-vsdoc.js
├── rx.aggregates.js
├── rx.aggregates.min.js
├── rx.binding-vsdoc.js
├── rx.binding.js
├── rx.binding.min.js
├── rx.coincidence-vsdoc.js
├── rx.coincidence.js
├── rx.coincidence.min.js
├── rx.experimental-vsdoc.js
├── rx.experimental.js
├── rx.experimental.min.js
├── rx.jQuery.js
├── rx.joinpatterns-vsdoc.js
├── rx.joinpatterns.js
├── rx.joinpatterns.min.js
├── rx.joins.js
├── rx.js
├── rx.min.js
├── rx.node.js
├── rx.testing-vsdoc.js
├── rx.testing.js
├── rx.testing.min.js
├── rx.time-vsdoc.js
├── rx.time.js
└── rx.time.min.js
├── readme
└── rxkoans.html
/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Eclipse
3 | #################
4 |
5 | *.pydevproject
6 | .project
7 | .metadata
8 | bin/
9 | tmp/
10 | *.tmp
11 | *.bak
12 | *.swp
13 | *~.nib
14 | local.properties
15 | .classpath
16 | .settings/
17 | .loadpath
18 |
19 | # External tool builders
20 | .externalToolBuilders/
21 |
22 | # Locally stored "Eclipse launch configurations"
23 | *.launch
24 |
25 | # CDT-specific
26 | .cproject
27 |
28 | # PDT-specific
29 | .buildpath
30 |
31 |
32 | #################
33 | ## Visual Studio
34 | #################
35 |
36 | ## Ignore Visual Studio temporary files, build results, and
37 | ## files generated by popular Visual Studio add-ons.
38 |
39 | # User-specific files
40 | *.suo
41 | *.user
42 | *.sln.docstates
43 |
44 | # Build results
45 | [Dd]ebug/
46 | [Rr]elease/
47 | *_i.c
48 | *_p.c
49 | *.ilk
50 | *.meta
51 | *.obj
52 | *.pch
53 | *.pdb
54 | *.pgc
55 | *.pgd
56 | *.rsp
57 | *.sbr
58 | *.tlb
59 | *.tli
60 | *.tlh
61 | *.tmp
62 | *.vspscc
63 | .builds
64 | *.dotCover
65 |
66 | ## TODO: If you have NuGet Package Restore enabled, uncomment this
67 | #packages/
68 |
69 | # Visual C++ cache files
70 | ipch/
71 | *.aps
72 | *.ncb
73 | *.opensdf
74 | *.sdf
75 |
76 | # Visual Studio profiler
77 | *.psess
78 | *.vsp
79 |
80 | # ReSharper is a .NET coding add-in
81 | _ReSharper*
82 |
83 | # Installshield output folder
84 | [Ee]xpress
85 |
86 | # DocProject is a documentation generator add-in
87 | DocProject/buildhelp/
88 | DocProject/Help/*.HxT
89 | DocProject/Help/*.HxC
90 | DocProject/Help/*.hhc
91 | DocProject/Help/*.hhk
92 | DocProject/Help/*.hhp
93 | DocProject/Help/Html2
94 | DocProject/Help/html
95 |
96 | # Click-Once directory
97 | publish
98 |
99 | # Others
100 | [Bb]in
101 | [Oo]bj
102 | sql
103 | TestResults
104 | *.Cache
105 | ClientBin
106 | stylecop.*
107 | ~$*
108 | *.dbmdl
109 | Generated_Code #added for RIA/Silverlight projects
110 |
111 | # Backup & report files from converting an old project file to a newer
112 | # Visual Studio version. Backup files are not needed, because we have git ;-)
113 | _UpgradeReport_Files/
114 | Backup*/
115 | UpgradeLog*.XML
116 |
117 |
118 |
119 | ############
120 | ## Windows
121 | ############
122 |
123 | # Windows image file caches
124 | Thumbs.db
125 |
126 | # Folder config file
127 | Desktop.ini
128 |
129 |
130 | #############
131 | ## Python
132 | #############
133 |
134 | *.py[co]
135 |
136 | # Packages
137 | *.egg
138 | *.egg-info
139 | dist
140 | build
141 | eggs
142 | parts
143 | bin
144 | var
145 | sdist
146 | develop-eggs
147 | .installed.cfg
148 |
149 | # Installer logs
150 | pip-log.txt
151 |
152 | # Unit test / coverage reports
153 | .coverage
154 | .tox
155 |
156 | #Translations
157 | *.mo
158 |
159 | #Mr Developer
160 | .mr.developer.cfg
161 |
162 | # Mac crap
163 | .DS_Store
164 |
165 | # Emacs junk
166 | *.*~
167 | \#*\#
168 | .\#*
169 | *.log
170 |
171 | Doc/Decoding.synctex.gz
172 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "browser": true,
4 | "esnext": true,
5 | "bitwise": true,
6 | "camelcase": true,
7 | "curly": true,
8 | "eqeqeq": true,
9 | "immed": true,
10 | "indent": 4,
11 | "latedef": true,
12 | "newcap": true,
13 | "noarg": true,
14 | "quotmark": "single",
15 | "regexp": true,
16 | "undef": true,
17 | "unused": false,
18 | "strict": false,
19 | "trailing": true,
20 | "smarttabs": true,
21 | "globals": {
22 | "test": false,
23 | "equals": false,
24 | "Rx": false,
25 | "L2O": false,
26 | "Range": false
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/koans/Answers/lesson1-observablestreams.js:
--------------------------------------------------------------------------------
1 | module('Lesson 1 - Observable Streams');
2 |
3 | /*
4 | * Step 1: find the 1st method that fails
5 | * Step 2: Fill in the blank ____ to make it pass
6 | * Step 3: run it again
7 | * Note: Do not change anything other than the blank
8 | */
9 |
10 | test('ObjectsFirst', function () {
11 | var xs = L2O.Enumerable.fromArray([1, 2, 3]);
12 | equals(xs.first(), 1/*_______*/);
13 |
14 | var itsOk = L2O.Enumerable
15 | .returnValue(42);
16 | equals(itsOk.first(), 42 /*_______*/);
17 | });
18 |
19 | test('SimpleSubscription', function() {
20 | Rx.Observable
21 | .returnValue(42)
22 | .subscribe(function(x) { equals(x, 42 /*_______*/); });
23 | });
24 |
25 | test('SimpleReturn', function() {
26 | var received = '';
27 | Rx.Observable
28 | .returnValue('Foo')
29 | .subscribe(function(x) { received = x; });
30 | equals(received, 'Foo'/*_______*/);
31 | });
32 |
33 | test('TheLastEvent', function() {
34 | var received = '';
35 | var numbers = ['Foo','Bar'];
36 | Rx.Observable
37 | .fromArray(numbers)
38 | .subscribe(function(x) { received = x; });
39 | equals(received, 'Bar'/*_______*/);
40 | });
41 |
42 | test('EveryThingCounts', function() {
43 | var received = 0;
44 | var numbers = [3, 4 ];
45 | Rx.Observable
46 | .fromArray(numbers)
47 | .subscribe(function(x) { received += x; });
48 | equals(received, 7/*_______*/);
49 | });
50 |
51 | test('DoingInTheMiddle', function() {
52 | var status = [];
53 | var daysTillTest = Range.create(1, 4).reverse().toObservable();
54 | daysTillTest
55 | .doAction(
56 | function(d) { status.push(
57 | d + '=' + (d === 1 ? 'Study Like Mad' : 'Party'/*_______*/));
58 | })
59 | .subscribe();
60 | equals(
61 | status.toString(),
62 | '4=Party,3=Party,2=Party,1=Study Like Mad');
63 | });
64 |
65 | test('NothingListensUntilYouSubscribe', function() {
66 | var sum = 0;
67 | var numbers = Range.create(1,10).toObservable();
68 | var observable = numbers
69 | .doAction(function(n) { sum += n; });
70 |
71 | equals(0, sum);
72 |
73 | observable.subscribe/*_______*/();
74 |
75 | equals(55, sum);
76 | });
77 |
--------------------------------------------------------------------------------
/koans/Answers/lesson2-ComposableObservations.js:
--------------------------------------------------------------------------------
1 | module('Lesson 2 - Composable Observations');
2 |
3 | /*
4 | * Step 1: find the 1st method that fails
5 | * Step 2: Fill in the blank ____ to make it pass
6 | * Step 3: run it again
7 | * Note: Do not change anything other than the blank
8 | */
9 |
10 | test('ComposableAddition', function() {
11 | var received = 0;
12 | var numbers = [10, 100, 1000/*_______*/];
13 | numbers
14 | .toObservable()
15 | .sum()
16 | .subscribe(function(x) { received = x; });
17 | equals(received, 1110);
18 | });
19 |
20 | test('ComposeableBeforeAndAfter', function() {
21 | var names = Range.create(1, 6),
22 | a = '',
23 | b = '';
24 | names
25 | .toObservable()
26 | .doAction(function(n) { a += n.toString(); })
27 | .where(function(n) { return n % 2 === 0; })
28 | .doAction(function(n) { b += n.toString(); })
29 | .subscribe();
30 | equals(a, '123456'/*_______*/);
31 | equals(b, '246');
32 | });
33 |
34 | test('WeWroteThis', function() {
35 | var received = [];
36 | var names = ['Bart', 'Wes', 'Erik', 'Matthew', 'Brian'];
37 | names
38 | .toObservable()
39 | .where(function(n) { return n.length <= 4/*_______*/; })
40 | .subscribe(function(x) { received.push(x); });
41 | equals(received.toString(), 'Bart,Wes,Erik');
42 | });
43 |
44 | test('ConvertingEvents', function() {
45 | var received = '';
46 | var names = ['wE', 'hOpE', 'yOU', 'aRe', 'eNJoyIng', 'tHiS' ];
47 | names
48 | .toObservable()
49 | .select(function(x) { return x.toLowerCase()/*_______*/; })
50 | .subscribe(function(x) { received += x + ' '; });
51 | equals(received, 'we hope you are enjoying this ');
52 | });
53 |
54 | test('CreatingAMoreRelevantEventStream', function() {
55 | var received = '',
56 | mouseXMovements = [100, 200, 150],
57 | windowTopX = 50,
58 | relativemouse = mouseXMovements
59 | .toObservable()
60 | .select(function(x) { return x - windowTopX/*_______*/; });
61 |
62 | relativemouse.subscribe(function(x) { received += x + ', '; });
63 | equals(received, '50, 150, 100, ');
64 | });
65 |
66 | test('CheckingEverything', function() {
67 | var received = null;
68 | var numbers = [ 2, 4, 6, 8 ];
69 | numbers
70 | .toObservable()
71 | .all(function(x) { return x % 2 === 0; })
72 | .subscribe(function(x) { received = x; });
73 | equals(received, true/*_______*/);
74 | });
75 |
76 | test('CompositionMeansTheSumIsGreaterThanTheParts', function() {
77 | var numbers = Rx.Observable.range(1, 10);
78 | numbers
79 | .where(function(x) { return x > 8/*_______*/; })
80 | .sum()
81 | .subscribe(function(x) { equals(19, x); });
82 | });
83 |
--------------------------------------------------------------------------------
/koans/Answers/lesson3-Time.js:
--------------------------------------------------------------------------------
1 | module('Lesson 3 - Time');
2 |
3 | /*
4 | * Step 1: find the 1st method that fails
5 | * Step 2: Fill in the blank ____ to make it pass
6 | * Step 3: run it again
7 | * Note: Do not change anything other than the blank
8 | */
9 |
10 | asyncTest('LaunchingAnActionInTheFuture', function() {
11 | var received = '';
12 | var delay = 250/*_______*/;
13 | Rx
14 | .Scheduler
15 | .immediate
16 | .schedule(function() { received = 'Finished'; }, delay);
17 |
18 | setTimeout(function() { equals(received, 'Finished'); start(); }, 500);
19 | });
20 |
21 | asyncTest('LaunchingAnEventInTheFuture', function() {
22 | var received = '',
23 | time = 250/*_______*/;
24 |
25 | Rx
26 | .Observable
27 | .returnValue('Godot', Rx.Scheduler.Immediate)
28 | .delay(time)
29 | .subscribe(function(x) { received = x; });
30 |
31 | setTimeout(function() { equals(received, 'Godot'); start(); }, 500);
32 | });
33 |
34 | asyncTest('AWatchedPot', function() {
35 | var received = '',
36 | delay = 500,
37 | timeout = 650/*_______*/,
38 | timeoutEvent =
39 | Rx .Observable
40 | .returnValue('Tepid');
41 |
42 | Rx
43 | .Observable
44 | .returnValue('Boiling')
45 | .delay(delay)
46 | .timeout(timeout, timeoutEvent)
47 | .subscribe(function(x) { received = x; });
48 |
49 | setTimeout(function() { equals(received, 'Boiling'); start(); }, 500);
50 | });
51 |
52 |
--------------------------------------------------------------------------------
/koans/Answers/lesson4-Events.js:
--------------------------------------------------------------------------------
1 | module('Lesson 4 - Events');
2 |
3 | test('listening to events', function() {
4 | var received = '';
5 | var subscription =
6 | $(document)
7 | .toObservable('foo')
8 | .subscribe(function(e) { received += e.payload; });
9 |
10 | $(document).trigger({ type: 'foo', payload : 'M'});
11 | $(document).trigger({ type: 'foo', payload : 'A'});
12 | $(document).trigger({ type: 'foo', payload : 'T'});
13 | subscription.dispose();
14 | $(document).trigger({ type: 'foo', payload : 'T'});
15 |
16 | equals(received, 'MAT'/*_______*/);
17 | });
18 |
19 | test('listening to the right events', function() {
20 | var received = '';
21 | var subscription =
22 | $(document)
23 | .toObservable('foo')
24 | .subscribe(function(e) { received += e.payload; });
25 |
26 | $(document).trigger({ type: 'foo', payload : 'M'});
27 | $(document).trigger({ type: 'bar', payload : 'A'});
28 | $(document).trigger({ type: 'foo', payload : 'T'});
29 | $(document).trigger({ type: 'foo', payload : 'T'});
30 | subscription.dispose();
31 |
32 | equals(received, 'MTT'/*_______*/);
33 | });
34 |
--------------------------------------------------------------------------------
/koans/Answers/lesson6-AdvancedStreams.js:
--------------------------------------------------------------------------------
1 | module('Lesson 6 - Advanced Streams');
2 |
3 | test('Merging', function() {
4 | var easy = [],
5 | you = [1,2,3].toObservable(),
6 | me = ['A','B','C'].toObservable();
7 | you
8 | .merge(me)
9 | .subscribe(function(a) { easy.push(a); });
10 |
11 | // equals(easy === '1 A 2 B 3 C ' || easy === '1 2 3 A B C ', true/*_______*/);
12 |
13 | // Actually, this is not so easy! The result could be any arbitrary
14 | // riffle of the original two streams. More later on Riffles in JS.
15 |
16 | riffles([1, 2, 3].toEnumerable(), ['A', 'B', 'C'].toEnumerable())
17 | .forEach(function(riffle) {
18 | console.log("riffle: ", riffle.toArray());
19 | });
20 | console.log("easy: ", easy);
21 |
22 | equals( riffles([1, 2, 3].toEnumerable(), ['A', 'B', 'C'].toEnumerable())
23 | .select(function (riffle) {return riffle.toArray();})
24 | .contains(easy, arrayComparer),
25 | true);
26 |
27 |
28 | });
29 |
30 | // Given a 1-based index n, produces a function that will pluck the n-th
31 | // item from any Enumerable and return it. Pluck produces a function so
32 | // that it can be mapped over Enumerables of Enumerables, say to produce
33 | // a columnar slice from an array. WARNING: these are 1-based indices!
34 | var pluck = function (n) {
35 | return function(xs) {
36 | if (n <= 0 || n > xs.count)
37 | throw new Error('index out of range');
38 | return xs.elementAt(n - 1);
39 | };
40 | };
41 |
42 | // Given a 1-based index n, produces a function that will produce an
43 | // Enumerable with the n-th item missing. WARNING: these are 1-based
44 | // indices!
45 | var coPluck = function(n) {
46 | return function(xs) {
47 |
48 | // is the following error-checking redundant? The error-handling
49 | // policy of Ix is not clear to me at this point! (4 Nov 12)
50 |
51 | // if (! (xs instanceof Ix.Enumerable) )
52 | // throw new Error('xs must be an Ix.Enumerable');
53 | var c = xs.count();
54 | if (n <= 0 || n > c)
55 | throw new Error('index out of range');
56 | var ys = [];
57 | var i = 1;
58 | xs.forEach( function (x) {
59 | if (i != n)
60 | ys.push(x);
61 | i++;
62 | });
63 | return ys.toEnumerable();
64 | };
65 | };
66 |
67 | // A function that compares arrays for equality given an optional
68 | // elementComparer. Be aware that this is not sufficiently flexible
69 | // to work on arrayw of arbitrary nesting.
70 | var arrayComparer = function (xs, ys, elementComparer) {
71 | if ( (! (xs instanceof Array)) || (! (ys instanceof Array)) )
72 | return false;
73 | var xl = xs.length;
74 | var yl = ys.length;
75 | if (xl != yl)
76 | return false;
77 | elementComparer || (elementComparer = function(x, y) { return x === y; });
78 | var i;
79 | for (i = 0; i < xl; i++)
80 | if (! elementComparer(xs[i], ys[i]))
81 | return false;
82 | return true;
83 | };
84 |
85 | // Produces an Enumerable of all splits of another Enumerable, as an
86 | // Enumerable of pairs of left and right after the splits. A more
87 | // sophisticated implementation would build the nested enumerators.
88 | var splits = function(xs) {
89 | var c = xs.count();
90 | var ys = [];
91 | for (var i = 0; i <= c; i++)
92 | // ys.push( [xs.take(i), xs.skip(i)].toEnumerable() );
93 | ys.push( [xs.take(i).toArray().slice(0).toEnumerable(),
94 | xs.skip(i).toArray().slice(0).toEnumerable()]
95 | .toEnumerable() );
96 | return ys.toEnumerable();
97 | };
98 |
99 | // Produces an Enumerable of all riffles of two other Enumerables. A more
100 | // sophisticated implementation would build the nested enumerators.
101 | var riffles = function(left, right) {
102 | if (left.count() === 0)
103 | return Ix.Enumerable.returnValue(right);
104 | if (right.count() === 0)
105 | return Ix.Enumerable.returnValue(left);
106 | var ys = [];
107 |
108 | splits(right).skip(1).take(1).forEach( function(r)
109 | { splits(left).forEach( function(l)
110 | { riffles(l.elementAt(1), r.elementAt(1)).forEach( function(f)
111 | { ys.push(l.first().concat(r.first()).concat(f));
112 | }); }); });
113 |
114 | return ys.toEnumerable();
115 | };
116 |
117 | test('Riffles', function() {
118 | var e = [1, 2, 3].toEnumerable();
119 |
120 | equals(e.contains(2), true);
121 | equals(e.count(), 3);
122 | equals([[1, 2], [3, 4]].toEnumerable().contains([3, 4], arrayComparer), true);
123 |
124 | e.forEach(function (x) { equals( pluck(x)(e), x ); });
125 |
126 | // Expecting exceptions to be thrown
127 | try { pluck(0)(e); equals(false, true); }
128 | catch (exception) { equals(true, true); }
129 |
130 | try { pluck(4)(e); equals(false, true); }
131 | catch (exception) { equals(true, true); }
132 |
133 | try { pluck(-2)(e); equals(false, true); }
134 | catch (exception) { equals(true, true); }
135 |
136 | equals( arrayComparer(coPluck(2)(e).toArray(), [1, 3]), true );
137 |
138 | equals( arrayComparer(riffles(e, Ix.Enumerable.empty()).first().toArray(),
139 | e.toArray()), true);
140 | equals( arrayComparer(riffles(Ix.Enumerable.empty(), e).first().toArray(),
141 | e.toArray()), true);
142 | equals( riffles([1,2,3].toEnumerable(), [4,5,6].toEnumerable())
143 | .select(function (riffle) {return riffle.toArray();})
144 | .contains([1,2,4,5,3,6], arrayComparer),
145 | true);
146 | });
147 |
148 | var floatingEquals = function (a, b, digits) {
149 | var exponent = Math.abs( digits || 12 );
150 | var multiplier = Math.pow(10, exponent);
151 | return Math.round( multiplier * a ) === Math.round( multiplier * b);
152 | };
153 |
154 | test('DescriptiveStatistics', function () {
155 | var e = [1, 2, 3].toEnumerable();
156 | equals(e.standardDeviation(), 1);
157 |
158 | equals(floatingEquals(
159 | [1, 2].toEnumerable().standardDeviation(),
160 | 1 / Math.sqrt(2)), true);
161 |
162 | // Should be sqrt ( (1^2 + 2^2 + 4^2 - 7^2 / 3) / 2 )
163 | // = sqrt( (1 + 4 + 16 - 49 / 3) / 2 )
164 | // = sqrt( (21 - 49 / 3) / 2 )
165 | // = sqrt( (63 - 49) / 6 )
166 | // = sqrt( 14 / 6 )
167 | // = sqrt( 7 / 3 )
168 |
169 | equals(floatingEquals(
170 | [1, 2, 4]
171 | .toEnumerable()
172 | .standardDeviation(),
173 | Math.sqrt(7 / 3)), true);
174 |
175 | [1, 2, 4]
176 | .toObservable()
177 | .standardDeviation()
178 | .subscribe(function (s) {
179 | console.log(s);
180 | equals(floatingEquals(s, Math.sqrt(7 / 3)), true); });
181 | });
182 |
183 |
184 | test('Splitting Up', function() {
185 | var oddsAndEvens = ['',''];
186 | numbers = Rx.Observable.range(1, 9),
187 | split = numbers
188 | .groupBy(function(n) { return n % 2 /*_______*/; });
189 |
190 | split.subscribe(function (g) {
191 | return g.subscribe(
192 | function (i) {
193 | return console.log(i, g.key);
194 | });
195 | });
196 |
197 | split
198 | .subscribe(function(group) {
199 | group
200 | .subscribe(function(n) { oddsAndEvens[group.key] += n; });
201 | });
202 |
203 | var evens = oddsAndEvens[0],
204 | odds = oddsAndEvens[1];
205 |
206 | equals(evens, '2468');
207 | equal(odds, '13579');
208 | });
209 |
210 |
211 | test('Subscribe Imediately When Splitting', function() {
212 | var averages = [0.0,0.0],
213 | numbers = [22,22,99,22,101,22].toObservable(),
214 | split = numbers
215 | .groupBy(function(n) { return n % 2; });
216 | split
217 | .subscribe(function(g) {
218 | g
219 | .average()
220 | .subscribe/*_______*/(function(a) { averages[g.key] = a; });
221 | });
222 | equals(22, averages[0]);
223 | equals(100, averages[1]);
224 | });
225 |
226 | test('Multiple Subscriptions', function() {
227 | var numbers = new Rx.Subject(),
228 | sum = 0,
229 | average = 0;
230 |
231 | numbers
232 | .sum()
233 | .subscribe(function(n) { sum = n; });
234 | numbers.onNext(1);
235 | numbers.onNext(1);
236 | numbers.onNext(1);
237 | numbers.onNext(1);
238 | numbers.onNext(1);
239 |
240 | numbers
241 | .average()
242 | .subscribe(function(n) {
243 | average = n;
244 | // Bug, not called?
245 | });
246 | numbers.onNext(2);
247 | numbers.onNext(2);
248 | numbers.onNext(2);
249 | numbers.onNext(2);
250 | numbers.onNext(2);
251 |
252 | numbers.onCompleted();
253 |
254 | equals(sum, 15);
255 | equals(average, 2/*_______*/);
256 | });
257 |
258 |
259 |
--------------------------------------------------------------------------------
/koans/issue.js:
--------------------------------------------------------------------------------
1 | module('issue -- possible bug for investigation');
2 |
3 | // Produces an Enumerable of all splits of another Enumerable, as an
4 | // Enumerable of pairs of left and right after the splits. A more
5 | // sophisticated implementation would build the nested enumerators.
6 | var splits = function(xs) {
7 | var c = xs.count();
8 | var ys = [];
9 | for (var i = 0; i <= c; i++)
10 | // ys.push( [xs.take(i), xs.skip(i)].toEnumerable() );
11 | ys.push( [xs.take(i).toArray().slice(0).toEnumerable(),
12 | xs.skip(i).toArray().slice(0).toEnumerable()]
13 | .toEnumerable() );
14 | return ys.toEnumerable();
15 | };
16 |
17 | // Produces an Enumerable of all riffles of two other Enumerables. A more
18 | // sophisticated implementation would build the nested enumerators.
19 | var riffles = function(left, right) {
20 | if (left.count() === 0)
21 | return Ix.Enumerable.returnValue(right);
22 | if (right.count() === 0)
23 | return Ix.Enumerable.returnValue(left);
24 | var ys = [];
25 |
26 | splits(right).skip(1).take(1).forEach( function(r)
27 | { splits(left).forEach( function(l)
28 | { riffles(l.elementAt(1), r.elementAt(1)).forEach( function(f)
29 | { ys.push(l.first().concat(r.first()).concat(f));
30 | }); }); });
31 |
32 | return ys.toEnumerable();
33 | };
34 |
35 | // A function that compares arrays for equality given an optional
36 | // elementComparer. Be aware that this is not sufficiently flexible
37 | // to work on arrayw of arbitrary nesting.
38 | var arrayComparer = function (xs, ys, elementComparer) {
39 | if ( (! (xs instanceof Array)) || (! (ys instanceof Array)) )
40 | return false;
41 | var xl = xs.length;
42 | var yl = ys.length;
43 | if (xl != yl)
44 | return false;
45 | elementComparer || (elementComparer = function(x, y) { return x === y; });
46 | var i;
47 | for (i = 0; i < xl; i++)
48 | if (! elementComparer(xs[i], ys[i]))
49 | return false;
50 | return true;
51 | };
52 |
53 | test('Riffles', function() {
54 | // splits([1, 2, 3].toEnumerable()).forEach( function(s) {
55 | // console.log("split: ",
56 | // s.toArray().slice(0)[0].toArray().slice(0),
57 | // s.toArray().slice(0)[1].toArray().slice(0));
58 | // });
59 | var e = [1, 2, 3].toEnumerable();
60 | // riffles([].toEnumerable(), [].toEnumerable())
61 | // .forEach(function(riffle) {
62 | // console.log("riffle: ", riffle.toArray());
63 | // });
64 | // riffles([1].toEnumerable(), [].toEnumerable())
65 | // .forEach(function(riffle) {
66 | // console.log("riffle: ", riffle.toArray());
67 | // });
68 | // riffles([].toEnumerable(), [4].toEnumerable())
69 | // .forEach(function(riffle) {
70 | // console.log("riffle: ", riffle.toArray());
71 | // });
72 | // riffles([1].toEnumerable(), [4].toEnumerable())
73 | // .forEach(function(riffle) {
74 | // console.log("riffle: ", riffle.toArray());
75 | // });
76 | riffles([1, 2, 3].toEnumerable(), [4, 5, 6].toEnumerable())
77 | .forEach(function(riffle) {
78 | console.log("riffle: ", riffle.toArray());
79 | });
80 |
81 | //riffles([1, 2, 3].toEnumerable(), [4].toEnumerable());
82 |
83 | equals( arrayComparer(riffles(e, Ix.Enumerable.empty()).first().toArray(),
84 | e.toArray()), true);
85 | equals( arrayComparer(riffles(Ix.Enumerable.empty(), e).first().toArray(),
86 | e.toArray()), true);
87 | equals( riffles([1,2,3].toEnumerable(), [4,5,6].toEnumerable())
88 | .select(function (riffle) {return riffle.toArray();})
89 | .contains([1,2,4,5,3,6], arrayComparer),
90 | true);
91 | });
92 |
93 |
--------------------------------------------------------------------------------
/koans/lesson1-observablestreams.js:
--------------------------------------------------------------------------------
1 | module('Lesson 1 - Observable Streams');
2 |
3 | /*
4 | * Step 1: find the 1st method that fails
5 | * Step 2: Fill in the blank ____ to make it pass
6 | * Step 3: run it again
7 | * Note: Do not change anything other than the blank
8 | */
9 |
10 | test('ObjectsFirst', function () {
11 | var xs = L2O.Enumerable.fromArray([1, 2, 3]);
12 | equals(xs.first(), _______);
13 |
14 | var itsOk = L2O.Enumerable
15 | .returnValue(42);
16 | equals(itsOk.first(), _______);
17 | });
18 |
19 | test('SimpleSubscription', function() {
20 | Rx.Observable
21 | .returnValue(42)
22 | .subscribe(function(x) { equals(x, _______); });
23 | });
24 |
25 | test('SimpleReturn', function() {
26 | var received = '';
27 | Rx.Observable
28 | .returnValue('Foo')
29 | .subscribe(function(x) { received = x; });
30 | equals(received, _______);
31 | });
32 |
33 | test('TheLastEvent', function() {
34 | var received = '';
35 | var numbers = ['Foo','Bar'];
36 | Rx.Observable
37 | .fromArray(numbers)
38 | .subscribe(function(x) { received = x; });
39 | equals(received, _______);
40 | });
41 |
42 | test('EveryThingCounts', function() {
43 | var received = 0;
44 | var numbers = [3, 4 ];
45 | Rx.Observable
46 | .fromArray(numbers)
47 | .subscribe(function(x) { received += x; });
48 | equals(received, _______);
49 | });
50 |
51 | test('DoingInTheMiddle', function() {
52 | var status = [];
53 | var daysTillTest = Range.create(1, 4).reverse().toObservable();
54 | daysTillTest
55 | .doAction(
56 | function(d) { status.push(
57 | d + '=' + (d === 1 ? 'Study Like Mad' : _______));
58 | })
59 | .subscribe();
60 | equals(
61 | status.toString(),
62 | '4=Party,3=Party,2=Party,1=Study Like Mad');
63 | });
64 |
65 | test('NothingListensUntilYouSubscribe', function() {
66 | var sum = 0;
67 | var numbers = Range.create(1,10).toObservable();
68 | var observable = numbers
69 | .doAction(function(n) { sum += n; });
70 |
71 | equals(0, sum);
72 |
73 | observable._______();
74 |
75 | equals(55, sum);
76 | });
77 |
--------------------------------------------------------------------------------
/koans/lesson2-ComposableObservations.js:
--------------------------------------------------------------------------------
1 | module('Lesson 2 - Composable Observations');
2 |
3 | /*
4 | * Step 1: find the 1st method that fails
5 | * Step 2: Fill in the blank ____ to make it pass
6 | * Step 3: run it again
7 | * Note: Do not change anything other than the blank
8 | */
9 |
10 | test('ComposableAddition', function() {
11 | var received = 0;
12 | var numbers = [10, 100, _______];
13 | numbers
14 | .toObservable()
15 | .sum()
16 | .subscribe(function(x) { received = x; });
17 | equals(received, 1110);
18 | });
19 |
20 | test('ComposeableBeforeAndAfter', function() {
21 | var names = Range.create(1, 6),
22 | a = '',
23 | b = '';
24 | names
25 | .toObservable()
26 | .doAction(function(n) { a += n.toString(); })
27 | .where(function(n) { return n % 2 === 0; })
28 | .doAction(function(n) { b += n.toString(); })
29 | .subscribe();
30 | equals(a, _______);
31 | equals(b, '246');
32 | });
33 |
34 | test('WeWroteThis', function() {
35 | var received = [];
36 | var names = ['Bart', 'Wes', 'Erik', 'Matthew', 'Brian'];
37 | names
38 | .toObservable()
39 | .where(function(n) { return n.length <= _______; })
40 | .subscribe(function(x) { received.push(x); });
41 | equals(received.toString(), 'Bart,Wes,Erik');
42 | });
43 |
44 | test('ConvertingEvents', function() {
45 | var received = '';
46 | var names = ['wE', 'hOpE', 'yOU', 'aRe', 'eNJoyIng', 'tHiS' ];
47 | names
48 | .toObservable()
49 | .select(function(x) { return x._______; })
50 | .subscribe(function(x) { received += x + ' '; });
51 | equals(received, 'we hope you are enjoying this ');
52 | });
53 |
54 | test('CreatingAMoreRelevantEventStream', function() {
55 | var received = '',
56 | mouseXMovements = [100, 200, 150],
57 | windowTopX = 50,
58 | relativemouse = mouseXMovements
59 | .toObservable()
60 | .select(function(x) { return x - _______; });
61 |
62 | relativemouse.subscribe(function(x) { received += x + ', '; });
63 | equals(received, '50, 150, 100, ');
64 | });
65 |
66 | test('CheckingEverything', function() {
67 | var received = null;
68 | var numbers = [ 2, 4, 6, 8 ];
69 | numbers
70 | .toObservable()
71 | .all(function(x) { return x % 2 === 0; })
72 | .subscribe(function(x) { received = x; });
73 | equals(received, _______);
74 | });
75 |
76 | test('CompositionMeansTheSumIsGreaterThanTheParts', function() {
77 | var numbers = Rx.Observable.range(1, 10);
78 | numbers
79 | .where(function(x) { return x > _______; })
80 | .sum()
81 | .subscribe(function(x) { equals(19, x); });
82 | });
83 |
--------------------------------------------------------------------------------
/koans/lesson3-Time.js:
--------------------------------------------------------------------------------
1 | module('Lesson 3 - Time');
2 |
3 | /*
4 | * Step 1: find the 1st method that fails
5 | * Step 2: Fill in the blank ____ to make it pass
6 | * Step 3: run it again
7 | * Note: Do not change anything other than the blank
8 | */
9 |
10 | asyncTest('LaunchingAnActionInTheFuture', function() {
11 | var received = '';
12 | var delay = _______;
13 | Rx
14 | .Scheduler
15 | .immediate
16 | .schedule(function() { received = 'Finished'; }, delay);
17 |
18 | setTimeout(function() { equals(received, 'Finished'); start(); }, 500);
19 | });
20 |
21 | asyncTest('LaunchingAnEventInTheFuture', function() {
22 | var received = '',
23 | time = _______;
24 |
25 | Rx
26 | .Observable
27 | .returnValue('Godot', Rx.Scheduler.Immediate)
28 | .delay(time)
29 | .subscribe(function(x) { received = x; });
30 |
31 | setTimeout(function() { equals(received, 'Godot'); start(); }, 500);
32 | });
33 |
34 | asyncTest('AWatchedPot', function() {
35 | var received = '',
36 | delay = 500,
37 | timeout = _______,
38 | timeoutEvent =
39 | Rx .Observable
40 | .returnValue('Tepid');
41 | Rx
42 | .Observable
43 | .returnValue('Boiling')
44 | .delay(delay)
45 | .timeout(timeout, timeoutEvent)
46 | .subscribe(function(x) { received = x; });
47 |
48 | setTimeout(function() { equals(received, 'Boiling'); start(); }, 500);
49 | });
50 |
51 |
--------------------------------------------------------------------------------
/koans/lesson4-Events.js:
--------------------------------------------------------------------------------
1 | module('Lesson 4 - Events');
2 |
3 | test('listening to events', function() {
4 | var received = '';
5 | var subscription =
6 | $(document)
7 | .toObservable('foo')
8 | .subscribe(function(e) { received += e.payload; });
9 |
10 | $(document).trigger({ type: 'foo', payload : 'M'});
11 | $(document).trigger({ type: 'foo', payload : 'A'});
12 | $(document).trigger({ type: 'foo', payload : 'T'});
13 | subscription.dispose();
14 | $(document).trigger({ type: 'foo', payload : 'T'});
15 |
16 | equals(received, 'MAT'/*_______*/);
17 | });
18 |
19 | test('listening to the right events', function() {
20 | var received = '';
21 | var subscription =
22 | $(document)
23 | .toObservable('foo')
24 | .subscribe(function(e) { received += e.payload; });
25 |
26 | $(document).trigger({ type: 'foo', payload : 'M'});
27 | $(document).trigger({ type: 'bar', payload : 'A'});
28 | $(document).trigger({ type: 'foo', payload : 'T'});
29 | $(document).trigger({ type: 'foo', payload : 'T'});
30 | subscription.dispose();
31 |
32 | equals(received, 'MTT'/*_______*/);
33 | });
34 |
--------------------------------------------------------------------------------
/koans/lesson6-AdvancedStreams.js:
--------------------------------------------------------------------------------
1 | module('Lesson 6 - Advanced Streams');
2 |
3 | test('Merging', function() {
4 | var easy = [],
5 | you = [1,2,3].toObservable(),
6 | me = ['A','B','C'].toObservable();
7 | you
8 | .merge(me)
9 | .subscribe(function(a) { easy.push(a); });
10 |
11 | // equals(easy === '1 A 2 B 3 C ' || easy === '1 2 3 A B C ', _______);
12 |
13 | // Actually, this is not so easy! The result could be any arbitrary
14 | // riffle of the original two streams.
15 |
16 | riffles([1, 2, 3].toEnumerable(), ['A', 'B', 'C'].toEnumerable())
17 | .forEach(function(riffle) {
18 | console.log("riffle: ", riffle.toArray());
19 | });
20 |
21 | console.log("easy: ", easy);
22 |
23 | equals(
24 | riffles([1, 2, 3].toEnumerable(), ['A', 'B', 'C'].toEnumerable())
25 | .select(function (riffle) {return riffle.toArray();})
26 | ._______(easy, arrayComparer),
27 | true);
28 | });
29 |
30 | // A function that compares arrays for equality given an optional
31 | // elementComparer. Be aware that this is not sufficiently flexible
32 | // to work on arrays of arbitrary nesting.
33 | var arrayComparer = function (xs, ys, elementComparer) {
34 | if ( (! (xs instanceof Array)) || (! (ys instanceof Array)) )
35 | return false;
36 | var xl = xs.length;
37 | var yl = ys.length;
38 | if (xl != yl)
39 | return false;
40 | elementComparer || (elementComparer = function(x, y) { return x === y; });
41 | var i;
42 | for (i = 0; i < xl; i++)
43 | if (! elementComparer(xs[i], ys[i]))
44 | return false;
45 | return true;
46 | };
47 |
48 | // Produces an Enumerable of all splits of another Enumerable, as an
49 | // Enumerable of pairs of left and right after the splits. A more
50 | // sophisticated implementation would build the nested enumerators.
51 | var splits = function(xs) {
52 | var c = xs.count();
53 | var ys = [];
54 | for (var i = 0; i <= c; i++)
55 | ys.push( [xs.take(i), xs.skip(i)].toEnumerable() );
56 | return ys.toEnumerable();
57 | };
58 |
59 | // Produces an Enumerable of all riffles of two other Enumerables. A more
60 | // sophisticated implementation would build the nested enumerators.
61 | var riffles = function(left, right) {
62 | if (left.count() === 0)
63 | return Ix.Enumerable.returnValue(right);
64 | if (right.count() === 0)
65 | return Ix.Enumerable.returnValue(left);
66 | var ys = [];
67 |
68 | splits(right).skip(1).take(1).forEach( function(r)
69 | { splits(left).forEach( function(l)
70 | { riffles(l.elementAt(1), r.elementAt(1)).forEach( function(f)
71 | { ys.push(l.first().concat(r.first()).concat(f));
72 | }); }); });
73 |
74 | return ys.toEnumerable();
75 | };
76 |
77 | var floatingEquals = function (a, b, digits) {
78 | var exponent = Math.abs( digits || 12 );
79 | var multiplier = Math.pow(10, exponent);
80 | return Math.round( multiplier * a ) === Math.round( multiplier * b);
81 | };
82 |
83 | test('DescriptiveStatistics', function () {
84 | var e = [1, 2, 3].toEnumerable();
85 | equals(e.standardDeviation(), _______);
86 |
87 | equals(floatingEquals(
88 | [1, 2].toEnumerable().standardDeviation(),
89 | 1 / Math.sqrt(2)), true);
90 |
91 | // Should be sqrt ( (1^2 + 2^2 + 4^2 - 7^2 / 3) / 2 )
92 | // = sqrt( (1 + 4 + 16 - 49 / 3) / 2 )
93 | // = sqrt( (21 - 49 / 3) / 2 )
94 | // = sqrt( (63 - 49) / 6 )
95 | // = sqrt( 14 / 6 )
96 | // = sqrt( 7 / 3 )
97 |
98 | equals(floatingEquals(
99 | [1, 2, 4]
100 | .toEnumerable()
101 | .standardDeviation(),
102 | Math.sqrt(7 / 3)), true);
103 |
104 | [1, 2, 4]
105 | .toObservable()
106 | .standardDeviation()
107 | .subscribe(function (s) {
108 | console.log(s);
109 | equals(floatingEquals(s, Math.sqrt(7 / 3)), true); });
110 | });
111 |
112 |
113 | test('Splitting Up', function() {
114 | var oddsAndEvens = ['',''];
115 | numbers = Rx.Observable.range(1, 9),
116 | split = numbers
117 | .groupBy(function(n) { return n % _______; });
118 |
119 | split.subscribe(function (g) {
120 | return g.subscribe(
121 | function (i) {
122 | return console.log(i, g.key, g);
123 | });
124 | });
125 |
126 | split
127 | .subscribe(function(group) {
128 | group
129 | .subscribe(function(n) { oddsAndEvens[group.key] += n; });
130 | });
131 |
132 | var evens = oddsAndEvens[0],
133 | odds = oddsAndEvens[1];
134 |
135 | equals(evens, '2468');
136 | equal(odds, '13579');
137 | });
138 |
139 |
140 | test('Subscribe Imediately When Splitting', function() {
141 | var averages = [0.0,0.0],
142 | numbers = [22,22,99,22,101,22].toObservable(),
143 | split = numbers
144 | .groupBy(function(n) { return n % 2; });
145 | split
146 | .subscribe(function(g) {
147 | g
148 | .average()
149 | ._______(function(a) { averages[g.key] = a; });
150 | });
151 | equals(22, averages[0]);
152 | equals(100, averages[1]);
153 | });
154 |
155 | test('Multiple Subscriptions', function() {
156 | var numbers = new Rx.Subject(),
157 | sum = 0,
158 | average = 0;
159 |
160 | numbers
161 | .sum()
162 | .subscribe(function(n) { sum = n; });
163 | numbers.onNext(1);
164 | numbers.onNext(1);
165 | numbers.onNext(1);
166 | numbers.onNext(1);
167 | numbers.onNext(1);
168 |
169 | numbers
170 | .average()
171 | .subscribe(function(n) {
172 | average = n;
173 | // Bug, not called?
174 | });
175 | numbers.onNext(2);
176 | numbers.onNext(2);
177 | numbers.onNext(2);
178 | numbers.onNext(2);
179 | numbers.onNext(2);
180 |
181 | numbers.onCompleted();
182 |
183 | equals(sum, 15);
184 | equals(average, _______);
185 | });
186 |
187 | test('Tally', function()
188 | {
189 | var alice = [
190 | "Alice", "was", "beginning", "to", "get", "very", "tired", "of", "sitting", "by", "her", "sister", "on", "the",
191 | "bank", "and", "of", "having", "nothing", "to", "do", "once", "or", "twice", "she", "had", "peeped", "into", "the",
192 | "book", "her", "sister", "was", "reading", "but", "it", "had", "no", "pictures", "or", "conversations", "in",
193 | "it", "and", "what", "is", "the", "use", "of", "a", "book", "thought", "Alice", "without", "pictures", "or",
194 | "conversation",
195 | "So", "she", "was", "considering", "in", "her", "own", "mind", "as", "well", "as", "she", "could", "for", "the",
196 | "hot", "day", "made", "her", "feel", "very", "sleepy", "and", "stupid", "whether", "the", "pleasure",
197 | "of", "making", "a", "daisy", "chain", "would", "be", "worth", "the", "trouble", "of", "getting", "up", "and",
198 | "picking", "the", "daisies", "when", "suddenly", "a", "White", "Rabbit", "with", "pink", "eyes", "ran",
199 | "close", "by", "her",
200 |
201 | "There", "was", "nothing", "so", "VERY", "remarkable", "in", "that", "nor", "did", "Alice", "think", "it", "so",
202 | "VERY", "much", "out", "of", "the", "way", "to", "hear", "the", "Rabbit", "say", "to", "itself", "Oh", "dear",
203 | "Oh", "dear", "I", "shall", "be", "late", "when", "she", "thought", "it", "over", "afterwards", "it",
204 | "occurred", "to", "her", "that", "she", "ought", "to", "have", "wondered", "at", "this", "but", "at", "the", "time",
205 | "it", "all", "seemed", "quite", "natural", "but", "when", "the", "Rabbit", "actually", "TOOK", "A", "WATCH",
206 | "OUT", "OF", "ITS", "WAISTCOAT", "POCKET", "and", "looked", "at", "it", "and", "then", "hurried", "on",
207 | "Alice", "started", "to", "her", "feet", "for", "it", "flashed", "across", "her", "mind", "that", "she", "had",
208 | "never", "before", "seen", "a", "rabbit", "with", "either", "a", "waistcoat", "pocket", "or", "a", "watch",
209 | "to", "take", "out", "of", "it", "and", "burning", "with", "curiosity", "she", "ran", "across", "the", "field",
210 | "after", "it", "and", "fortunately", "was", "just", "in", "time", "to", "see", "it", "pop", "down", "a", "large",
211 | "rabbit", "hole", "under", "the", "hedge",
212 |
213 | "In", "another", "moment", "down", "went", "Alice", "after", "it", "never", "once", "considering", "how",
214 | "in", "the", "world", "she", "was", "to", "get", "out", "again",
215 |
216 | "The", "rabbit", "hole", "went", "straight", "on", "like", "a", "tunnel", "for", "some", "way", "and", "then",
217 | "dipped", "suddenly", "down", "so", "suddenly", "that", "Alice", "had", "not", "a", "moment", "to", "think",
218 | "about", "stopping", "herself", "before", "she", "found", "herself", "falling", "down", "a", "very", "deep",
219 | "well",
220 |
221 | "Either", "the", "well", "was", "very", "deep", "or", "she", "fell", "very", "slowly", "for", "she", "had",
222 | "plenty", "of", "time", "as", "she", "went", "down", "to", "look", "about", "her", "and", "to", "wonder", "what", "was",
223 | "going", "to", "happen", "next", "First", "she", "tried", "to", "look", "down", "and", "make", "out", "what",
224 | "she", "was", "coming", "to", "but", "it", "was", "too", "dark", "to", "see", "anything", "then", "she",
225 | "looked", "at", "the", "sides", "of", "the", "well", "and", "noticed", "that", "they", "were", "filled", "with",
226 | "cupboards", "and", "book", "shelves", "here", "and", "there", "she", "saw", "maps", "and", "pictures",
227 | "hung", "upon", "pegs", "She", "took", "down", "a", "jar", "from", "one", "of", "the", "shelves", "as",
228 | "she", "passed", "it", "was", "labelled", "ORANGE", "MARMALADE", "but", "to", "her", "great",
229 | "disappointment", "it", "was", "empty", "she", "did", "not", "like", "to", "drop", "the", "jar", "for", "fear",
230 | "of", "killing", "somebody", "so", "managed", "to", "put", "it", "into", "one", "of", "the", "cupboards", "as",
231 | "she", "fell", "past", "it"
232 | ];
233 |
234 | alice
235 | .toObservable()
236 | .select(function(s) {return s.toLowerCase();})
237 | .tally()
238 | .subscribe(function (s) {console.log(s);})
239 | ;
240 | });
241 |
242 |
243 |
--------------------------------------------------------------------------------
/lib/IxJs/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 | *.sln merge=union
7 | *.csproj merge=union
8 | *.vbproj merge=union
9 | *.fsproj merge=union
10 | *.dbproj merge=union
11 |
12 | # Standard to msysgit
13 | *.doc diff=astextplain
14 | *.DOC diff=astextplain
15 | *.docx diff=astextplain
16 | *.DOCX diff=astextplain
17 | *.dot diff=astextplain
18 | *.DOT diff=astextplain
19 | *.pdf diff=astextplain
20 | *.PDF diff=astextplain
21 | *.rtf diff=astextplain
22 | *.RTF diff=astextplain
23 |
--------------------------------------------------------------------------------
/lib/IxJs/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Eclipse
3 | #################
4 |
5 | *.pydevproject
6 | .project
7 | .metadata
8 | bin/
9 | tmp/
10 | *.tmp
11 | *.bak
12 | *.swp
13 | *~.nib
14 | local.properties
15 | .classpath
16 | .settings/
17 | .loadpath
18 |
19 | # External tool builders
20 | .externalToolBuilders/
21 |
22 | # Locally stored "Eclipse launch configurations"
23 | *.launch
24 |
25 | # CDT-specific
26 | .cproject
27 |
28 | # PDT-specific
29 | .buildpath
30 |
31 |
32 | #################
33 | ## Visual Studio
34 | #################
35 |
36 | ## Ignore Visual Studio temporary files, build results, and
37 | ## files generated by popular Visual Studio add-ons.
38 |
39 | # User-specific files
40 | *.suo
41 | *.user
42 | *.sln.docstates
43 |
44 | # Build results
45 | [Dd]ebug/
46 | [Rr]elease/
47 | *_i.c
48 | *_p.c
49 | *.ilk
50 | *.meta
51 | *.obj
52 | *.pch
53 | *.pdb
54 | *.pgc
55 | *.pgd
56 | *.rsp
57 | *.sbr
58 | *.tlb
59 | *.tli
60 | *.tlh
61 | *.tmp
62 | *.vspscc
63 | .builds
64 | *.dotCover
65 |
66 | ## TODO: If you have NuGet Package Restore enabled, uncomment this
67 | #packages/
68 |
69 | # Visual C++ cache files
70 | ipch/
71 | *.aps
72 | *.ncb
73 | *.opensdf
74 | *.sdf
75 |
76 | # Visual Studio profiler
77 | *.psess
78 | *.vsp
79 |
80 | # ReSharper is a .NET coding add-in
81 | _ReSharper*
82 |
83 | # Installshield output folder
84 | [Ee]xpress
85 |
86 | # DocProject is a documentation generator add-in
87 | DocProject/buildhelp/
88 | DocProject/Help/*.HxT
89 | DocProject/Help/*.HxC
90 | DocProject/Help/*.hhc
91 | DocProject/Help/*.hhk
92 | DocProject/Help/*.hhp
93 | DocProject/Help/Html2
94 | DocProject/Help/html
95 |
96 | # Click-Once directory
97 | publish
98 |
99 | # Others
100 | [Bb]in
101 | [Oo]bj
102 | sql
103 | TestResults
104 | *.Cache
105 | ClientBin
106 | stylecop.*
107 | ~$*
108 | *.dbmdl
109 | Generated_Code #added for RIA/Silverlight projects
110 |
111 | # Backup & report files from converting an old project file to a newer
112 | # Visual Studio version. Backup files are not needed, because we have git ;-)
113 | _UpgradeReport_Files/
114 | Backup*/
115 | UpgradeLog*.XML
116 |
117 |
118 |
119 | ############
120 | ## Windows
121 | ############
122 |
123 | # Windows image file caches
124 | Thumbs.db
125 |
126 | # Folder config file
127 | Desktop.ini
128 |
129 |
130 | #############
131 | ## Python
132 | #############
133 |
134 | *.py[co]
135 |
136 | # Packages
137 | *.egg
138 | *.egg-info
139 | dist
140 | build
141 | eggs
142 | parts
143 | bin
144 | var
145 | sdist
146 | develop-eggs
147 | .installed.cfg
148 |
149 | # Installer logs
150 | pip-log.txt
151 |
152 | # Unit test / coverage reports
153 | .coverage
154 | .tox
155 |
156 | #Translations
157 | *.mo
158 |
159 | #Mr Developer
160 | .mr.developer.cfg
161 |
162 | # Mac crap
163 | .DS_Store
164 |
--------------------------------------------------------------------------------
/lib/IxJs/tests/L2O.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Enumerable Extensions for JavaScript Tests
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/lib/IxJs/tests/aggregates.js:
--------------------------------------------------------------------------------
1 | (function (window) {
2 |
3 | function identity (x) { return x; }
4 |
5 | var root = window.L2O,
6 | Enumerable = root.Enumerable;
7 |
8 | QUnit.module('Aggregate Tests');
9 |
10 | test('IsEmpty_Empty', function () {
11 | ok(Enumerable.empty().isEmpty());
12 | });
13 |
14 | test('IsEmpty_Empty', function () {
15 | ok(!Enumerable.returnValue(1).isEmpty());
16 | });
17 |
18 | test('Min', function () {
19 | equal(3, Enumerable.fromArray([5,3,7]).minBy(identity, function (x, y) { return x % 3 - y % 3; }).first());
20 | });
21 |
22 | test('MinBy', function () {
23 | var res = Enumerable.fromArray([2, 5, 0, 7, 4, 3, 6, 2, 1]).minBy(function (x) { return x % 3; });
24 | ok(res.sequenceEqual(Enumerable.fromArray([ 0, 3, 6])));
25 | });
26 |
27 | test('MinBy_Empty', function () {
28 | raises(function () {
29 | Enumerable.empty().minBy(identity);
30 | });
31 | });
32 |
33 | test('Max', function () {
34 | equal(5, Enumerable.fromArray([2, 5, 3, 7]).maxBy(identity, function (x, y) { return x % 7 - y % 7; }).first());
35 | });
36 |
37 | test('MaxBy', function () {
38 | var res = Enumerable.fromArray([2, 5, 0, 7, 4, 3, 6, 2, 1]).maxBy(function (x) { return x % 3; });
39 | ok(res.sequenceEqual(Enumerable.fromArray([2, 5, 2 ])));
40 | });
41 |
42 | test('MinBy_Empty', function () {
43 | raises(function () {
44 | Enumerable.empty().maxBy(identity);
45 | });
46 | });
47 |
48 |
49 | }(this));
50 |
--------------------------------------------------------------------------------
/lib/IxJs/tests/creation.js:
--------------------------------------------------------------------------------
1 | (function (window) {
2 |
3 | function identity (x) { return x; }
4 |
5 | function noNext (e) {
6 | ok(!e.moveNext());
7 | }
8 |
9 | function hasNext (e, value) {
10 | ok(e.moveNext());
11 | equal(value, e.getCurrent());
12 | }
13 |
14 | var root = window.L2O,
15 | Enumerator = root.Enumerator,
16 | Enumerable = root.Enumerable;
17 |
18 | function MyEnumerator() {
19 | var values = [1, 2], length = values.length, index = 0, current;
20 | return Enumerator.create(function () {
21 | if (index === length) {
22 | return false;
23 | }
24 | current = values[index++];
25 | return true;
26 | }, function () {
27 | return current;
28 | });
29 | }
30 |
31 | QUnit.module('Creation Tests');
32 |
33 | test('Create1', function () {
34 | var hot = false,
35 | res = Enumerable.create(function () {
36 | hot = true;
37 | return new MyEnumerator();
38 | });
39 |
40 | ok(!hot);
41 |
42 | var e = res.getEnumerator();
43 | ok(hot);
44 |
45 | hasNext(e, 1);
46 | hasNext(e, 2);
47 | noNext(e);
48 |
49 | hot = false;
50 | var f = res.getEnumerator();
51 | ok(hot);
52 | });
53 |
54 | test('Return', function () {
55 | equal(42, Enumerable.returnValue(42).single());
56 | });
57 |
58 | test('Throw', function () {
59 | var ex = new Error('Woops');
60 | var xs = Enumerable.throwException(ex);
61 |
62 | var e = xs.getEnumerator();
63 | raises(function () { e.moveNext(); });
64 | });
65 |
66 | test('Defer1', function () {
67 | var i = 0;
68 | var n = 5;
69 | var xs = Enumerable.defer(function () {
70 | i++;
71 | return Enumerable.range(0, n);
72 | });
73 |
74 | equal(0, i);
75 |
76 | ok(xs.sequenceEqual(Enumerable.range(0, n)));
77 | equal(1, i);
78 |
79 | n = 3;
80 | ok(xs.sequenceEqual(Enumerable.range(0, n)));
81 | equal(2, i);
82 | });
83 |
84 | test('Defer2', function () {
85 | var xs = Enumerable.defer(function () {
86 | throw new Error('woops');
87 | });
88 |
89 | raises(function () { xs.getEnumerator().moveNext(); });
90 | });
91 |
92 | test('Generate', function () {
93 | var res = Enumerable.generate(
94 | 0,
95 | function (x) { return x < 5; },
96 | function (x) { return x + 1; },
97 | function (x) { return x * x; });
98 | ok(res.sequenceEqual(Enumerable.fromArray([0, 1, 4, 9, 16])));
99 | });
100 |
101 | function MyDisposable () {
102 | this.done = false;
103 | }
104 | MyDisposable.prototype.dispose = function () {
105 | this.done = true;
106 | };
107 |
108 | test('Using1', function () {
109 | var d;
110 |
111 | var xs = Enumerable.using(function () {
112 | return d = new MyDisposable();
113 | }, function (d_) {
114 | return Enumerable.returnValue(1);
115 | });
116 | ok(!d);
117 |
118 | var d1;
119 | xs.forEach(function () { d1 = d; ok(d1); ok(!d1.done); });
120 | ok(d1.done);
121 |
122 | var d2;
123 | xs.forEach(function () { d2 = d; ok(d2); ok(!d2.done); });
124 | ok(d2.done);
125 |
126 | notEqual(d1, d2);
127 | });
128 |
129 | test('Using2', function () {
130 | var d;
131 |
132 | var xs = Enumerable.using(function () {
133 | return d = new MyDisposable();
134 | }, function (d_) {
135 | return Enumerable.throwException(new Error('Woops'));
136 | });
137 | ok(!d);
138 |
139 | raises(function () { xs.forEach(function () { }); });
140 | ok(d.done);
141 | });
142 |
143 | test('Using3', function () {
144 | var d;
145 |
146 | var xs = Enumerable.using(function () {
147 | return d = new MyDisposable();
148 | }, function (d_) {
149 | throw new Error('Woops');
150 | });
151 | ok(!d);
152 |
153 | raises(function () { xs.forEach(function () { }); });
154 | ok(d.done);
155 | });
156 |
157 | test('RepeatElementInfinite', function () {
158 | var xs = Enumerable.repeat(42).take(1000);
159 | ok(xs.all(function (x) { return x === 42; }));
160 | ok(xs.count() == 1000);
161 | });
162 |
163 | test('RepeatSequence1', function () {
164 | var i = 0;
165 | var xs = Enumerable.fromArray([1,2]).doAction(function () { i++; }).repeat();
166 |
167 | var res = xs.take(10).toArray();
168 | equal(10, res.length);
169 | ok(Enumerable.fromArray(res).bufferWithCount(2).select(function (b) { return b.sum(); }).all(function (x) { return x === 3; }));
170 | equal(10, i);
171 | });
172 |
173 | test('RepeatSequence2', function () {
174 | var i = 0;
175 | var xs = Enumerable.fromArray([1,2]).doAction(function () { i++; }).repeat(5);
176 |
177 | var res = xs.toArray();
178 | equal(10, res.length);
179 | ok(Enumerable.fromArray(res).bufferWithCount(2).select(function (b) { return b.sum(); }).all(function (x) { return x === 3; }));
180 | equal(10, i);
181 | });
182 |
183 | }(this));
--------------------------------------------------------------------------------
/lib/IxJs/tests/vendor/qunit-1.9.0.css:
--------------------------------------------------------------------------------
1 | /**
2 | * QUnit v1.9.0 - A JavaScript Unit Testing Framework
3 | *
4 | * http://docs.jquery.com/QUnit
5 | *
6 | * Copyright (c) 2012 John Resig, Jörn Zaefferer
7 | * Dual licensed under the MIT (MIT-LICENSE.txt)
8 | * or GPL (GPL-LICENSE.txt) licenses.
9 | */
10 |
11 | /** Font Family and Sizes */
12 |
13 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
14 | font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
15 | }
16 |
17 | #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
18 | #qunit-tests { font-size: smaller; }
19 |
20 |
21 | /** Resets */
22 |
23 | #qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {
24 | margin: 0;
25 | padding: 0;
26 | }
27 |
28 |
29 | /** Header */
30 |
31 | #qunit-header {
32 | padding: 0.5em 0 0.5em 1em;
33 |
34 | color: #8699a4;
35 | background-color: #0d3349;
36 |
37 | font-size: 1.5em;
38 | line-height: 1em;
39 | font-weight: normal;
40 |
41 | border-radius: 5px 5px 0 0;
42 | -moz-border-radius: 5px 5px 0 0;
43 | -webkit-border-top-right-radius: 5px;
44 | -webkit-border-top-left-radius: 5px;
45 | }
46 |
47 | #qunit-header a {
48 | text-decoration: none;
49 | color: #c2ccd1;
50 | }
51 |
52 | #qunit-header a:hover,
53 | #qunit-header a:focus {
54 | color: #fff;
55 | }
56 |
57 | #qunit-testrunner-toolbar label {
58 | display: inline-block;
59 | padding: 0 .5em 0 .1em;
60 | }
61 |
62 | #qunit-banner {
63 | height: 5px;
64 | }
65 |
66 | #qunit-testrunner-toolbar {
67 | padding: 0.5em 0 0.5em 2em;
68 | color: #5E740B;
69 | background-color: #eee;
70 | }
71 |
72 | #qunit-userAgent {
73 | padding: 0.5em 0 0.5em 2.5em;
74 | background-color: #2b81af;
75 | color: #fff;
76 | text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
77 | }
78 |
79 |
80 | /** Tests: Pass/Fail */
81 |
82 | #qunit-tests {
83 | list-style-position: inside;
84 | }
85 |
86 | #qunit-tests li {
87 | padding: 0.4em 0.5em 0.4em 2.5em;
88 | border-bottom: 1px solid #fff;
89 | list-style-position: inside;
90 | }
91 |
92 | #qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running {
93 | display: none;
94 | }
95 |
96 | #qunit-tests li strong {
97 | cursor: pointer;
98 | }
99 |
100 | #qunit-tests li a {
101 | padding: 0.5em;
102 | color: #c2ccd1;
103 | text-decoration: none;
104 | }
105 | #qunit-tests li a:hover,
106 | #qunit-tests li a:focus {
107 | color: #000;
108 | }
109 |
110 | #qunit-tests ol {
111 | margin-top: 0.5em;
112 | padding: 0.5em;
113 |
114 | background-color: #fff;
115 |
116 | border-radius: 5px;
117 | -moz-border-radius: 5px;
118 | -webkit-border-radius: 5px;
119 | }
120 |
121 | #qunit-tests table {
122 | border-collapse: collapse;
123 | margin-top: .2em;
124 | }
125 |
126 | #qunit-tests th {
127 | text-align: right;
128 | vertical-align: top;
129 | padding: 0 .5em 0 0;
130 | }
131 |
132 | #qunit-tests td {
133 | vertical-align: top;
134 | }
135 |
136 | #qunit-tests pre {
137 | margin: 0;
138 | white-space: pre-wrap;
139 | word-wrap: break-word;
140 | }
141 |
142 | #qunit-tests del {
143 | background-color: #e0f2be;
144 | color: #374e0c;
145 | text-decoration: none;
146 | }
147 |
148 | #qunit-tests ins {
149 | background-color: #ffcaca;
150 | color: #500;
151 | text-decoration: none;
152 | }
153 |
154 | /*** Test Counts */
155 |
156 | #qunit-tests b.counts { color: black; }
157 | #qunit-tests b.passed { color: #5E740B; }
158 | #qunit-tests b.failed { color: #710909; }
159 |
160 | #qunit-tests li li {
161 | padding: 5px;
162 | background-color: #fff;
163 | border-bottom: none;
164 | list-style-position: inside;
165 | }
166 |
167 | /*** Passing Styles */
168 |
169 | #qunit-tests li li.pass {
170 | color: #3c510c;
171 | background-color: #fff;
172 | border-left: 10px solid #C6E746;
173 | }
174 |
175 | #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
176 | #qunit-tests .pass .test-name { color: #366097; }
177 |
178 | #qunit-tests .pass .test-actual,
179 | #qunit-tests .pass .test-expected { color: #999999; }
180 |
181 | #qunit-banner.qunit-pass { background-color: #C6E746; }
182 |
183 | /*** Failing Styles */
184 |
185 | #qunit-tests li li.fail {
186 | color: #710909;
187 | background-color: #fff;
188 | border-left: 10px solid #EE5757;
189 | white-space: pre;
190 | }
191 |
192 | #qunit-tests > li:last-child {
193 | border-radius: 0 0 5px 5px;
194 | -moz-border-radius: 0 0 5px 5px;
195 | -webkit-border-bottom-right-radius: 5px;
196 | -webkit-border-bottom-left-radius: 5px;
197 | }
198 |
199 | #qunit-tests .fail { color: #000000; background-color: #EE5757; }
200 | #qunit-tests .fail .test-name,
201 | #qunit-tests .fail .module-name { color: #000000; }
202 |
203 | #qunit-tests .fail .test-actual { color: #EE5757; }
204 | #qunit-tests .fail .test-expected { color: green; }
205 |
206 | #qunit-banner.qunit-fail { background-color: #EE5757; }
207 |
208 |
209 | /** Result */
210 |
211 | #qunit-testresult {
212 | padding: 0.5em 0.5em 0.5em 2.5em;
213 |
214 | color: #2b81af;
215 | background-color: #D2E0E6;
216 |
217 | border-bottom: 1px solid white;
218 | }
219 | #qunit-testresult .module-name {
220 | font-weight: bold;
221 | }
222 |
223 | /** Fixture */
224 |
225 | #qunit-fixture {
226 | position: absolute;
227 | top: -10000px;
228 | left: -10000px;
229 | width: 1000px;
230 | height: 1000px;
231 | }
232 |
--------------------------------------------------------------------------------
/lib/IxJs/tests/vendor/qunit-clib.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * QUnit CLI Boilerplate v1.0.0
3 | * Copyright 2011-2012 John-David Dalton
4 | * Based on a gist by Jörn Zaefferer
5 | * Available under MIT license
6 | */
7 | ;(function(global) {
8 | 'use strict';
9 |
10 | /** Add `console.log()` support for Narwhal, Rhino, and RingoJS */
11 | global.console || (global.console = { 'log': global.print });
12 |
13 | /** Reduce global.QUnit.QUnit -> global.QUnit */
14 | global.QUnit && (QUnit = QUnit.QUnit || QUnit);
15 |
16 | /*--------------------------------------------------------------------------*/
17 |
18 | /** Used as a horizontal rule in console output */
19 | var hr = '----------------------------------------';
20 |
21 | /** Shortcut used to convert array-like objects to arrays */
22 | var slice = [].slice;
23 |
24 | /** Used to resolve a value's internal [[Class]] */
25 | var toString = {}.toString;
26 |
27 | /** Used by timer methods */
28 | var doneCalled,
29 | timer,
30 | counter = 0,
31 | ids = {};
32 |
33 | /*--------------------------------------------------------------------------*/
34 |
35 | /**
36 | * An iteration utility for arrays.
37 | *
38 | * @private
39 | * @param {Array} array The array to iterate over.
40 | * @param {Function} callback The function called per iteration.
41 | */
42 | function each(array, callback) {
43 | var index = -1,
44 | length = array.length;
45 |
46 | while (++index < length) {
47 | callback(array[index], index, array);
48 | }
49 | }
50 |
51 | /**
52 | * Checks if the specified `value` is a function.
53 | *
54 | * @private
55 | * @param {Mixed} value The value to check.
56 | * @returns {Boolean} Returns `true` if `value` is a function, else `false`.
57 | */
58 | function isFunction(value) {
59 | return toString.call(value) == '[object Function]';
60 | }
61 |
62 | /*--------------------------------------------------------------------------*/
63 |
64 | /**
65 | * Timeout fallbacks based on the work of Andrea Giammarchi and Weston C.
66 | * https://github.com/WebReflection/wru/blob/master/src/rhinoTimers.js
67 | * http://stackoverflow.com/questions/2261705/how-to-run-a-javascript-function-asynchronously-without-using-settimeout
68 | */
69 |
70 | /**
71 | * Clears the delay set by `setInterval` or `setTimeout`.
72 | *
73 | * @memberOf global
74 | * @param {Number} id The ID of the timeout to be cleared.
75 | */
76 | function clearTimer(id) {
77 | if (ids[id]) {
78 | ids[id].cancel();
79 | timer.purge();
80 | delete ids[id];
81 | }
82 | }
83 |
84 | /**
85 | * Schedules timer-based callbacks.
86 | *
87 | * @private
88 | * @param {Function} fn The function to call.
89 | * @oaram {Number} delay The number of milliseconds to delay the `fn` call.
90 | * @param [arg1, arg2, ...] Arguments to invoke `fn` with.
91 | * @param {Boolean} repeated A flag to specify whether `fn` is called repeatedly.
92 | * @returns {Number} The the ID of the timeout.
93 | */
94 | function schedule(fn, delay, args, repeated) {
95 | // Rhino 1.7RC4 will error assigning `task` below
96 | // https://bugzilla.mozilla.org/show_bug.cgi?id=775566
97 | var task = ids[++counter] = new JavaAdapter(java.util.TimerTask, {
98 | 'run': function() {
99 | fn.apply(global, args);
100 | }
101 | });
102 | // support non-functions
103 | if (!isFunction(fn)) {
104 | fn = (function(code) {
105 | code = String(code);
106 | return function() { eval(code); };
107 | }(fn));
108 | }
109 | // used by setInterval
110 | if (repeated) {
111 | timer.schedule(task, delay, delay);
112 | }
113 | // used by setTimeout
114 | else {
115 | timer.schedule(task, delay);
116 | }
117 | return counter;
118 | }
119 |
120 | /**
121 | * Executes a code snippet or function repeatedly, with a delay between each call.
122 | *
123 | * @memberOf global
124 | * @param {Function|String} fn The function to call or string to evaluate.
125 | * @oaram {Number} delay The number of milliseconds to delay each `fn` call.
126 | * @param [arg1, arg2, ...] Arguments to invoke `fn` with.
127 | * @returns {Number} The the ID of the timeout.
128 | */
129 | function setInterval(fn, delay) {
130 | return schedule(fn, delay, slice.call(arguments, 2), true);
131 | }
132 |
133 | /**
134 | * Executes a code snippet or a function after specified delay.
135 | *
136 | * @memberOf global
137 | * @param {Function|String} fn The function to call or string to evaluate.
138 | * @oaram {Number} delay The number of milliseconds to delay the `fn` call.
139 | * @param [arg1, arg2, ...] Arguments to invoke `fn` with.
140 | * @returns {Number} The the ID of the timeout.
141 | */
142 | function setTimeout(fn, delay) {
143 | return schedule(fn, delay, slice.call(arguments, 2));
144 | }
145 |
146 | /*--------------------------------------------------------------------------*/
147 |
148 | /**
149 | * A logging callback triggered when all testing is completed.
150 | *
151 | * @memberOf QUnit
152 | * @param {Object} details An object with properties `failed`, `passed`,
153 | * `runtime`, and `total`.
154 | */
155 | function done(details) {
156 | // stop `asyncTest()` from erroneously calling `done()` twice in
157 | // environments w/o timeouts
158 | if (doneCalled) {
159 | return;
160 | }
161 | doneCalled = true;
162 | console.log(hr);
163 | console.log(' PASS: ' + details.passed + ' FAIL: ' + details.failed + ' TOTAL: ' + details.total);
164 | console.log(' Finished in ' + details.runtime + ' milliseconds.');
165 | console.log(hr);
166 |
167 | // exit out of Rhino
168 | try {
169 | quit();
170 | } catch(e) { }
171 |
172 | // exit out of Node.js
173 | try {
174 | process.exit();
175 | } catch(e) { }
176 | }
177 |
178 | /**
179 | * A logging callback triggered after every assertion.
180 | *
181 | * @memberOf QUnit
182 | * @param {Object} details An object with properties `actual`, `expected`,
183 | * `message`, and `result`.
184 | */
185 | function log(details) {
186 | var expected = details.expected,
187 | result = details.result,
188 | type = typeof expected != 'undefined' ? 'EQ' : 'OK';
189 |
190 | var assertion = [
191 | result ? 'PASS' : 'FAIL',
192 | type,
193 | details.message || 'ok'
194 | ];
195 |
196 | if (!result && type == 'EQ') {
197 | assertion.push('Expected: ' + expected + ', Actual: ' + details.actual);
198 | }
199 | QUnit.config.testStats.assertions.push(assertion.join(' | '));
200 | }
201 |
202 | /**
203 | * A logging callback triggered at the start of every test module.
204 | *
205 | * @memberOf QUnit
206 | * @param {Object} details An object with property `name`.
207 | */
208 | function moduleStart(details) {
209 | console.log(hr);
210 | console.log(details.name);
211 | console.log(hr);
212 | }
213 |
214 | /**
215 | * Converts an object into a string representation.
216 | *
217 | * @memberOf QUnit
218 | * @type Function
219 | * @param {Object} object The object to stringify.
220 | * @returns {String} The result string.
221 | */
222 | var parseObject = (function() {
223 | var func = QUnit.jsDump.parsers.object;
224 | return function(object) {
225 | // fork to support Rhino's error objects
226 | if (typeof object.rhinoException == 'object') {
227 | return object.name +
228 | ' { message: "' + object.message +
229 | '", fileName: "' + object.fileName +
230 | '", lineNumber: ' + object.lineNumber + ' }';
231 | }
232 | return func(object);
233 | };
234 | }());
235 |
236 | /**
237 | * A logging callback triggered after a test is completed.
238 | *
239 | * @memberOf QUnit
240 | * @param {Object} details An object with properties `failed`, `name`,
241 | * `passed`, and `total`.
242 | */
243 | function testDone(details) {
244 | var assertions = QUnit.config.testStats.assertions,
245 | testName = details.name;
246 |
247 | if (details.failed > 0) {
248 | console.log(' FAIL - '+ testName);
249 | each(assertions, function(value) {
250 | console.log(' ' + value);
251 | });
252 | }
253 | else {
254 | console.log(' PASS - ' + testName);
255 | }
256 | assertions.length = 0;
257 | }
258 |
259 | /*--------------------------------------------------------------------------*/
260 |
261 | /**
262 | * An object used to hold information about the current running test.
263 | *
264 | * @memberOf QUnit.config
265 | * @type Object
266 | */
267 | QUnit.config.testStats = {
268 |
269 | /**
270 | * An array of test summaries (pipe separated).
271 | *
272 | * @memberOf QUnit.config.testStats
273 | * @type Array
274 | */
275 | 'assertions': []
276 | };
277 |
278 | // add shortcuts to the global
279 | // exclude `module` because some environments have it as a built-in object
280 | each(['asyncTest', 'deepEqual', 'equal', 'equals', 'expect', 'notDeepEqual',
281 | 'notEqual', 'notStrictEqual', 'ok', 'raises', 'same', 'start', 'stop',
282 | 'strictEqual', 'test', 'throws'], function(funcName) {
283 | var func = QUnit[funcName];
284 | if (func) {
285 | global[funcName] = func;
286 | }
287 | });
288 |
289 | // expose timer methods to global
290 | try {
291 | timer = new java.util.Timer;
292 | if (!isFunction(global.clearInterval)) {
293 | global.clearInterval = clearTimer;
294 | }
295 | if (!isFunction(global.clearTimeout)) {
296 | global.clearTimeout = clearTimer;
297 | }
298 | if (!isFunction(global.setInterval)) {
299 | global.setInterval = setInterval;
300 | }
301 | if (!isFunction(global.setTimeout)) {
302 | global.setTimeout = setTimeout;
303 | }
304 | } catch(e) { }
305 |
306 | // add callbacks
307 | QUnit.done(done);
308 | QUnit.log(log);
309 | QUnit.moduleStart(moduleStart);
310 | QUnit.testDone(testDone);
311 |
312 | // add wrapped function
313 | QUnit.jsDump.parsers.object = parseObject;
314 |
315 | // must call `QUnit.start()` in the test file if using QUnit < 1.3.0 with
316 | // Node.js or any version of QUnit with Narwhal, Rhino, or RingoJS
317 | QUnit.init();
318 |
319 | }(typeof global == 'object' && global || this));
320 |
--------------------------------------------------------------------------------
/lib/PermutationsAndShuffles.cs.linq:
--------------------------------------------------------------------------------
1 | void Main()
2 | {
3 | (new int [] {}).Permutations().Dump("Permutations of empty collection");
4 | (new [] {1}).Permutations().Dump("Permutations of singleton collection");
5 | (new [] {1,2}).Permutations().Dump("Permutations of doubleton collection");
6 | (new [] {1,2,3}).Permutations().Dump("Permutations of tripleton
7 | collection");
8 |
9 | Pluck(2)(new [] {1,2,3}).Dump("Pluck second element from a
10 | collection");
11 | CoPluck(2)(new [] {1,2,3}).Dump("A new collection with all
12 | but the second element");
13 |
14 | (new [] {new [] {1,2,3}, new [] {4,5,6}})
15 | .Select(Pluck(2))
16 | .Dump("Map Pluck(2)");
17 |
18 | (new [] {1,2,3}).PluckPair(2).Dump("The plucked element and its residual");
19 | (new [] {1,2,3}).PluckPairs().Dump("All pluck pairs of a collection");
20 |
21 | (new int [] {}).Permutations2().Dump("Permutations of empty collection");
22 | (new [] {1}).Permutations2().Dump("Permutations of singleton collection");
23 | (new [] {1,2}).Permutations2().Dump("Permutations of doubleton collection");
24 | (new [] {1,2,3}).Permutations2().Dump("Permutations of tripleton
25 | collection");
26 |
27 | (new int [] {}).Riffles(new int [] {}).Dump("All riffles of two
28 | empty collections");
29 | (new [] {1}).Riffles(new int [] {}).Dump("All riffles of a
30 | singleton and an empty");
31 | (new int [] {}).Riffles(new [] {4}).Dump("All riffles of an empty
32 | and a singleton");
33 | (new [] {1}).Riffles(new [] {4}).Dump("All riffles of two singletons");
34 | (new [] {1,2}).Riffles(new [] {4}).Dump("All riffles of a
35 | doubleton and a singletons");
36 | (new [] {1}).Riffles(new [] {4,5}).Dump("All riffles of a
37 | singleton and a doubleton");
38 | (new [] {1,2}).Riffles(new [] {4,5}).Dump("All riffles of two doubletons");
39 | (new [] {1,2,3}).Riffles(new [] {4,5}).Dump("All riffles of a
40 | tripleton and a doubleton");
41 | (new [] {1,2}).Riffles(new [] {4,5,6}).Dump("All riffles of a
42 | doubleton and a tripleton");
43 | (new [] {1,2,3}).Riffles(new [] {4,5,6}).Dump("All riffles of two
44 | tripletons");
45 | }
46 |
47 | // Pluck returns a function so it can be mapped over other collections.
48 | public static Func, T> Pluck(int n)
49 | { return xs =>
50 | { if (n <= 0 || n > xs.Count())
51 | throw new ArgumentOutOfRangeException("n",
52 | String.Format("argument must have value between 1 and
53 | {0} inclusive",
54 | xs.Count()));
55 | return xs.ElementAt(n - 1);
56 | };
57 | }
58 |
59 | // CoPluck returns a function so it can be mapped over other collections
60 | public static Func, IEnumerable> CoPluck(int n)
61 | { return xs =>
62 | { var c = xs.Count();
63 | if (n <= 0 || n > c)
64 | throw new ArgumentOutOfRangeException("n",
65 | String.Format("argument must have value between 1 and
66 | {0} inclusive", c));
67 | var ys = new List();
68 | var i = 1;
69 | foreach (var x in xs)
70 | { if (i != n)
71 | ys.Add(x);
72 | i++;
73 | }
74 | return ys;
75 | };
76 | }
77 | public static class Extensions
78 | {
79 | public static IEnumerable> Riffles(this
80 | IEnumerable left, IEnumerable right)
81 | { if (left.Count() == 0)
82 | { yield return right;
83 | yield break;
84 | }
85 | if (right.Count() == 0)
86 | { yield return left;
87 | yield break;
88 | }
89 | foreach (var r in right.Splits().Skip(1).Take(1))
90 | { foreach (var l in left.Splits())
91 | { foreach (var f in Riffles(l.Second(), r.Second()))
92 | { yield return l.First().Concat(r.First()).Concat(f);
93 | }
94 | }
95 | }
96 | }
97 | public static T Second (this IEnumerable these)
98 | { return these.Skip(1).First();
99 | }
100 | public static IEnumerable>>
101 | Splits(this IEnumerable these)
102 | { var c = these.Count();
103 | for (var i = 0; i <= c; i++)
104 | yield return new IEnumerable [2] {these.Take(i), these.Skip(i)};
105 | }
106 |
107 | public static IEnumerable Append(this IEnumerable these, T that)
108 | { foreach (var t in these)
109 | yield return t;
110 | yield return that;
111 | }
112 | public static IEnumerable Prepend(this IEnumerable these, T that)
113 | { yield return that;
114 | foreach (var t in these)
115 | yield return t;
116 | }
117 | public static IEnumerable>>
118 | PluckPairs(this IEnumerable xs)
119 | { var c = xs.Count();
120 | var result = new List>>();
121 | for (var n = 1; n <= c; n++)
122 | { var ys = new List();
123 | var y = default(T);
124 | var i = 1;
125 | foreach (var x in xs)
126 | { if (i != n)
127 | ys.Add(x);
128 | else
129 | y = x;
130 | i++;
131 | }
132 | result.Add(Tuple.Create(y, (IEnumerable)ys));
133 | }
134 | return result;
135 | }
136 | public static Tuple> PluckPair(this
137 | IEnumerable xs, int n)
138 | { var c = xs.Count();
139 | if (n <= 0 || n > c)
140 | throw new ArgumentOutOfRangeException("n",
141 | String.Format("argument must have value between 1 and
142 | {0} inclusive", c));
143 | var ys = new List();
144 | var y = default(T);
145 | var i = 1;
146 | foreach (var x in xs)
147 | { if (i != n)
148 | ys.Add(x);
149 | else
150 | y = x;
151 | i++;
152 | }
153 | return Tuple.Create(y, (IEnumerable)ys);
154 | }
155 |
156 | // Slow but understandable "reference implementation" of Permutations
157 | public static IEnumerable> Permutations2(this
158 | IEnumerable these)
159 | { Debug.Assert(these != null);
160 | // Inherently combinatorial-time algorithm!
161 | var len = these.Count();
162 | if (len == 1)
163 | { yield return these;
164 | yield break;
165 | }
166 | foreach (var pluckPair in these.PluckPairs())
167 | { foreach (var permutation in pluckPair.Item2.Permutations2())
168 | { yield return permutation.Prepend(pluckPair.Item1);
169 | }
170 | }
171 | }
172 | // Faster but more difficult index-based implementation of Permutations
173 | public static IEnumerable> Permutations(this
174 | IEnumerable these)
175 | { Debug.Assert(these != null);
176 | // Inherently combinatorial-time algorithm!
177 | var len = these.Count();
178 | if (len == 1)
179 | { yield return these;
180 | yield break;
181 | }
182 | var source = these.ToArray();
183 | var result = new T [len];
184 | for (var i = 0; i < len; i++)
185 | { result[0] = source[i];
186 | var rs = new T [len - 1];
187 | for (var j = 0; j < len - 1; j++)
188 | { if (j < i)
189 | { rs[j] = source[j];
190 | }
191 | else if (j >= i)
192 | { rs[j] = source[j + 1];
193 | }
194 | }
195 | var perms = rs.Permutations();
196 | foreach (var perm in perms)
197 | { var ps = perm.ToArray();
198 | for(var j = 0; j < len - 1; j++)
199 | result[j + 1] = ps[j];
200 | yield return result;
201 | }
202 | }
203 | }
204 | }
--------------------------------------------------------------------------------
/lib/PermutationsAndShuffles.js:
--------------------------------------------------------------------------------
1 | /* void Main()
2 | {
3 | (new int [] {}).Permutations().Dump("Permutations of empty collection");
4 | (new [] {1}).Permutations().Dump("Permutations of singleton collection");
5 | (new [] {1,2}).Permutations().Dump("Permutations of doubleton collection");
6 | (new [] {1,2,3}).Permutations().Dump("Permutations of tripleton
7 | collection");
8 |
9 | Pluck(2)(new [] {1,2,3}).Dump("Pluck second element from a
10 | collection");
11 | CoPluck(2)(new [] {1,2,3}).Dump("A new collection with all
12 | but the second element");
13 |
14 | (new [] {new [] {1,2,3}, new [] {4,5,6}})
15 | .Select(Pluck(2))
16 | .Dump("Map Pluck(2)");
17 |
18 | (new [] {1,2,3}).PluckPair(2).Dump("The plucked element and its residual");
19 | (new [] {1,2,3}).PluckPairs().Dump("All pluck pairs of a collection");
20 |
21 | (new int [] {}).Permutations2().Dump("Permutations of empty collection");
22 | (new [] {1}).Permutations2().Dump("Permutations of singleton collection");
23 | (new [] {1,2}).Permutations2().Dump("Permutations of doubleton collection");
24 | (new [] {1,2,3}).Permutations2().Dump("Permutations of tripleton
25 | collection");
26 |
27 | (new int [] {}).Riffles(new int [] {}).Dump("All riffles of two
28 | empty collections");
29 | (new [] {1}).Riffles(new int [] {}).Dump("All riffles of a
30 | singleton and an empty");
31 | (new int [] {}).Riffles(new [] {4}).Dump("All riffles of an empty
32 | and a singleton");
33 | (new [] {1}).Riffles(new [] {4}).Dump("All riffles of two singletons");
34 | (new [] {1,2}).Riffles(new [] {4}).Dump("All riffles of a
35 | doubleton and a singletons");
36 | (new [] {1}).Riffles(new [] {4,5}).Dump("All riffles of a
37 | singleton and a doubleton");
38 | (new [] {1,2}).Riffles(new [] {4,5}).Dump("All riffles of two doubletons");
39 | (new [] {1,2,3}).Riffles(new [] {4,5}).Dump("All riffles of a
40 | tripleton and a doubleton");
41 | (new [] {1,2}).Riffles(new [] {4,5,6}).Dump("All riffles of a
42 | doubleton and a tripleton");
43 | (new [] {1,2,3}).Riffles(new [] {4,5,6}).Dump("All riffles of two
44 | tripletons");
45 | }
46 |
47 | // Pluck returns a function so it can be mapped over other collections.
48 | public static Func, T> Pluck(int n)
49 | { return xs =>
50 | { if (n <= 0 || n > xs.Count())
51 | throw new ArgumentOutOfRangeException("n",
52 | String.Format("argument must have value between 1 and
53 | {0} inclusive",
54 | xs.Count()));
55 | return xs.ElementAt(n - 1);
56 | };
57 | }
58 |
59 | // CoPluck returns a function so it can be mapped over other collections
60 | public static Func, IEnumerable> CoPluck(int n)
61 | { return xs =>
62 | { var c = xs.Count();
63 | if (n <= 0 || n > c)
64 | throw new ArgumentOutOfRangeException("n",
65 | String.Format("argument must have value between 1 and
66 | {0} inclusive", c));
67 | var ys = new List();
68 | var i = 1;
69 | foreach (var x in xs)
70 | { if (i != n)
71 | ys.Add(x);
72 | i++;
73 | }
74 | return ys;
75 | };
76 | }
77 | public static class Extensions
78 | {
79 | public static IEnumerable> Riffles(this
80 | IEnumerable left, IEnumerable right)
81 | { if (left.Count() == 0)
82 | { yield return right;
83 | yield break;
84 | }
85 | if (right.Count() == 0)
86 | { yield return left;
87 | yield break;
88 | }
89 | foreach (var r in right.Splits().Skip(1).Take(1))
90 | { foreach (var l in left.Splits())
91 | { foreach (var f in Riffles(l.Second(), r.Second()))
92 | { yield return l.First().Concat(r.First()).Concat(f);
93 | }
94 | }
95 | }
96 | }
97 | public static T Second (this IEnumerable these)
98 | { return these.Skip(1).First();
99 | }
100 | public static IEnumerable>>
101 | Splits(this IEnumerable these)
102 | { var c = these.Count();
103 | for (var i = 0; i <= c; i++)
104 | yield return new IEnumerable [2] {these.Take(i), these.Skip(i)};
105 | }
106 |
107 | public static IEnumerable Append(this IEnumerable these, T that)
108 | { foreach (var t in these)
109 | yield return t;
110 | yield return that;
111 | }
112 | public static IEnumerable Prepend(this IEnumerable these, T that)
113 | { yield return that;
114 | foreach (var t in these)
115 | yield return t;
116 | }
117 | public static IEnumerable>>
118 | PluckPairs(this IEnumerable xs)
119 | { var c = xs.Count();
120 | var result = new List>>();
121 | for (var n = 1; n <= c; n++)
122 | { var ys = new List();
123 | var y = default(T);
124 | var i = 1;
125 | foreach (var x in xs)
126 | { if (i != n)
127 | ys.Add(x);
128 | else
129 | y = x;
130 | i++;
131 | }
132 | result.Add(Tuple.Create(y, (IEnumerable)ys));
133 | }
134 | return result;
135 | }
136 | public static Tuple> PluckPair(this
137 | IEnumerable xs, int n)
138 | { var c = xs.Count();
139 | if (n <= 0 || n > c)
140 | throw new ArgumentOutOfRangeException("n",
141 | String.Format("argument must have value between 1 and
142 | {0} inclusive", c));
143 | var ys = new List();
144 | var y = default(T);
145 | var i = 1;
146 | foreach (var x in xs)
147 | { if (i != n)
148 | ys.Add(x);
149 | else
150 | y = x;
151 | i++;
152 | }
153 | return Tuple.Create(y, (IEnumerable)ys);
154 | }
155 |
156 | // Slow but understandable "reference implementation" of Permutations
157 | public static IEnumerable> Permutations2(this
158 | IEnumerable these)
159 | { Debug.Assert(these != null);
160 | // Inherently combinatorial-time algorithm!
161 | var len = these.Count();
162 | if (len == 1)
163 | { yield return these;
164 | yield break;
165 | }
166 | foreach (var pluckPair in these.PluckPairs())
167 | { foreach (var permutation in pluckPair.Item2.Permutations2())
168 | { yield return permutation.Prepend(pluckPair.Item1);
169 | }
170 | }
171 | }
172 | // Faster but more difficult index-based implementation of Permutations
173 | public static IEnumerable> Permutations(this
174 | IEnumerable these)
175 | { Debug.Assert(these != null);
176 | // Inherently combinatorial-time algorithm!
177 | var len = these.Count();
178 | if (len == 1)
179 | { yield return these;
180 | yield break;
181 | }
182 | var source = these.ToArray();
183 | var result = new T [len];
184 | for (var i = 0; i < len; i++)
185 | { result[0] = source[i];
186 | var rs = new T [len - 1];
187 | for (var j = 0; j < len - 1; j++)
188 | { if (j < i)
189 | { rs[j] = source[j];
190 | }
191 | else if (j >= i)
192 | { rs[j] = source[j + 1];
193 | }
194 | }
195 | var perms = rs.Permutations();
196 | foreach (var perm in perms)
197 | { var ps = perm.ToArray();
198 | for(var j = 0; j < len - 1; j++)
199 | result[j + 1] = ps[j];
200 | yield return result;
201 | }
202 | }
203 | }
204 | }
205 | */
206 |
--------------------------------------------------------------------------------
/lib/koanutils.js:
--------------------------------------------------------------------------------
1 | var Range = {
2 | create : function (start, count) {
3 | var values = [];
4 | for(var i = 0; i < count; i++) {
5 | values.push(i + start);
6 | }
7 |
8 | return values;
9 | }
10 | };
11 |
12 | Array.prototype.toObservable = function() {
13 | return Rx.Observable.fromArray(this);
14 | };
15 |
16 | var Ix = L2O;
17 |
18 | Array.prototype.toEnumerable = function() {
19 | return Ix.Enumerable.fromArray(this);
20 | };
21 |
22 | Rx.Subject.prototype.onNextAll = function() {
23 | var subject = this;
24 | for(var arg in arguments) {
25 | subject.onNext(arguments[arg]);
26 | }
27 | };
28 |
--------------------------------------------------------------------------------
/lib/qunit.css:
--------------------------------------------------------------------------------
1 | /** Font Family and Sizes */
2 |
3 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
4 | font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial;
5 | }
6 |
7 | #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
8 | #qunit-tests { font-size: smaller; }
9 |
10 |
11 | /** Resets */
12 |
13 | #qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {
14 | margin: 0;
15 | padding: 0;
16 | }
17 |
18 |
19 | /** Header */
20 |
21 | #qunit-header {
22 | padding: 0.5em 0 0.5em 1em;
23 |
24 | color: #8699a4;
25 | background-color: #0d3349;
26 |
27 | font-size: 1.5em;
28 | line-height: 1em;
29 | font-weight: normal;
30 |
31 | border-radius: 15px 15px 0 0;
32 | -moz-border-radius: 15px 15px 0 0;
33 | -webkit-border-top-right-radius: 15px;
34 | -webkit-border-top-left-radius: 15px;
35 | }
36 |
37 | #qunit-header a {
38 | text-decoration: none;
39 | color: #c2ccd1;
40 | }
41 |
42 | #qunit-header a:hover,
43 | #qunit-header a:focus {
44 | color: #fff;
45 | }
46 |
47 | #qunit-banner {
48 | height: 5px;
49 | }
50 |
51 | #qunit-testrunner-toolbar {
52 | padding: 0.5em 0 0.5em 2em;
53 | color: #5E740B;
54 | background-color: #eee;
55 | }
56 |
57 | #qunit-userAgent {
58 | padding: 0.5em 0 0.5em 2.5em;
59 | background-color: #2b81af;
60 | color: #fff;
61 | text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
62 | }
63 |
64 |
65 | /** Tests: Pass/Fail */
66 |
67 | #qunit-tests {
68 | list-style-position: inside;
69 | }
70 |
71 | #qunit-tests li {
72 | padding: 0.4em 0.5em 0.4em 2.5em;
73 | border-bottom: 1px solid #fff;
74 | list-style-position: inside;
75 | }
76 |
77 | #qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running {
78 | display: none;
79 | }
80 |
81 | #qunit-tests li strong {
82 | cursor: pointer;
83 | }
84 |
85 | #qunit-tests ol {
86 | margin-top: 0.5em;
87 | padding: 0.5em;
88 |
89 | background-color: #fff;
90 |
91 | border-radius: 15px;
92 | -moz-border-radius: 15px;
93 | -webkit-border-radius: 15px;
94 |
95 | box-shadow: inset 0px 2px 13px #999;
96 | -moz-box-shadow: inset 0px 2px 13px #999;
97 | -webkit-box-shadow: inset 0px 2px 13px #999;
98 | }
99 |
100 | #qunit-tests table {
101 | border-collapse: collapse;
102 | margin-top: .2em;
103 | }
104 |
105 | #qunit-tests th {
106 | text-align: right;
107 | vertical-align: top;
108 | padding: 0 .5em 0 0;
109 | }
110 |
111 | #qunit-tests td {
112 | vertical-align: top;
113 | }
114 |
115 | #qunit-tests pre {
116 | margin: 0;
117 | white-space: pre-wrap;
118 | word-wrap: break-word;
119 | }
120 |
121 | #qunit-tests del {
122 | background-color: #e0f2be;
123 | color: #374e0c;
124 | text-decoration: none;
125 | }
126 |
127 | #qunit-tests ins {
128 | background-color: #ffcaca;
129 | color: #500;
130 | text-decoration: none;
131 | }
132 |
133 | /*** Test Counts */
134 |
135 | #qunit-tests b.counts { color: black; }
136 | #qunit-tests b.passed { color: #5E740B; }
137 | #qunit-tests b.failed { color: #710909; }
138 |
139 | #qunit-tests li li {
140 | margin: 0.5em;
141 | padding: 0.4em 0.5em 0.4em 0.5em;
142 | background-color: #fff;
143 | border-bottom: none;
144 | list-style-position: inside;
145 | }
146 |
147 | /*** Passing Styles */
148 |
149 | #qunit-tests li li.pass {
150 | color: #5E740B;
151 | background-color: #fff;
152 | border-left: 26px solid #C6E746;
153 | }
154 |
155 | #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
156 | #qunit-tests .pass .test-name { color: #366097; }
157 |
158 | #qunit-tests .pass .test-actual,
159 | #qunit-tests .pass .test-expected { color: #999999; }
160 |
161 | #qunit-banner.qunit-pass { background-color: #C6E746; }
162 |
163 | /*** Failing Styles */
164 |
165 | #qunit-tests li li.fail {
166 | color: #710909;
167 | background-color: #fff;
168 | border-left: 26px solid #EE5757;
169 | }
170 |
171 | #qunit-tests > li:last-child {
172 | border-radius: 0 0 15px 15px;
173 | -moz-border-radius: 0 0 15px 15px;
174 | -webkit-border-bottom-right-radius: 15px;
175 | -webkit-border-bottom-left-radius: 15px;
176 | }
177 |
178 | #qunit-tests .fail { color: #000000; background-color: #EE5757; }
179 | #qunit-tests .fail .test-name,
180 | #qunit-tests .fail .module-name { color: #000000; }
181 |
182 | #qunit-tests .fail .test-actual { color: #EE5757; }
183 | #qunit-tests .fail .test-expected { color: green; }
184 |
185 | #qunit-banner.qunit-fail { background-color: #EE5757; }
186 |
187 |
188 | /** Result */
189 |
190 | #qunit-testresult {
191 | padding: 0.5em 0.5em 0.5em 2.5em;
192 |
193 | color: #2b81af;
194 | background-color: #D2E0E6;
195 |
196 | border-bottom: 1px solid white;
197 | }
198 |
199 | /** Fixture */
200 |
201 | #qunit-fixture {
202 | position: absolute;
203 | top: -10000px;
204 | left: -10000px;
205 | }
206 |
--------------------------------------------------------------------------------
/lib/rx.aggregates.min.js:
--------------------------------------------------------------------------------
1 | /*** @preserve Copyright (c) Microsoft Corporation. All rights reserved.
2 | * This code is licensed by Microsoft Corporation under the terms
3 | * of the MICROSOFT REACTIVE EXTENSIONS FOR JAVASCRIPT AND .NET LIBRARIES License.
4 | * See http://go.microsoft.com/fwlink/?LinkID=220762.
5 | */
6 | (function(e,t){var n=typeof exports=="object"&&exports&&(typeof e=="object"&&e&&e==e.global&&(window=e),exports);typeof define=="function"&&define.amd?define(["rx","exports"],function(n,r){return e.Rx=t(e,r,n),e.Rx}):typeof module=="object"&&module&&module.exports==n?module.exports=t(e,module.exports,require("./rx")):e.Rx=t(e,{},e.Rx)})(this,function(e,t,n,r){function l(e,t){return e===t}function c(e){return e}function h(e,t){return e>t?1:e===t?0:-1}function p(e,t,n){return new u(function(r){var i=!1,s=null,o=[];return e.subscribe(function(e){var u,a;try{a=t(e)}catch(f){r.onError(f);return}u=0;if(!i)i=!0,s=a;else try{u=n(a,s)}catch(l){r.onError(l);return}u>0&&(s=a,o=[]),u>=0&&o.push(e)},r.onError.bind(r),function(){r.onNext(o),r.onCompleted()})})}function d(e){if(e.length==0)throw new Error(f);return e[0]}function v(e,t,n){return new u(function(r){var i=0,s=t.length;return e.subscribe(function(e){var o=!1;try{i0){i=a.shift();try{n=t(i,e)}catch(o){r.onError(o);return}n||(r.onNext(!1),r.onCompleted())}else s?(r.onNext(!1),r.onCompleted()):u.push(e)},r.onError.bind(r),function(){i=!0,u.length===0&&(a.length>0?(r.onNext(!1),r.onCompleted()):s&&(r.onNext(!0),r.onCompleted()))}),l=e.subscribe(function(e){var n,s;if(u.length>0){s=u.shift();try{n=t(s,e)}catch(o){r.onError(o);return}n||(r.onNext(!1),r.onCompleted())}else i?(r.onNext(!1),r.onCompleted()):a.push(e)},r.onError.bind(r),function(){s=!0,a.length===0&&(u.length>0?(r.onNext(!1),r.onCompleted()):i&&(r.onNext(!0),r.onCompleted()))});return new o(f,l)})},s.elementAt=function(e){return m(this,e,!1)},s.elementAtOrDefault=function(e,t){return m(this,e,!0,t)},s.single=function(e){return e?this.where(e).single():g(this,!1)},s.singleOrDefault=function(e,t){return e?this.where(e).singleOrDefault(null,t):g(this,!0,t)},s.first=function(e){return e?this.where(e).first():y(this,!1)},s.firstOrDefault=function(e,t){return e?this.where(e).firstOrDefault(null,t):y(this,!0,t)},s.last=function(e){return e?this.where(e).last():b(this,!1)},s.lastOrDefault=function(e,t){return e?this.where(e).lastOrDefault(null,t):b(this,!0,t)},n});
--------------------------------------------------------------------------------
/lib/rx.binding.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @preserve Copyright (c) Microsoft Corporation. All rights reserved.
3 | * This code is licensed by Microsoft Corporation under the terms
4 | * of the Microsoft Reference Source License (MS-RSL).
5 | * http://referencesource.microsoft.com/referencesourcelicense.aspx.
6 | */
7 |
8 | (function (root, factory) {
9 | var freeExports = typeof exports == 'object' && exports &&
10 | (typeof root == 'object' && root && root == root.global && (window = root), exports);
11 |
12 | // Because of build optimizers
13 | if (typeof define === 'function' && define.amd) {
14 | define(['rx', 'exports'], function (Rx, exports) {
15 | root.Rx = factory(root, exports, Rx);
16 | return root.Rx;
17 | });
18 | } else if (typeof module == 'object' && module && module.exports == freeExports) {
19 | module.exports = factory(root, module.exports, require('./rx'));
20 | } else {
21 | root.Rx = factory(root, {}, root.Rx);
22 | }
23 | }(this, function (global, exp, root, undefined) {
24 |
25 | var Observable = root.Observable,
26 | observableProto = Observable.prototype,
27 | AnonymousObservable = root.Internals.AnonymousObservable,
28 | Subject = root.Subject,
29 | AsyncSubject = root.AsyncSubject,
30 | Observer = root.Observer,
31 | ScheduledObserver = root.Internals.ScheduledObserver,
32 | disposableCreate = root.Disposable.create,
33 | disposableEmpty = root.Disposable.empty,
34 | CompositeDisposable = root.CompositeDisposable,
35 | currentThreadScheduler = root.Scheduler.currentThread,
36 | inherits = root.Internals.inherits,
37 | addProperties = root.Internals.addProperties;
38 |
39 | // Utilities
40 | var objectDisposed = 'Object has been disposed';
41 | function checkDisposed() {
42 | if (this.isDisposed) {
43 | throw new Error(objectDisposed);
44 | }
45 | }
46 |
47 | observableProto.multicast = function (subjectOrSubjectSelector, selector) {
48 | var source = this;
49 | return typeof subjectOrSubjectSelector === 'function' ?
50 | new AnonymousObservable(function (observer) {
51 | var connectable = source.multicast(subjectOrSubjectSelector());
52 | return new CompositeDisposable(selector(connectable).subscribe(observer), connectable.connect());
53 | }) :
54 | new ConnectableObservable(source, subjectOrSubjectSelector);
55 | };
56 |
57 | observableProto.publish = function (selector) {
58 | return !selector ?
59 | this.multicast(new Subject()) :
60 | this.multicast(function () {
61 | return new Subject();
62 | }, selector);
63 | };
64 |
65 | observableProto.publishLast = function (selector) {
66 | return !selector ?
67 | this.multicast(new AsyncSubject()) :
68 | this.multicast(function () {
69 | return new AsyncSubject();
70 | }, selector);
71 | };
72 |
73 | observableProto.publishValue = function (initialValueOrSelector, initialValue) {
74 | return arguments.length === 2 ?
75 | this.multicast(function () {
76 | return new BehaviorSubject(initialValue);
77 | }, initialValueOrSelector) :
78 | this.multicast(new BehaviorSubject(initialValueOrSelector));
79 | };
80 |
81 | observableProto.replay = function (selector, bufferSize, window, scheduler) {
82 | return !selector ?
83 | this.multicast(new ReplaySubject(bufferSize, window, scheduler)) :
84 | this.multicast(function () {
85 | return new ReplaySubject(bufferSize, window, scheduler);
86 | }, selector);
87 | };
88 |
89 | var InnerSubscription = function (subject, observer) {
90 | this.subject = subject;
91 | this.observer = observer;
92 | };
93 | InnerSubscription.prototype.dispose = function () {
94 | if (!this.subject.isDisposed && this.observer !== null) {
95 | var idx = this.subject.observers.indexOf(this.observer);
96 | this.subject.observers.splice(idx, 1);
97 | this.observer = null;
98 | }
99 | };
100 |
101 | var BehaviorSubject = root.BehaviorSubject = (function () {
102 | function subscribe(observer) {
103 | var ex;
104 | checkDisposed.call(this);
105 | if (!this.isStopped) {
106 | this.observers.push(observer);
107 | observer.onNext(this.value);
108 | return new InnerSubscription(this, observer);
109 | }
110 | ex = this.exception;
111 | if (ex) {
112 | observer.onError(ex);
113 | } else {
114 | observer.onCompleted();
115 | }
116 | return disposableEmpty;
117 | }
118 |
119 | inherits(BehaviorSubject, Observable);
120 | function BehaviorSubject(value) {
121 | BehaviorSubject.super_.constructor.call(this, subscribe);
122 |
123 | this.value = value,
124 | this.observers = [],
125 | this.isDisposed = false,
126 | this.isStopped = false,
127 | this.exception = null;
128 | }
129 |
130 | addProperties(BehaviorSubject.prototype, Observer, {
131 | onCompleted: function () {
132 | checkDisposed.call(this);
133 | if (!this.isStopped) {
134 | var os = this.observers.slice(0);
135 | this.isStopped = true;
136 | for (var i = 0, len = os.length; i < len; i++) {
137 | os[i].onCompleted();
138 | }
139 |
140 | this.observers = [];
141 | }
142 | },
143 | onError: function (error) {
144 | checkDisposed.call(this);
145 | if (!this.isStopped) {
146 | var os = this.observers.slice(0);
147 | this.isStopped = true;
148 | this.exception = error;
149 |
150 | for (var i = 0, len = os.length; i < len; i++) {
151 | os[i].onError(error);
152 | }
153 |
154 | this.observers = [];
155 | }
156 | },
157 | onNext: function (value) {
158 | checkDisposed.call(this);
159 | if (!this.isStopped) {
160 | this.value = value;
161 | var os = this.observers.slice(0);
162 | for (var i = 0, len = os.length; i < len; i++) {
163 | os[i].onNext(value);
164 | }
165 | }
166 | },
167 | dispose: function () {
168 | this.isDisposed = true;
169 | this.observers = null;
170 | this.value = null;
171 | this.exception = null;
172 | }
173 | });
174 |
175 | return BehaviorSubject;
176 | }());
177 |
178 | // Replay Subject
179 | var ReplaySubject = root.ReplaySubject = (function (base) {
180 | var RemovableDisposable = function (subject, observer) {
181 | this.subject = subject;
182 | this.observer = observer;
183 | };
184 |
185 | RemovableDisposable.prototype.dispose = function () {
186 | this.observer.dispose();
187 | if (!this.subject.isDisposed) {
188 | var idx = this.subject.observers.indexOf(this.observer);
189 | this.subject.observers.splice(idx, 1);
190 | }
191 | };
192 |
193 | function subscribe(observer) {
194 | var so = new ScheduledObserver(this.scheduler, observer),
195 | subscription = new RemovableDisposable(this, so);
196 | checkDisposed.call(this);
197 | this._trim(this.scheduler.now());
198 | this.observers.push(so);
199 |
200 | var n = this.q.length;
201 |
202 | for (var i = 0, len = this.q.length; i < len; i++) {
203 | so.onNext(this.q[i].value);
204 | }
205 |
206 | if (this.hasError) {
207 | n++;
208 | so.onError(this.error);
209 | } else if (this.isStopped) {
210 | n++;
211 | so.onCompleted();
212 | }
213 |
214 | so.ensureActive(n);
215 | return subscription;
216 | }
217 |
218 | inherits(ReplaySubject, Observable);
219 |
220 | function ReplaySubject(bufferSize, window, scheduler) {
221 | this.bufferSize = bufferSize == null ? Number.MAX_VALUE : bufferSize;
222 | this.window = window == null ? Number.MAX_VALUE : window;
223 | this.scheduler = scheduler || currentThreadScheduler;
224 | this.q = [];
225 | this.observers = [];
226 | this.isStopped = false;
227 | this.isDisposed = false;
228 | this.hasError = false;
229 | this.error = null;
230 | ReplaySubject.super_.constructor.call(this, subscribe);
231 | }
232 |
233 | addProperties(ReplaySubject.prototype, Observer, {
234 | _trim: function (now) {
235 | while (this.q.length > this.bufferSize) {
236 | this.q.shift();
237 | }
238 | while (this.q.length > 0 && (now - this.q[0].interval) > this.window) {
239 | this.q.shift();
240 | }
241 | },
242 | onNext: function (value) {
243 | var observer;
244 | checkDisposed.call(this);
245 | if (!this.isStopped) {
246 | var now = this.scheduler.now();
247 | this.q.push({ interval: now, value: value });
248 | this._trim(now);
249 |
250 | var o = this.observers.slice(0);
251 | for (var i = 0, len = o.length; i < len; i++) {
252 | observer = o[i];
253 | observer.onNext(value);
254 | observer.ensureActive();
255 | }
256 | }
257 | },
258 | onError: function (error) {
259 | var observer;
260 | checkDisposed.call(this);
261 | if (!this.isStopped) {
262 | this.isStopped = true;
263 | this.error = error;
264 | this.hasError = true;
265 | var now = this.scheduler.now();
266 | this._trim(now);
267 | var o = this.observers.slice(0);
268 | for (var i = 0, len = o.length; i < len; i++) {
269 | observer = o[i];
270 | observer.onError(error);
271 | observer.ensureActive();
272 | }
273 | this.observers = [];
274 | }
275 | },
276 | onCompleted: function () {
277 | var observer;
278 | checkDisposed.call(this);
279 | if (!this.isStopped) {
280 | this.isStopped = true;
281 | var now = this.scheduler.now();
282 | this._trim(now);
283 | var o = this.observers.slice(0);
284 | for (var i = 0, len = o.length; i < len; i++) {
285 | observer = o[i];
286 | observer.onCompleted();
287 | observer.ensureActive();
288 | }
289 | this.observers = [];
290 | }
291 | },
292 | dispose: function () {
293 | this.isDisposed = true;
294 | this.observers = null;
295 | }
296 | });
297 |
298 | return ReplaySubject;
299 | }());
300 |
301 | var ConnectableObservable = (function () {
302 | inherits(ConnectableObservable, Observable);
303 | function ConnectableObservable(source, subject) {
304 | var state = {
305 | subject: subject,
306 | source: source.asObservable(),
307 | hasSubscription: false,
308 | subscription: null
309 | };
310 |
311 | this.connect = function () {
312 | if (!state.hasSubscription) {
313 | state.hasSubscription = true;
314 | state.subscription = new CompositeDisposable(state.source.subscribe(state.subject), disposableCreate(function () {
315 | state.hasSubscription = false;
316 | }));
317 | }
318 | return state.subscription;
319 | };
320 |
321 | var subscribe = function (observer) {
322 | return state.subject.subscribe(observer);
323 | };
324 | ConnectableObservable.super_.constructor.call(this, subscribe);
325 | }
326 |
327 | ConnectableObservable.prototype.connect = function () { return this.connect(); };
328 | ConnectableObservable.prototype.refCount = function () {
329 | var connectableSubscription = null,
330 | count = 0,
331 | source = this;
332 | return new AnonymousObservable(function (observer) {
333 | var shouldConnect, subscription;
334 | count++;
335 | shouldConnect = count === 1;
336 | subscription = source.subscribe(observer);
337 | if (shouldConnect) {
338 | connectableSubscription = source.connect();
339 | }
340 | return disposableCreate(function () {
341 | subscription.dispose();
342 | count--;
343 | if (count === 0) {
344 | connectableSubscription.dispose();
345 | }
346 | });
347 | });
348 | };
349 |
350 | return ConnectableObservable;
351 | }());
352 |
353 | return root;
354 | }));
--------------------------------------------------------------------------------
/lib/rx.binding.min.js:
--------------------------------------------------------------------------------
1 | /*** @preserve Copyright (c) Microsoft Corporation. All rights reserved.
2 | * This code is licensed by Microsoft Corporation under the terms
3 | * of the MICROSOFT REACTIVE EXTENSIONS FOR JAVASCRIPT AND .NET LIBRARIES License.
4 | * See http://go.microsoft.com/fwlink/?LinkID=220762.
5 | */
6 | (function(e,t){var n=typeof exports=="object"&&exports&&(typeof e=="object"&&e&&e==e.global&&(window=e),exports);typeof define=="function"&&define.amd?define(["rx","exports"],function(n,r){return e.Rx=t(e,r,n),e.Rx}):typeof module=="object"&&module&&module.exports==n?module.exports=t(e,module.exports,require("./rx")):e.Rx=t(e,{},e.Rx)})(this,function(e,t,n,r){function y(){if(this.isDisposed)throw new Error(g)}var i=n.Observable,s=i.prototype,o=n.Internals.AnonymousObservable,u=n.Subject,a=n.AsyncSubject,f=n.Observer,l=n.Internals.ScheduledObserver,c=n.Disposable.create,h=n.Disposable.empty,p=n.CompositeDisposable,d=n.Scheduler.currentThread,v=n.Internals.inherits,m=n.Internals.addProperties,g="Object has been disposed";s.multicast=function(e,t){var n=this;return typeof e=="function"?new o(function(r){var i=n.multicast(e());return new p(t(i).subscribe(r),i.connect())}):new S(n,e)},s.publish=function(e){return e?this.multicast(function(){return new u},e):this.multicast(new u)},s.publishLast=function(e){return e?this.multicast(function(){return new a},e):this.multicast(new a)},s.publishValue=function(e,t){return arguments.length===2?this.multicast(function(){return new w(t)},e):this.multicast(new w(e))},s.replay=function(e,t,n,r){return e?this.multicast(function(){return new E(t,n,r)},e):this.multicast(new E(t,n,r))};var b=function(e,t){this.subject=e,this.observer=t};b.prototype.dispose=function(){if(!this.subject.isDisposed&&this.observer!==null){var e=this.subject.observers.indexOf(this.observer);this.subject.observers.splice(e,1),this.observer=null}};var w=n.BehaviorSubject=function(){function e(e){var t;return y.call(this),this.isStopped?(t=this.exception,t?e.onError(t):e.onCompleted(),h):(this.observers.push(e),e.onNext(this.value),new b(this,e))}function t(n){t.super_.constructor.call(this,e),this.value=n,this.observers=[],this.isDisposed=!1,this.isStopped=!1,this.exception=null}return v(t,i),m(t.prototype,f,{onCompleted:function(){y.call(this);if(!this.isStopped){var e=this.observers.slice(0);this.isStopped=!0;for(var t=0,n=e.length;tthis.bufferSize)this.q.shift();while(this.q.length>0&&e-this.q[0].interval>this.window)this.q.shift()},onNext:function(e){var t;y.call(this);if(!this.isStopped){var n=this.scheduler.now();this.q.push({interval:n,value:e}),this._trim(n);var r=this.observers.slice(0);for(var i=0,s=r.length;i=e)return n}r=e|1;while(r=0;o=this.entries[o].next)if(this.entries[o].hashCode===i&&this.comparer(this.entries[o].key,e)){if(n)throw b;this.entries[o].value=t;return}if(this.freeCount>0){var u=this.freeList;this.freeList=this.entries[u].next,--this.freeCount}else this.size===this.entries.length&&(this._resize(),s=i%this.buckets.length),u=this.size,++this.size;this.entries[u].hashCode=i,this.entries[u].next=this.buckets[s],this.entries[u].key=e,this.entries[u].value=t,this.buckets[s]=u},T.prototype._resize=function(){var e=E(this.size*2),t=new Array(e);for(r=0;r=0;s=this.entries[s].next){if(this.entries[s].hashCode===t&&this.comparer(this.entries[s].key,e))return i<0?this.buckets[n]=this.entries[s].next:this.entries[i].next=this.entries[s].next,this.entries[s].hashCode=-1,this.entries[s].next=this.freeList,this.entries[s].key=null,this.entries[s].value=null,this.freeList=s,++this.freeCount,!0;i=s}}return!1},T.prototype.clear=function(){var e,t;if(this.size<=0)return;for(e=0,t=this.buckets.length;e=0;n=this.entries[n].next)if(this.entries[n].hashCode===t&&this.comparer(this.entries[n].key,e))return n}return-1},T.prototype.count=function(){return this.size-this.freeCount},T.prototype.tryGetEntry=function(e){var t=this._findEntry(e);return t>=0?{key:this.entries[t].key,value:this.entries[t].value}:r},T.prototype.getValues=function(){var e=0,t=[];if(this.entries!==r)for(var n=0;n=0&&(t[e++]=this.entries[n].value);return t},T.prototype.get=function(e){var t=this._findEntry(e);if(t>=0)return this.entries[t].value;throw new Error(y)},T.prototype.set=function(e,t){this._insert(e,t,!1)},T.prototype.containskey=function(e){return this._findEntry(e)>=0},l.join=function(e,t,n,r){var i=this;return new h(function(o){var a=new s,f=!1,l=0,c=new T,h=!1,p=0,d=new T;return a.add(i.subscribe(function(e){var n,i,s=l++,h=new u,p,m;c.add(s,e),a.add(h),i=function(){return c.remove(s)&&c.count()===0&&f&&o.onCompleted(),a.remove(h)};try{n=t(e)}catch(g){o.onError(g);return}h.disposable(n.take(1).subscribe(v,o.onError.bind(o),function(){i()})),m=d.getValues();for(var y=0;y 0) {
115 | isOwner = !isAcquired;
116 | isAcquired = true;
117 | }
118 | if (isOwner) {
119 | m.setDisposable(scheduler.scheduleRecursive(function (self) {
120 | var work;
121 | if (q.length > 0) {
122 | work = q.shift();
123 | } else {
124 | isAcquired = false;
125 | return;
126 | }
127 | var m1 = new SingleAssignmentDisposable();
128 | d.add(m1);
129 | m1.setDisposable(work.subscribe(function (x) {
130 | observer.onNext(x);
131 | var result = null;
132 | try {
133 | result = selector(x);
134 | } catch (e) {
135 | observer.onError(e);
136 | }
137 | q.push(result);
138 | activeCount++;
139 | ensureActive();
140 | }, observer.onError.bind(observer), function () {
141 | d.remove(m1);
142 | activeCount--;
143 | if (activeCount === 0) {
144 | observer.onCompleted();
145 | }
146 | }));
147 | self();
148 | }));
149 | }
150 | };
151 |
152 | q.push(source);
153 | activeCount++;
154 | ensureActive();
155 | return d;
156 | });
157 | };
158 |
159 | Observable.forkJoin = function () {
160 | var allSources = argsOrArray(arguments, 0);
161 | return observableCreateWithDisposable(function (subscriber) {
162 | var count = allSources.length;
163 | if (count === 0) {
164 | subscriber.onCompleted();
165 | return disposableEmpty;
166 | }
167 | var group = new CompositeDisposable(),
168 | finished = false,
169 | hasResults = new Array(count),
170 | hasCompleted = new Array(count),
171 | results = new Array(count);
172 |
173 | for (var idx = 0; idx < count; idx++) {
174 | (function (i) {
175 | var source = allSources[i];
176 | group.add(source.subscribe(function (value) {
177 | if (!finished) {
178 | hasResults[i] = true;
179 | results[i] = value;
180 | }
181 | }, function (e) {
182 | finished = true;
183 | subscriber.onError(e);
184 | group.dispose();
185 | }, function () {
186 | if (!finished) {
187 | if (!hasResults[i]) {
188 | subscriber.onCompleted();
189 | return;
190 | }
191 | hasCompleted[i] = true;
192 | for (var ix = 0; ix < count; ix++) {
193 | if (!hasCompleted[ix]) {
194 | return;
195 | }
196 | }
197 | finished = true;
198 | subscriber.onNext(results);
199 | subscriber.onCompleted();
200 | }
201 | }));
202 | })(idx);
203 | }
204 |
205 | return group;
206 | });
207 | };
208 |
209 | observableProto.forkJoin = function (second, resultSelector) {
210 | var first = this;
211 |
212 | return observableCreateWithDisposable(function (observer) {
213 | var leftStopped = false, rightStopped = false,
214 | hasLeft = false, hasRight = false,
215 | lastLeft, lastRight,
216 | leftSubscription = new SingleAssignmentDisposable(), rightSubscription = new SingleAssignmentDisposable();
217 |
218 | leftSubscription.setDisposable(
219 | first.subscribe(function (left) {
220 | hasLeft = true;
221 | lastLeft = left;
222 | }, function (err) {
223 | rightSubscription.dispose();
224 | observer.onError(err);
225 | }, function () {
226 | leftStopped = true;
227 | if (rightStopped) {
228 | if (!hasLeft) {
229 | observer.onCompleted();
230 | } else if (!hasRight) {
231 | observer.onCompleted();
232 | } else {
233 | var result;
234 | try {
235 | result = resultSelector(lastLeft, lastRight);
236 | } catch (e) {
237 | observer.onError(e);
238 | return;
239 | }
240 | observer.onNext(result);
241 | observer.onCompleted();
242 | }
243 | }
244 | })
245 | );
246 |
247 | rightSubscription.setDisposable(
248 | second.subscribe(function (right) {
249 | hasRight = true;
250 | lastRight = right;
251 | }, function (err) {
252 | leftSubscription.dispose();
253 | observer.onError(err);
254 | }, function () {
255 | rightStopped = true;
256 | if (leftStopped) {
257 | if (!hasLeft) {
258 | observer.onCompleted();
259 | } else if (!hasRight) {
260 | observer.onCompleted();
261 | } else {
262 | var result;
263 | try {
264 | result = resultSelector(lastLeft, lastRight);
265 | } catch (e) {
266 | observer.onError(e);
267 | return;
268 | }
269 | observer.onNext(result);
270 | observer.onCompleted();
271 | }
272 | }
273 | })
274 | );
275 |
276 | return new CompositeDisposable(leftSubscription, rightSubscription);
277 | });
278 | };
279 |
280 | return root;
281 | }));
--------------------------------------------------------------------------------
/lib/rx.experimental.min.js:
--------------------------------------------------------------------------------
1 | /*** @preserve Copyright (c) Microsoft Corporation. All rights reserved.
2 | * This code is licensed by Microsoft Corporation under the terms
3 | * of the MICROSOFT REACTIVE EXTENSIONS FOR JAVASCRIPT AND .NET LIBRARIES License.
4 | * See http://go.microsoft.com/fwlink/?LinkID=220762.
5 | */
6 | (function(e,t){var n=typeof exports=="object"&&exports&&(typeof e=="object"&&e&&e==e.global&&(window=e),exports);typeof define=="function"&&define.amd?define(["rx","exports"],function(n,r){return e.Rx=t(e,r,n),e.Rx}):typeof module=="object"&&module&&module.exports==n?module.exports=t(e,module.exports,require("./rx")):e.Rx=t(e,{},e.Rx)})(this,function(e,t,n,r){function w(e,t){return e.length===1&&Array.isArray(e[t])?e[t]:b.call(e)}function E(e,t){return new m(function(){var n;return v(function(){return e()?(n=t,!0):!1},function(){return n})})}var i=n.Observable,s=i.prototype,o=i.createWithDisposable,u=i.concat,a=i.defer,f=i.empty,l=n.Disposable.empty,c=n.Internals.BinaryObserver,h=n.CompositeDisposable,p=n.SerialDisposable,d=n.SingleAssignmentDisposable,v=n.Internals.Enumerator.create,m=n.Internals.Enumerable,g=m.forEach,y=n.Scheduler.immediate,b=Array.prototype.slice;s.letBind=function(e){return e(this)},i.ifThen=function(e,t,n){return a(function(){n||(n=f());if(n.now){var r=n;n=f(r)}return e()?t:n})},i.forIn=function(e,t){return g(e,t).concat()};var S=i.whileDo=function(e,t){return E(e,t).concat()};return s.doWhile=function(e){return u([this,S(e,this)])},i.switchCase=function(e,t,n){return a(function(){n||(n=f());if(n.now){var i=n;n=f(i)}var s=t[e()];return s!==r?s:n})},s.expand=function(e,t){t||(t=y);var n=this;return o(function(r){var i=[],s=new p,o=new h(s),u=0,a=!1,f=function(){var n=!1;i.length>0&&(n=!a,a=!0),n&&s.setDisposable(t.scheduleRecursive(function(t){var n;if(!(i.length>0)){a=!1;return}n=i.shift();var s=new d;o.add(s),s.setDisposable(n.subscribe(function(t){r.onNext(t);var n=null;try{n=e(t)}catch(s){r.onError(s)}i.push(n),u++,f()},r.onError.bind(r),function(){o.remove(s),u--,u===0&&r.onCompleted()})),t()}))};return i.push(n),u++,f(),o})},i.forkJoin=function(){var e=w(arguments,0);return o(function(t){var n=e.length;if(n===0)return t.onCompleted(),l;var r=new h,i=!1,s=new Array(n),o=new Array(n),u=new Array(n);for(var a=0;a
93 | /// Creates a pattern that matches the current plan matches and when the specified observable sequences has an available value.
94 | ///
95 | /// Observable sequence to match in addition to the current pattern.
96 | /// Pattern object that matches when all observable sequences in the pattern have an available value.
97 | var patterns = this.patterns.slice(0);
98 | patterns.push(other);
99 | return new Pattern(patterns);
100 | };
101 | Pattern.prototype.then = function (selector) {
102 | ///
103 | /// Matches when all observable sequences in the pattern (specified using a chain of and operators) have an available value and projects the values.
104 | ///
105 | /// Selector that will be invoked with available values from the source sequences, in the same order of the sequences in the pattern.
106 | /// Plan that produces the projected values, to be fed (with other plans) to the when operator.
107 | return new Plan(this, selector);
108 | };
109 |
110 | // Plan
111 | function Plan(expression, selector) {
112 | this.expression = expression;
113 | this.selector = selector;
114 | }
115 | Plan.prototype.activate = function (externalSubscriptions, observer, deactivate) {
116 | var self = this;
117 | var joinObservers = [];
118 | for (var i = 0, len = this.expression.patterns.length; i < len; i++) {
119 | joinObservers.push(planCreateObserver(externalSubscriptions, this.expression.patterns[i], observer.onError.bind(observer)));
120 | }
121 | var activePlan = new ActivePlan(joinObservers, function () {
122 | var result;
123 | try {
124 | result = self.selector.apply(self, arguments);
125 | } catch (exception) {
126 | observer.onError(exception);
127 | return;
128 | }
129 | observer.onNext(result);
130 | }, function () {
131 | for (var j = 0, jlen = joinObservers.length; j < jlen; j++) {
132 | joinObservers[j].removeActivePlan(activePlan);
133 | }
134 | deactivate(activePlan);
135 | });
136 | for (i = 0, len = joinObservers.length; i < len; i++) {
137 | joinObservers[i].addActivePlan(activePlan);
138 | }
139 | return activePlan;
140 | };
141 |
142 | function planCreateObserver(externalSubscriptions, observable, onError) {
143 | var entry = externalSubscriptions.get(observable);
144 | if (!entry) {
145 | var observer = new JoinObserver(observable, onError);
146 | externalSubscriptions.set(observable, observer);
147 | return observer;
148 | }
149 | return entry;
150 | }
151 |
152 | // Active Plan
153 | function ActivePlan(joinObserverArray, onNext, onCompleted) {
154 | var i, joinObserver;
155 | this.joinObserverArray = joinObserverArray;
156 | this.onNext = onNext;
157 | this.onCompleted = onCompleted;
158 | this.joinObservers = new Map();
159 | for (i = 0; i < this.joinObserverArray.length; i++) {
160 | joinObserver = this.joinObserverArray[i];
161 | this.joinObservers.set(joinObserver, joinObserver);
162 | }
163 | }
164 |
165 | ActivePlan.prototype.dequeue = function () {
166 | var values = this.joinObservers.getValues();
167 | for (var i = 0, len = values.length; i < len; i++) {
168 | values[i].queue.shift();
169 | }
170 | };
171 | ActivePlan.prototype.match = function () {
172 | var firstValues, i, len, isCompleted, values, hasValues = true;
173 | for (i = 0, len = this.joinObserverArray.length; i < len; i++) {
174 | if (this.joinObserverArray[i].queue.length === 0) {
175 | hasValues = false;
176 | break;
177 | }
178 | }
179 | if (hasValues) {
180 | firstValues = [];
181 | isCompleted = false;
182 | for (i = 0, len = this.joinObserverArray.length; i < len; i++) {
183 | firstValues.push(this.joinObserverArray[i].queue[0]);
184 | if (this.joinObserverArray[i].queue[0].kind === 'C') {
185 | isCompleted = true;
186 | }
187 | }
188 | if (isCompleted) {
189 | this.onCompleted();
190 | } else {
191 | this.dequeue();
192 | values = [];
193 | for (i = 0; i < firstValues.length; i++) {
194 | values.push(firstValues[i].value);
195 | }
196 | this.onNext.apply(this, values);
197 | }
198 | }
199 | };
200 |
201 | // Join Observer
202 | var JoinObserver = (function () {
203 |
204 | inherits(JoinObserver, AbstractObserver);
205 |
206 | function JoinObserver(source, onError) {
207 | JoinObserver.super_.constructor.call(this);
208 | this.source = source;
209 | this.onError = onError;
210 | this.queue = [];
211 | this.activePlans = [];
212 | this.subscription = new SingleAssignmentDisposable();
213 | this.isDisposed = false;
214 | }
215 |
216 | JoinObserver.prototype.next = function (notification) {
217 | if (!this.isDisposed) {
218 | if (notification.kind === 'E') {
219 | this.onError(notification.exception);
220 | return;
221 | }
222 | this.queue.push(notification);
223 | var activePlans = this.activePlans.slice(0);
224 | for (var i = 0, len = activePlans.length; i < len; i++) {
225 | activePlans[i].match();
226 | }
227 | }
228 | };
229 | JoinObserver.prototype.error = noop;
230 | JoinObserver.prototype.completed = noop;
231 |
232 | JoinObserver.prototype.addActivePlan = function (activePlan) {
233 | this.activePlans.push(activePlan);
234 | };
235 | JoinObserver.prototype.subscribe = function () {
236 | this.subscription.disposable(this.source.materialize().subscribe(this));
237 | };
238 | JoinObserver.prototype.removeActivePlan = function (activePlan) {
239 | var idx = this.activePlans.indexOf(activePlan);
240 | this.activePlans.splice(idx, 1);
241 | if (this.activePlans.length === 0) {
242 | this.dispose();
243 | }
244 | };
245 | JoinObserver.prototype.dispose = function () {
246 | JoinObserver.super_.dispose.call(this);
247 | if (!this.isDisposed) {
248 | this.isDisposed = true;
249 | this.subscription.dispose();
250 | }
251 | };
252 | return JoinObserver;
253 | } ());
254 |
255 | // Observable extensions
256 | observableProto.and = function (right) {
257 | ///
258 | /// Creates a pattern that matches when both observable sequences have an available value.
259 | ///
260 | /// Observable sequence to match with the current sequence.
261 | /// Pattern object that matches when both observable sequences have an available value.
262 | return new Pattern([this, right]);
263 | };
264 | observableProto.then = function (selector) {
265 | ///
266 | /// Matches when the observable sequence has an available value and projects the value.
267 | ///
268 | /// Selector that will be invoked for values in the source sequence.
269 | /// Plan that produces the projected values, to be fed (with other plans) to the when operator.
270 | return new Pattern([this]).then(selector);
271 | };
272 | Observable.when = function () {
273 | ///
274 | /// Joins together the results from several patterns.
275 | ///
276 | /// A series of plans (specified as an Array of as a series of arguments) created by use of the Then operator on patterns.
277 | /// Observable sequence with the results form matching several patterns.
278 | var plans = argsOrArray(arguments, 0);
279 | return new AnonymousObservable(function (observer) {
280 | var activePlans = [],
281 | externalSubscriptions = new Map(),
282 | group,
283 | i, len,
284 | joinObserver,
285 | joinValues,
286 | outObserver;
287 | outObserver = observerCreate(observer.onNext.bind(observer), function (exception) {
288 | var values = externalSubscriptions.getValues();
289 | for (var j = 0, jlen = values.length; j < jlen; j++) {
290 | values[j].onError(exception);
291 | }
292 | observer.onError(exception);
293 | }, observer.onCompleted.bind(observer));
294 | try {
295 | for (i = 0, len = plans.length; i < len; i++) {
296 | activePlans.push(plans[i].activate(externalSubscriptions, outObserver, function (activePlan) {
297 | var idx = activePlans.indexOf(activePlan);
298 | activePlans.splice(idx, 1);
299 | if (activePlans.length === 0) {
300 | outObserver.onCompleted();
301 | }
302 | }));
303 | }
304 | } catch (e) {
305 | observableThrow(e).subscribe(observer);
306 | }
307 | group = new CompositeDisposable();
308 | joinValues = externalSubscriptions.getValues();
309 | for (i = 0, len = joinValues.length; i < len; i++) {
310 | joinObserver = joinValues[i];
311 | joinObserver.subscribe();
312 | group.add(joinObserver);
313 | }
314 | return group;
315 | });
316 | };
317 |
318 |
319 | return root;
320 | }));
--------------------------------------------------------------------------------
/lib/rx.joinpatterns.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @preserve Copyright (c) Microsoft Corporation. All rights reserved.
3 | * This code is licensed by Microsoft Corporation under the terms
4 | * of the Microsoft Reference Source License (MS-RSL).
5 | * http://referencesource.microsoft.com/referencesourcelicense.aspx.
6 | */
7 |
8 | (function (root, factory) {
9 | var freeExports = typeof exports == 'object' && exports &&
10 | (typeof root == 'object' && root && root == root.global && (window = root), exports);
11 |
12 | // Because of build optimizers
13 | if (typeof define === 'function' && define.amd) {
14 | define(['rx', 'exports'], function (Rx, exports) {
15 | root.Rx = factory(root, exports, Rx);
16 | return root.Rx;
17 | });
18 | } else if (typeof module == 'object' && module && module.exports == freeExports) {
19 | module.exports = factory(root, module.exports, require('./rx'));
20 | } else {
21 | root.Rx = factory(root, {}, root.Rx);
22 | }
23 | }(this, function (global, exp, root, undefined) {
24 |
25 | // Aliases
26 | var Observable = root.Observable,
27 | observableProto = Observable.prototype,
28 | AnonymousObservable = root.Internals.AnonymousObservable,
29 | observableThrow = Observable.throwException,
30 | observerCreate = root.Observer.create,
31 | SingleAssignmentDisposable = root.SingleAssignmentDisposable,
32 | CompositeDisposable = root.CompositeDisposable,
33 | AbstractObserver = root.Internals.AbstractObserver;
34 |
35 | // Defaults
36 | function defaultComparer(x, y) { return x === y; }
37 | function noop() { }
38 |
39 | // Utilities
40 | var inherits = root.Internals.inherits;
41 | var slice = Array.prototype.slice;
42 | function argsOrArray(args, idx) {
43 | return args.length === 1 && Array.isArray(args[idx]) ?
44 | args[idx] :
45 | slice.call(args);
46 | }
47 |
48 | // TODO: Replace with a real Map once finalized
49 | var Map = (function () {
50 | function Map() {
51 | this.keys = [];
52 | this.values = [];
53 | }
54 |
55 | Map.prototype['delete'] = function (key) {
56 | var i = this.keys.indexOf(key);
57 | if (i !== -1) {
58 | this.keys.splice(i, 1);
59 | this.values.splice(i, 1);
60 | }
61 | return i !== -1;
62 | };
63 |
64 | Map.prototype.get = function (key, fallback) {
65 | var i = this.keys.indexOf(key);
66 | return i !== -1 ? this.values[i] : fallback;
67 | };
68 |
69 | Map.prototype.set = function (key, value) {
70 | var i = this.keys.indexOf(key);
71 | if (i !== -1) {
72 | this.values[i] = value;
73 | }
74 | this.values[this.keys.push(key) - 1] = value;
75 | };
76 |
77 | Map.prototype.size = function () { return this.keys.length; };
78 | Map.prototype.has = function (key) {
79 | return this.keys.indexOf(key) !== -1;
80 | };
81 | Map.prototype.getKeys = function () { return this.keys.slice(0); };
82 | Map.prototype.getValues = function () { return this.values.slice(0); };
83 |
84 | return Map;
85 | }());
86 |
87 | // Pattern
88 | function Pattern(patterns) {
89 | this.patterns = patterns;
90 | }
91 | Pattern.prototype.and = function (other) {
92 | var patterns = this.patterns.slice(0);
93 | patterns.push(other);
94 | return new Pattern(patterns);
95 | };
96 | Pattern.prototype.then = function (selector) {
97 | return new Plan(this, selector);
98 | };
99 |
100 | // Plan
101 | function Plan(expression, selector) {
102 | this.expression = expression;
103 | this.selector = selector;
104 | }
105 | Plan.prototype.activate = function (externalSubscriptions, observer, deactivate) {
106 | var self = this;
107 | var joinObservers = [];
108 | for (var i = 0, len = this.expression.patterns.length; i < len; i++) {
109 | joinObservers.push(planCreateObserver(externalSubscriptions, this.expression.patterns[i], observer.onError.bind(observer)));
110 | }
111 | var activePlan = new ActivePlan(joinObservers, function () {
112 | var result;
113 | try {
114 | result = self.selector.apply(self, arguments);
115 | } catch (exception) {
116 | observer.onError(exception);
117 | return;
118 | }
119 | observer.onNext(result);
120 | }, function () {
121 | for (var j = 0, jlen = joinObservers.length; j < jlen; j++) {
122 | joinObservers[j].removeActivePlan(activePlan);
123 | }
124 | deactivate(activePlan);
125 | });
126 | for (i = 0, len = joinObservers.length; i < len; i++) {
127 | joinObservers[i].addActivePlan(activePlan);
128 | }
129 | return activePlan;
130 | };
131 |
132 | function planCreateObserver(externalSubscriptions, observable, onError) {
133 | var entry = externalSubscriptions.get(observable);
134 | if (!entry) {
135 | var observer = new JoinObserver(observable, onError);
136 | externalSubscriptions.set(observable, observer);
137 | return observer;
138 | }
139 | return entry;
140 | }
141 |
142 | // Active Plan
143 | function ActivePlan(joinObserverArray, onNext, onCompleted) {
144 | var i, joinObserver;
145 | this.joinObserverArray = joinObserverArray;
146 | this.onNext = onNext;
147 | this.onCompleted = onCompleted;
148 | this.joinObservers = new Map();
149 | for (i = 0; i < this.joinObserverArray.length; i++) {
150 | joinObserver = this.joinObserverArray[i];
151 | this.joinObservers.set(joinObserver, joinObserver);
152 | }
153 | }
154 |
155 | ActivePlan.prototype.dequeue = function () {
156 | var values = this.joinObservers.getValues();
157 | for (var i = 0, len = values.length; i < len; i++) {
158 | values[i].queue.shift();
159 | }
160 | };
161 | ActivePlan.prototype.match = function () {
162 | var firstValues, i, len, isCompleted, values, hasValues = true;
163 | for (i = 0, len = this.joinObserverArray.length; i < len; i++) {
164 | if (this.joinObserverArray[i].queue.length === 0) {
165 | hasValues = false;
166 | break;
167 | }
168 | }
169 | if (hasValues) {
170 | firstValues = [];
171 | isCompleted = false;
172 | for (i = 0, len = this.joinObserverArray.length; i < len; i++) {
173 | firstValues.push(this.joinObserverArray[i].queue[0]);
174 | if (this.joinObserverArray[i].queue[0].kind === 'C') {
175 | isCompleted = true;
176 | }
177 | }
178 | if (isCompleted) {
179 | this.onCompleted();
180 | } else {
181 | this.dequeue();
182 | values = [];
183 | for (i = 0; i < firstValues.length; i++) {
184 | values.push(firstValues[i].value);
185 | }
186 | this.onNext.apply(this, values);
187 | }
188 | }
189 | };
190 |
191 | // Join Observer
192 | var JoinObserver = (function () {
193 |
194 | inherits(JoinObserver, AbstractObserver);
195 |
196 | function JoinObserver(source, onError) {
197 | JoinObserver.super_.constructor.call(this);
198 | this.source = source;
199 | this.onError = onError;
200 | this.queue = [];
201 | this.activePlans = [];
202 | this.subscription = new SingleAssignmentDisposable();
203 | this.isDisposed = false;
204 | }
205 |
206 | JoinObserver.prototype.next = function (notification) {
207 | if (!this.isDisposed) {
208 | if (notification.kind === 'E') {
209 | this.onError(notification.exception);
210 | return;
211 | }
212 | this.queue.push(notification);
213 | var activePlans = this.activePlans.slice(0);
214 | for (var i = 0, len = activePlans.length; i < len; i++) {
215 | activePlans[i].match();
216 | }
217 | }
218 | };
219 | JoinObserver.prototype.error = noop;
220 | JoinObserver.prototype.completed = noop;
221 |
222 | JoinObserver.prototype.addActivePlan = function (activePlan) {
223 | this.activePlans.push(activePlan);
224 | };
225 | JoinObserver.prototype.subscribe = function () {
226 | this.subscription.disposable(this.source.materialize().subscribe(this));
227 | };
228 | JoinObserver.prototype.removeActivePlan = function (activePlan) {
229 | var idx = this.activePlans.indexOf(activePlan);
230 | this.activePlans.splice(idx, 1);
231 | if (this.activePlans.length === 0) {
232 | this.dispose();
233 | }
234 | };
235 | JoinObserver.prototype.dispose = function () {
236 | JoinObserver.super_.dispose.call(this);
237 | if (!this.isDisposed) {
238 | this.isDisposed = true;
239 | this.subscription.dispose();
240 | }
241 | };
242 | return JoinObserver;
243 | } ());
244 |
245 | // Observable extensions
246 | observableProto.and = function (right) {
247 | return new Pattern([this, right]);
248 | };
249 | observableProto.then = function (selector) {
250 | return new Pattern([this]).then(selector);
251 | };
252 | Observable.when = function () {
253 | var plans = argsOrArray(arguments, 0);
254 | return new AnonymousObservable(function (observer) {
255 | var activePlans = [],
256 | externalSubscriptions = new Map(),
257 | group,
258 | i, len,
259 | joinObserver,
260 | joinValues,
261 | outObserver;
262 | outObserver = observerCreate(observer.onNext.bind(observer), function (exception) {
263 | var values = externalSubscriptions.getValues();
264 | for (var j = 0, jlen = values.length; j < jlen; j++) {
265 | values[j].onError(exception);
266 | }
267 | observer.onError(exception);
268 | }, observer.onCompleted.bind(observer));
269 | try {
270 | for (i = 0, len = plans.length; i < len; i++) {
271 | activePlans.push(plans[i].activate(externalSubscriptions, outObserver, function (activePlan) {
272 | var idx = activePlans.indexOf(activePlan);
273 | activePlans.splice(idx, 1);
274 | if (activePlans.length === 0) {
275 | outObserver.onCompleted();
276 | }
277 | }));
278 | }
279 | } catch (e) {
280 | observableThrow(e).subscribe(observer);
281 | }
282 | group = new CompositeDisposable();
283 | joinValues = externalSubscriptions.getValues();
284 | for (i = 0, len = joinValues.length; i < len; i++) {
285 | joinObserver = joinValues[i];
286 | joinObserver.subscribe();
287 | group.add(joinObserver);
288 | }
289 | return group;
290 | });
291 | };
292 |
293 | return root;
294 | }));
--------------------------------------------------------------------------------
/lib/rx.joinpatterns.min.js:
--------------------------------------------------------------------------------
1 | /*** @preserve Copyright (c) Microsoft Corporation. All rights reserved.
2 | * This code is licensed by Microsoft Corporation under the terms
3 | * of the MICROSOFT REACTIVE EXTENSIONS FOR JAVASCRIPT AND .NET LIBRARIES License.
4 | * See http://go.microsoft.com/fwlink/?LinkID=220762.
5 | */
6 | (function(e,t){var n=typeof exports=="object"&&exports&&(typeof e=="object"&&e&&e==e.global&&(window=e),exports);typeof define=="function"&&define.amd?define(["rx","exports"],function(n,r){return e.Rx=t(e,r,n),e.Rx}):typeof module=="object"&&module&&module.exports==n?module.exports=t(e,module.exports,require("./rx")):e.Rx=t(e,{},e.Rx)})(this,function(e,t,n,r){function h(e,t){return e===t}function p(){}function m(e,t){return e.length===1&&Array.isArray(e[t])?e[t]:v.call(e)}function y(e){this.patterns=e}function b(e,t){this.expression=e,this.selector=t}function w(e,t,n){var r=e.get(t);if(!r){var i=new S(t,n);return e.set(t,i),i}return r}function E(e,t,n){var r,i;this.joinObserverArray=e,this.onNext=t,this.onCompleted=n,this.joinObservers=new g;for(r=0;r0&&u/v<2;};var k=function(u){for(var v=0;v0&&(o=n.now(),s+=r,s<=o&&(s=o+r)),t.onNext(i++),e(s)})})}function S(e,t){var n=b(e);return new o(function(e){return t.scheduleWithRelative(n,function(){e.onNext(0),e.onCompleted()})})}function x(e,t,n){return e===t?new o(function(e){return n.schedulePeriodicWithState(0,t,function(t){return e.onNext(t),t+1})}):u(function(){return E(n.now()+e,t,n)})}function C(e,t){var n=this;return new o(function(r){var i=!1,s=new p,o=null,u=[],a=!1,f;return f=n.materialize().timestamp(t).subscribe(function(n){var f,l;n.value.kind==="E"?(u=[],u.push(n),o=n.value.exception,l=!a):(u.push({value:n.value,timestamp:n.timestamp+e}),l=!i,i=!0),l&&(o!==null?r.onError(o):(f=new h,s.disposable(f),f.disposable(t.scheduleRecursiveWithRelative(e,function(e){var n,s,f,l;if(o!==null)return;a=!0;do f=null,u.length>0&&u[0].timestamp-t.now()<=0&&(f=u.shift().value),f!==null&&f.accept(r);while(f!==null);l=!1,s=0,u.length>0?(l=!0,s=Math.max(0,u[0].timestamp-t.now())):i=!1,n=o,a=!1,n!==null?r.onError(n):l&&e(s)}))))}),new d(f,s)})}function k(e,t){var n=this;return u(function(){var r=e-t.now();return C.call(n,r,t)})}function L(e,t){return new o(function(n){function o(){s&&(s=!1,n.onNext(i)),r&&n.onCompleted()}var r,i,s;return new d(e.subscribe(function(e){s=!0,i=e},n.onError.bind(n),function(){r=!0}),t.subscribe(o,n.onError.bind(n),o))})}var i=n.Observable,s=i.prototype,o=n.Internals.AnonymousObservable,u=i.defer,a=i.empty,f=i.throwException,l=i.fromArray,c=n.Scheduler.timeout,h=n.SingleAssignmentDisposable,p=n.SerialDisposable,d=n.CompositeDisposable,v=n.RefCountDisposable,m=n.Subject,g=n.Internals.BinaryObserver,y=n.Internals.addRef,b=n.Scheduler.normalize,T=i.interval=function(e,t){return t||(t=c),x(e,e,t)},N=i.timer=function(e,t,n){var i;return n||(n=c),t!==r&&typeof t=="number"?i=t:t!==r&&typeof t=="object"&&(n=t),e instanceof Date&&i===r?w(e.getTime(),n):e instanceof Date&&i!==r?(i=t,E(e.getTime(),i,n)):i===r?S(e,n):x(e,i,n)};return s.delay=function(e,t){return t||(t=c),e instanceof Date?k.call(this,e.getTime(),t):C.call(this,e,t)},s.throttle=function(e,t){t||(t=c);var n=this;return new o(function(r){var i=new p,s=!1,o=0,u,a=null;return u=n.subscribe(function(n){var u,f;s=!0,a=n,o++,u=o,f=new h,i.disposable(f),f.disposable(t.scheduleWithRelative(e,function(){s&&o===u&&r.onNext(a),s=!1}))},function(e){i.dispose(),r.onError(e),s=!1,o++},function(){i.dispose(),s&&r.onNext(a),r.onCompleted(),s=!1,o++}),new d(u,i)})},s.windowWithTime=function(e,t,n){var i=this,s;return t===r&&(s=e),n===r&&(n=c),typeof t=="number"?s=t:typeof t=="object"&&(s=e,n=t),new o(function(t){var r,o,u=s,a=e,f=[],l,c=new p,g=0;return o=new d(c),l=new v(o),r=function(){var e,i,o,p,d;o=new h,c.disposable(o),i=!1,e=!1,a===u?(i=!0,e=!0):a0&&s-i[0].interval>=e)r.onNext(i.shift().value)},r.onError.bind(r),function(){var n=t.now();while(i.length>0&&n-i[0].interval>=e)r.onNext(i.shift().value);r.onCompleted()})})},s.takeLastWithTime=function(e,t,n){return this.takeLastBufferWithTime(e,t).selectMany(function(e){return l(e,n)})},s.takeLastBufferWithTime=function(e,t){var n=this;return t||(t=c),new o(function(r){var i=[];return n.subscribe(function(n){var r=t.now();i.push({interval:r,value:n});while(i.length>0&&r-i[0].interval>=e)i.shift()},r.onError.bind(r),function(){var n=t.now(),s=[];while(i.length>0){var o=i.shift();n-o.interval<=e&&s.push(o.value)}r.onNext(s),r.onCompleted()})})},s.takeWithTime=function(e,t){var n=this;return t||(t=c),new o(function(r){var i=t.scheduleWithRelative(e,function(){r.onCompleted()});return new d(i,n.subscribe(r))})},s.skipWithTime=function(e,t){var n=this;return t||(t=c),new o(function(r){var i=!1,s=t.scheduleWithRelative(e,function(){i=!0}),o=n.subscribe(function(e){i&&r.onNext(e)},r.onError.bind(r),r.onCompleted.bind(r));return new d(s,o)})},s.skipUntilWithTime=function(e,t){t||(t=c);var n=this;return new o(function(r){var i=!1,s=t.scheduleWithAbsolute(e,function(){i=!0}),o=n.subscribe(function(e){i&&r.onNext(e)},r.onError.bind(r),r.onCompleted.bind(r));return new d(s,o)})},s.takeUntilWithTime=function(e,t){t||(t=c);var n=this;return new o(function(r){return new d(t.scheduleWithAbsolute(e,function(){r.onCompleted()}),n.subscribe(r))})},n});
--------------------------------------------------------------------------------
/readme:
--------------------------------------------------------------------------------
1 | !!
2 | !! WARNING: This repository is for teaching purposes ONLY.
3 | !! The software in this repository is COMPLETELY UNSUPPORTED.
4 | !!
5 |
6 | Learn Reactive Extensions for JavaScript
7 |
8 | The Reactive Extensions for JavaScript Koans walk you down the path in order to learn the Reactive Extensions for JavaScript.
9 |
10 | Based on the RxKoans: http://rxkoans.codeplex.com/
--------------------------------------------------------------------------------
/rxkoans.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | Rx Koans
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | test markup, will be hidden
46 |
47 |
48 |
--------------------------------------------------------------------------------