├── .editorconfig
├── .eslintrc.json
├── .gitattributes
├── .gitignore
├── .travis.yml
├── API.md
├── HISTORY.md
├── LICENSE
├── README.md
├── bower.json
├── build-examples.js
├── es
└── index.js
├── examples
├── drag-and-drop
│ ├── build.js
│ ├── index.html
│ └── script.js
├── multiple-clicks
│ ├── build.js
│ ├── index.html
│ ├── node_modules
│ │ ├── flyd-aftersilence
│ │ │ ├── LICENSE
│ │ │ ├── README.md
│ │ │ ├── aftersilence.js
│ │ │ ├── package.json
│ │ │ └── test
│ │ │ │ └── index.js
│ │ └── flyd
│ │ │ ├── .travis.yml
│ │ │ ├── LICENSE
│ │ │ ├── README.md
│ │ │ ├── bower.json
│ │ │ ├── coverage
│ │ │ ├── coverage.json
│ │ │ └── lcov.info
│ │ │ ├── examples
│ │ │ ├── multiple-clicks
│ │ │ │ ├── build.js
│ │ │ │ ├── index.html
│ │ │ │ ├── package.json
│ │ │ │ └── script.js
│ │ │ ├── secret-combination
│ │ │ │ ├── index.html
│ │ │ │ └── script.js
│ │ │ └── sum
│ │ │ │ └── index.html
│ │ │ ├── flyd.js
│ │ │ ├── package.json
│ │ │ ├── perf
│ │ │ ├── perf.js
│ │ │ └── test.js
│ │ │ └── test
│ │ │ └── index.js
│ ├── package.json
│ └── script.js
├── ramda-transducer
│ ├── README.md
│ ├── build.js
│ ├── package.json
│ └── script.js
├── secret-combination
│ ├── build.js
│ ├── index.html
│ ├── node_modules
│ │ ├── flyd-filter
│ │ │ ├── LICENSE
│ │ │ ├── README.md
│ │ │ ├── filter.js
│ │ │ ├── package.json
│ │ │ └── test
│ │ │ │ └── index.js
│ │ ├── flyd-inlast
│ │ │ ├── LICENSE
│ │ │ ├── README.md
│ │ │ ├── inlast.js
│ │ │ ├── package.json
│ │ │ └── test
│ │ │ │ └── index.js
│ │ ├── flyd-lift
│ │ │ ├── LICENSE
│ │ │ ├── README.md
│ │ │ ├── flyd-lift.js
│ │ │ ├── package.json
│ │ │ └── test
│ │ │ │ └── index.js
│ │ ├── flyd-sampleon
│ │ │ ├── LICENSE
│ │ │ ├── README.md
│ │ │ ├── package.json
│ │ │ ├── sampleon.js
│ │ │ └── test
│ │ │ │ └── index.js
│ │ └── flyd
│ │ │ ├── .travis.yml
│ │ │ ├── LICENSE
│ │ │ ├── README.md
│ │ │ ├── bower.json
│ │ │ ├── coverage
│ │ │ ├── coverage.json
│ │ │ └── lcov.info
│ │ │ ├── examples
│ │ │ ├── multiple-clicks
│ │ │ │ ├── build.js
│ │ │ │ ├── index.html
│ │ │ │ ├── package.json
│ │ │ │ └── script.js
│ │ │ ├── secret-combination
│ │ │ │ ├── index.html
│ │ │ │ └── script.js
│ │ │ └── sum
│ │ │ │ └── index.html
│ │ │ ├── flyd.js
│ │ │ ├── package.json
│ │ │ ├── perf
│ │ │ ├── perf.js
│ │ │ └── test.js
│ │ │ └── test
│ │ │ └── index.js
│ ├── package.json
│ └── script.js
├── sum
│ ├── build.js
│ ├── index.html
│ └── script.js
└── who-to-follow
│ ├── build.js
│ ├── index.html
│ ├── package.json
│ └── script.js
├── flyd.js
├── flyd.min.js
├── index.d.ts
├── lib
└── index.js
├── module
├── aftersilence
│ ├── README.md
│ ├── index.js
│ └── test
│ │ └── index.js
├── batchwhen
│ ├── README.md
│ ├── index.js
│ └── test
│ │ └── index.js
├── diff
│ ├── README.md
│ ├── index.js
│ └── test
│ │ └── index.js
├── droprepeats
│ ├── README.md
│ ├── index.js
│ └── test
│ │ └── index.js
├── every
│ ├── README.md
│ ├── index.js
│ └── test
│ │ ├── browsertest
│ │ ├── index.html
│ │ └── script.js
│ │ └── index.js
├── filter
│ ├── README.md
│ ├── index.js
│ └── test
│ │ └── index.js
├── forwardto
│ ├── README.md
│ ├── index.js
│ └── test
│ │ └── index.js
├── inlast
│ ├── README.md
│ ├── index.js
│ └── test
│ │ └── index.js
├── keepwhen
│ ├── README.md
│ ├── index.js
│ └── test
│ │ └── index.js
├── lift
│ ├── README.md
│ ├── index.js
│ └── test
│ │ └── index.js
├── mergeall
│ ├── README.md
│ ├── index.js
│ └── test
│ │ └── index.js
├── obj
│ ├── README.md
│ ├── index.js
│ └── test
│ │ └── index.js
├── previous
│ ├── README.md
│ ├── index.js
│ └── test
│ │ └── index.js
├── sampleon
│ ├── README.md
│ ├── index.js
│ └── test
│ │ └── index.js
├── scanmerge
│ ├── README.md
│ ├── index.js
│ └── test
│ │ └── index.js
├── switchlatest
│ ├── README.md
│ ├── index.js
│ └── test
│ │ └── index.js
└── takeuntil
│ ├── README.md
│ ├── index.js
│ └── test
│ └── index.js
├── package-lock.json
├── package.json
├── perf
├── perf.js
└── run-benchmarks
├── rollup.config.dev.js
├── rollup.config.js
└── test
└── index.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*]
2 | indent_style = space
3 | indent_size = 2
4 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "node": true,
4 | "mocha": true
5 | },
6 | "globals": {
7 | "Symbol": true
8 | },
9 | "rules": {
10 | "no-eval": 2,
11 | "eqeqeq": 0,
12 | "no-eq-null": 0,
13 | "new-cap": 0,
14 | "no-plusplus": 0,
15 | "no-undef": 2,
16 | "no-unused-vars": 2,
17 | "brace-style": [
18 | 2,
19 | "1tbs",
20 | {
21 | "allowSingleLine": true
22 | }
23 | ],
24 | "no-mixed-spaces-and-tabs": 2,
25 | "no-multi-str": 2,
26 | "one-var": [
27 | 2,
28 | {
29 | "uninitialized": "always",
30 | "initialized": "never"
31 | }
32 | ],
33 | "quote-props": [
34 | 2,
35 | "as-needed",
36 | {
37 | "keywords": true
38 | }
39 | ],
40 | "key-spacing": 0,
41 | "space-unary-ops": 0,
42 | "no-spaced-func": 2,
43 | "space-before-function-paren": [
44 | 2,
45 | "never"
46 | ],
47 | "spaced-comment": [
48 | 2,
49 | "always"
50 | ],
51 | "array-bracket-spacing": [
52 | 2,
53 | "never",
54 | {
55 | "singleValue": false
56 | }
57 | ],
58 | "space-in-parens": [
59 | 2,
60 | "never"
61 | ],
62 | "no-trailing-spaces": 2,
63 | "yoda": [
64 | 2,
65 | "never"
66 | ],
67 | "comma-style": [
68 | 2,
69 | "last"
70 | ],
71 | "curly": [
72 | 2,
73 | "multi-line"
74 | ],
75 | "dot-notation": 0,
76 | "eol-last": 2,
77 | "wrap-iife": [
78 | 2,
79 | "outside"
80 | ],
81 | "space-infix-ops": 2,
82 | "space-return-throw-case": 0,
83 | "keyword-spacing": ["error", {"after": true}],
84 | "lines-around-comment": 0,
85 | "space-before-blocks": [
86 | 2,
87 | "always"
88 | ],
89 | "indent": [
90 | 2,
91 | 2,
92 | {
93 | "SwitchCase": 1
94 | }
95 | ],
96 | "quotes": [
97 | 2,
98 | "single",
99 | "avoid-escape"
100 | ],
101 | "comma-dangle": [
102 | 2,
103 | "never"
104 | ],
105 | "no-debugger": 2,
106 | "no-dupe-args": 2,
107 | "no-dupe-keys": 2,
108 | "no-duplicate-case": 2,
109 | "no-extra-semi": 2,
110 | "no-unreachable": 2
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * eol=lf
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ### Node template
2 | # Logs
3 | logs
4 | *.log
5 |
6 | # Dependency directory
7 | node_modules
8 | bower_components
9 |
10 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "6"
4 | - "7"
5 | - "8"
6 | after_success:
7 | - "npm run post-to-coveralls-io"
8 |
--------------------------------------------------------------------------------
/API.md:
--------------------------------------------------------------------------------
1 | ## `flyd`
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | ## `flyd.combine`
11 |
12 | Create a new dependent stream
13 |
14 | __Signature__: `(...Stream * -> Stream b -> b) -> [Stream *] -> Stream b`
15 |
16 | ### Parameters
17 |
18 | * `fn` **`Function`** the function used to combine the streams
19 | * `dependencies` **`Array<stream>`** the streams that this one depends on
20 |
21 |
22 | ### Examples
23 |
24 | ```js
25 | var n1 = flyd.stream(0);
26 | var n2 = flyd.stream(0);
27 | var max = flyd.combine(function(n1, n2, self, changed) {
28 | return n1() > n2() ? n1() : n2();
29 | }, [n1, n2]);
30 | ```
31 |
32 | Returns `stream` the dependent stream
33 |
34 |
35 | ## `flyd.curryN`
36 |
37 | Returns `fn` curried to `n`. Use this function to curry functions exposed by
38 | modules for Flyd.
39 |
40 | ### Parameters
41 |
42 | * `arity` **`Integer`** the function arity
43 | * `fn` **`Function`** the function to curry
44 |
45 |
46 | ### Examples
47 |
48 | ```js
49 | function add(x, y) { return x + y; };
50 | var a = flyd.curryN(2, add);
51 | a(2)(4) // => 6
52 | ```
53 |
54 | Returns `Function` the curried function
55 |
56 |
57 | ## `flyd.endsOn`
58 |
59 | Changes which `endsStream` should trigger the ending of `s`.
60 |
61 | __Signature__: `Stream a -> Stream b -> Stream b`
62 |
63 | ### Parameters
64 |
65 | * `endStream` **`stream`** the stream to trigger the ending
66 | * `stream` **`stream`** the stream to be ended by the endStream
67 | * `the` **`stream`** stream modified to be ended by endStream
68 |
69 |
70 | ### Examples
71 |
72 | ```js
73 | var n = flyd.stream(1);
74 | var killer = flyd.stream();
75 | // `double` ends when `n` ends or when `killer` emits any value
76 | var double = flyd.endsOn(flyd.merge(n.end, killer), flyd.combine(function(n) {
77 | return 2 * n();
78 | }, [n]);
79 | ```
80 |
81 |
82 |
83 | ## `flyd.immediate`
84 |
85 | Invokes the body (the function to calculate the value) of a dependent stream
86 |
87 | By default the body of a dependent stream is only called when all the streams
88 | upon which it depends has a value. `immediate` can circumvent this behaviour.
89 | It immediately invokes the body of a dependent stream.
90 |
91 | __Signature__: `Stream a -> Stream a`
92 |
93 | ### Parameters
94 |
95 | * `stream` **`stream`** the dependent stream
96 |
97 |
98 | ### Examples
99 |
100 | ```js
101 | var s = flyd.stream();
102 | var hasItems = flyd.immediate(flyd.combine(function(s) {
103 | return s() !== undefined && s().length > 0;
104 | }, [s]);
105 | console.log(hasItems()); // logs `false`. Had `immediate` not been
106 | // used `hasItems()` would've returned `undefined`
107 | s([1]);
108 | console.log(hasItems()); // logs `true`.
109 | s([]);
110 | console.log(hasItems()); // logs `false`.
111 | ```
112 |
113 | Returns `stream` the same stream
114 |
115 |
116 | ## `flyd.isStream`
117 |
118 | Returns `true` if the supplied argument is a Flyd stream and `false` otherwise.
119 |
120 | __Signature__: `* -> Boolean`
121 |
122 | ### Parameters
123 |
124 | * `value` **`Any`** the value to test
125 |
126 |
127 | ### Examples
128 |
129 | ```js
130 | var s = flyd.stream(1);
131 | var n = 1;
132 | flyd.isStream(s); //=> true
133 | flyd.isStream(n); //=> false
134 | ```
135 |
136 | Returns `Boolean` `true` if is a Flyd streamn, `false` otherwise
137 |
138 |
139 | ## `flyd.map`
140 |
141 | Map a stream
142 |
143 | Returns a new stream consisting of every value from `s` passed through
144 | `fn`. I.e. `map` creates a new stream that listens to `s` and
145 | applies `fn` to every new value.
146 | __Signature__: `(a -> result) -> Stream a -> Stream result`
147 |
148 | ### Parameters
149 |
150 | * `fn` **`Function`** the function that produces the elements of the new stream
151 | * `stream` **`stream`** the stream to map
152 |
153 |
154 | ### Examples
155 |
156 | ```js
157 | var numbers = flyd.stream(0);
158 | var squaredNumbers = flyd.map(function(n) { return n*n; }, numbers);
159 | ```
160 |
161 | Returns `stream` a new stream with the mapped values
162 |
163 |
164 | ## `flyd.merge`
165 |
166 | Creates a new stream down which all values from both `stream1` and `stream2`
167 | will be sent.
168 |
169 | __Signature__: `Stream a -> Stream a -> Stream a`
170 |
171 | ### Parameters
172 |
173 | * `source1` **`stream`** one stream to be merged
174 | * `source2` **`stream`** the other stream to be merged
175 |
176 |
177 | ### Examples
178 |
179 | ```js
180 | var btn1Clicks = flyd.stream();
181 | button1Elm.addEventListener(btn1Clicks);
182 | var btn2Clicks = flyd.stream();
183 | button2Elm.addEventListener(btn2Clicks);
184 | var allClicks = flyd.merge(btn1Clicks, btn2Clicks);
185 | ```
186 |
187 | Returns `stream` a stream with the values from both sources
188 |
189 |
190 | ## `flyd.on`
191 |
192 | Listen to stream events
193 |
194 | Similair to `map` except that the returned stream is empty. Use `on` for doing
195 | side effects in reaction to stream changes. Use the returned stream only if you
196 | need to manually end it.
197 |
198 | __Signature__: `(a -> result) -> Stream a -> Stream undefined`
199 |
200 | ### Parameters
201 |
202 | * `cb` **`Function`** the callback
203 | * `stream` **`stream`** the stream
204 |
205 |
206 |
207 | Returns `stream` an empty stream (can be ended)
208 |
209 |
210 | ## `flyd.scan`
211 |
212 | Creates a new stream with the results of calling the function on every incoming
213 | stream with and accumulator and the incoming value.
214 |
215 | __Signature__: `(a -> b -> a) -> a -> Stream b -> Stream a`
216 |
217 | ### Parameters
218 |
219 | * `fn` **`Function`** the function to call
220 | * `val` **`Any`** the initial value of the accumulator
221 | * `stream` **`stream`** the stream source
222 |
223 |
224 | ### Examples
225 |
226 | ```js
227 | var numbers = flyd.stream();
228 | var sum = flyd.scan(function(sum, n) { return sum+n; }, 0, numbers);
229 | numbers(2)(3)(5);
230 | sum(); // 10
231 | ```
232 |
233 | Returns `stream` the new stream
234 |
235 |
236 | ## `flyd.stream`
237 |
238 | Creates a new stream
239 |
240 | __Signature__: `a -> Stream a`
241 |
242 | ### Parameters
243 |
244 | * `initialValue` **`Any`** (Optional) the initial value of the stream
245 |
246 |
247 | ### Examples
248 |
249 | ```js
250 | var n = flyd.stream(1); // Stream with initial value `1`
251 | var s = flyd.stream(); // Stream with no initial value
252 | ```
253 |
254 | Returns `stream` the stream
255 |
256 |
257 | ## `flyd.transduce`
258 |
259 | Creates a new stream resulting from applying `transducer` to `stream`.
260 |
261 | __Signature__: `Transducer -> Stream a -> Stream b`
262 |
263 | ### Parameters
264 |
265 | * `xform` **`Transducer`** the transducer transformation
266 | * `source` **`stream`** the stream source
267 |
268 |
269 | ### Examples
270 |
271 | ```js
272 | var t = require('transducers.js');
273 |
274 | var results = [];
275 | var s1 = flyd.stream();
276 | var tx = t.compose(t.map(function(x) { return x * 2; }), t.dedupe());
277 | var s2 = flyd.transduce(tx, s1);
278 | flyd.combine(function(s2) { results.push(s2()); }, [s2]);
279 | s1(1)(1)(2)(3)(3)(3)(4);
280 | results; // => [2, 4, 6, 8]
281 | ```
282 |
283 | Returns `stream` the new stream
284 |
285 |
286 | ## `stream.ap`
287 |
288 | Returns a new stream which is the result of applying the
289 | functions from `this` stream to the values in `stream` parameter.
290 |
291 | `this` stream must be a stream of functions.
292 |
293 | _Note:_ This function is included in order to support the fantasy land
294 | specification.
295 |
296 | __Signature__: Called bound to `Stream (a -> b)`: `a -> Stream b`
297 |
298 | ### Parameters
299 |
300 | * `stream` **`stream`** the values stream
301 |
302 |
303 | ### Examples
304 |
305 | ```js
306 | var add = flyd.curryN(2, function(x, y) { return x + y; });
307 | var numbers1 = flyd.stream();
308 | var numbers2 = flyd.stream();
309 | var addToNumbers1 = flyd.map(add, numbers1);
310 | var added = addToNumbers1.ap(numbers2);
311 | ```
312 |
313 | Returns `stream` a new stram with the functions applied to values
314 |
315 |
316 | ## `stream.end`
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 | ## `stream.map`
326 |
327 | Returns a new stream identical to the original except every
328 | value will be passed through `f`.
329 |
330 | _Note:_ This function is included in order to support the fantasy land
331 | specification.
332 |
333 | __Signature__: Called bound to `Stream a`: `(a -> b) -> Stream b`
334 |
335 | ### Parameters
336 |
337 | * `function` **`Function`** the function to apply
338 |
339 |
340 | ### Examples
341 |
342 | ```js
343 | var numbers = flyd.stream(0);
344 | var squaredNumbers = numbers.map(function(n) { return n*n; });
345 | ```
346 |
347 | Returns `stream` a new stream with the values mapped
348 |
349 |
350 | ## `stream.of`
351 |
352 |
353 |
354 | ### Parameters
355 |
356 | * `value` **`Any`** the initial value
357 |
358 |
359 | ### Examples
360 |
361 | ```js
362 | var n = flyd.stream(1);
363 | var m = n.of(1);
364 | ```
365 |
366 | Returns `stream` the new stream
367 |
368 |
369 | ## `stream.toString`
370 |
371 | Get a human readable view of a stream
372 |
373 |
374 |
375 |
376 | Returns `String` the stream string representation
377 |
--------------------------------------------------------------------------------
/HISTORY.md:
--------------------------------------------------------------------------------
1 | ### v.0.2.0
2 |
3 | * Fixed bug in `flyd/module/scanmerge`
4 | * Removed dependent stream syntax `flyd.stream([streams], combinFn)` in
5 | favor of the function `combine`. `flyd.stream` is now only used for
6 | creating top level streams.
7 | * Added `flyd.combine`
8 |
9 | ```
10 | flyd.combine((depA, depB, ..., depN, self, changed) => *, [depA, depB, ..., depN]);
11 | ```
12 |
13 | `self` is the combined stream and `changed` is an array of the streams
14 | that have changed.
15 |
16 | To update replace
17 |
18 | ```javascript
19 | var a = flyd.stream();
20 | var b = flyd.stream();
21 | var sum = flyd.stream([a, b], function() {
22 | return a() + b();
23 | }
24 | ```
25 |
26 | with
27 |
28 | ```
29 | var b = flyd.stream(0);
30 | var a = flyd.stream(0);
31 | var sum = flyd.combine(function(a, b) {
32 | return a + b;
33 | }, [a, b]);
34 | ```
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Simon Friis Vindum
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "flyd",
3 | "main": "flyd.js",
4 | "version": "0.1.14",
5 | "homepage": "https://github.com/paldepind/flyd",
6 | "authors": [
7 | "Simon Friis Vindum"
8 | ],
9 | "description": "The less is more, modular functional reactive programming library",
10 | "moduleType": [
11 | "amd",
12 | "globals",
13 | "node"
14 | ],
15 | "keywords": [
16 | "functional",
17 | "reactive",
18 | "modular"
19 | ],
20 | "license": "MIT",
21 | "ignore": [
22 | "**/.*",
23 | "node_modules",
24 | "bower_components",
25 | "test",
26 | "tests"
27 | ]
28 | }
29 |
--------------------------------------------------------------------------------
/build-examples.js:
--------------------------------------------------------------------------------
1 | const rollup = require('rollup');
2 | const resolve = require('rollup-plugin-node-resolve');
3 | const commonjs = require('rollup-plugin-commonjs');
4 |
5 | const fs = require('fs');
6 | const path = require('path');
7 |
8 | async function build(example) {
9 | console.log('Building ' + example);
10 |
11 | const inputOptions = {
12 | input: path.resolve(`./examples/${example}/script.js`),
13 | plugins: [
14 | resolve(),
15 | commonjs()
16 | ]
17 | }
18 | const outputOptions = {
19 | format: 'iife',
20 | file: path.resolve(`./examples/${example}/build.js`),
21 | name: example.replace(/-/g, ''),
22 | }
23 | // create a bundle
24 | const bundle = await rollup.rollup(inputOptions);
25 |
26 | // write bundle
27 | await bundle.write(outputOptions);
28 |
29 | console.log('Built ' + example);
30 | }
31 |
32 | const examples = fs.readdirSync('./examples');
33 |
34 | Promise.all(examples.map(build))
35 | .then(()=> console.log('Success!'))
36 | .catch(err => {
37 | console.error('Failed!');
38 | console.error(err);
39 | process.exit(1);
40 | });
--------------------------------------------------------------------------------
/examples/drag-and-drop/index.html:
--------------------------------------------------------------------------------
1 | <!DOCTYPE html>
2 | <html>
3 | <head>
4 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 | <title>Multiple clicks</title>
6 | <link href='http://fonts.googleapis.com/css?family=Inconsolata|Josefin+Sans:400,300' rel='stylesheet' type='text/css'>
7 | <script type="text/javascript" src="build.js"></script>
8 | <style>
9 | #drag {
10 | width: 200px;
11 | height: 200px;
12 | background-color: purple;
13 | position: absolute;
14 | cursor: move;
15 | color: white;
16 | border-radius: 4px;
17 | padding: 8px;
18 | }
19 | </style>
20 | </head>
21 | <body>
22 | <div id="drag">
23 | <span id="msg">Drag Me</span>
24 | </div>
25 | <p>
26 | <a href="https://github.com/paldepind/flyd/blob/master/examples/drag-and-drop/script.js">See the source code</a>
27 | </p>
28 | </body>
29 | </html>
30 |
--------------------------------------------------------------------------------
/examples/drag-and-drop/script.js:
--------------------------------------------------------------------------------
1 | var flyd = require('../../lib');
2 | var takeUntil = require('../../module/takeuntil');
3 |
4 | document.addEventListener('DOMContentLoaded', function() {
5 | var dragElm = document.getElementById('drag');
6 |
7 | var mousedown = flyd.stream();
8 | var mousemove = flyd.stream();
9 | var mouseup = flyd.stream();
10 |
11 | dragElm.addEventListener('mousedown', mousedown);
12 | document.addEventListener('mousemove', mousemove);
13 | document.addEventListener('mouseup', mouseup);
14 |
15 | var mousedrag = flyd.chain(function(md) {
16 | var startX = md.offsetX, startY = md.offsetY;
17 |
18 | return takeUntil(flyd.map(function(mm) {
19 | mm.preventDefault();
20 |
21 | return {
22 | left: mm.clientX - startX,
23 | top: mm.clientY - startY
24 | };
25 | }, mousemove), mouseup);
26 | }, mousedown);
27 |
28 | flyd.on(function(pos) {
29 | dragElm.style.top = pos.top + 'px';
30 | dragElm.style.left = pos.left + 'px';
31 | }, mousedrag);
32 | });
33 |
--------------------------------------------------------------------------------
/examples/multiple-clicks/index.html:
--------------------------------------------------------------------------------
1 | <!DOCTYPE html>
2 | <html>
3 | <head>
4 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 | <title>Multiple clicks</title>
6 | <link href='http://fonts.googleapis.com/css?family=Inconsolata|Josefin+Sans:400,300' rel='stylesheet' type='text/css'>
7 | <script type="text/javascript" src="build.js"></script>
8 | </head>
9 | <body>
10 | <button id="btn">Click me</button>
11 | <span id="msg">Double click it</span>
12 | <p>
13 | <a href="https://github.com/paldepind/flyd/blob/master/examples/multiple-clicks/script.js">See the source code</a>
14 | </p>
15 | </body>
16 | </html>
17 |
--------------------------------------------------------------------------------
/examples/multiple-clicks/node_modules/flyd-aftersilence/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Simon Friis Vindum
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/examples/multiple-clicks/node_modules/flyd-aftersilence/README.md:
--------------------------------------------------------------------------------
1 | # flyd-aftersilence
2 | Buffers values from a source stream in an array and emits it after a
3 | specified duration of silience from the source stream.
4 |
5 | __Signature__
6 |
7 | `Stream a -> Stream b
8 |
9 | __Example__
10 |
11 | ```javascript
12 | afterSilence(function(values) {
13 | console.log('You achieved a combo of + values.length + '!');
14 | }, afterSilence(1000, birdsShot);
15 | ```
16 |
17 | ```javascript
18 | afterSilence(function(values) {
19 | console.log('You typed: "' + values.join('') + '" without any pauses');
20 | }, afterSilence(300, characterTyped);
21 | ```
22 |
--------------------------------------------------------------------------------
/examples/multiple-clicks/node_modules/flyd-aftersilence/aftersilence.js:
--------------------------------------------------------------------------------
1 | var flyd = require('flyd');
2 |
3 | module.exports = function(dur, s) {
4 | var scheduled;
5 | var buffer = [];
6 | var ns = flyd.stream();
7 | flyd.map(function(v) {
8 | buffer.push(v);
9 | clearTimeout(scheduled);
10 | scheduled = setTimeout(function() {
11 | ns(buffer);
12 | buffer = [];
13 | }, dur);
14 | }, s);
15 | return ns;
16 | };
17 |
--------------------------------------------------------------------------------
/examples/multiple-clicks/node_modules/flyd-aftersilence/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "flyd-aftersilence",
3 | "version": "0.0.2",
4 | "description": "Flyd module that buffers values from a stream and emits them after a specified duration of silience",
5 | "main": "aftersilence.js",
6 | "directories": {
7 | "test": "test"
8 | },
9 | "scripts": {
10 | "test": "mocha"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "https://github.com/paldepind/flyd-aftersilence.git"
15 | },
16 | "keywords": [
17 | "flyd",
18 | "buffer",
19 | "time",
20 | "silence",
21 | "delay",
22 | "group"
23 | ],
24 | "author": {
25 | "name": "Simon Friis Vindum"
26 | },
27 | "license": "MIT",
28 | "bugs": {
29 | "url": "https://github.com/paldepind/flyd-aftersilence/issues"
30 | },
31 | "homepage": "https://github.com/paldepind/flyd-aftersilence",
32 | "dependencies": {
33 | "flyd": "0.0.x"
34 | },
35 | "readme": "# flyd-aftersilence\nBuffers values from a source stream in an array and emits it after a\nspecified duration of silience from the source stream.\n\n__Signature__\n\n`Stream a -> Stream b\n\n__Example__\n\n```javascript\nafterSilence(function(values) {\n console.log('You achieved a combo of + values.length + '!');\n}, afterSilence(1000, birdsShot);\n```\n\n```javascript\nafterSilence(function(values) {\n console.log('You typed: \"' + values.join('') + '\" without any pauses');\n}, afterSilence(300, characterTyped);\n```\n",
36 | "readmeFilename": "README.md",
37 | "gitHead": "08d1c025ddb3d45745e436587ab763180646e92c",
38 | "_id": "flyd-aftersilence@0.0.2",
39 | "_shasum": "f480d60ac20b7a266b8db72f96f3929c289798bc",
40 | "_from": "flyd-aftersilence@>=0.0.0 <0.1.0"
41 | }
42 |
--------------------------------------------------------------------------------
/examples/multiple-clicks/node_modules/flyd-aftersilence/test/index.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var flyd = require('flyd');
3 | var stream = flyd.stream;
4 |
5 | var afterSilence = require('../aftersilence.js');
6 |
7 | // KISS way of testing time dependent code :)
8 |
9 | describe('afterSilence', function() {
10 | it('correctly buffers values', function(done) {
11 | var result = [];
12 | var i = 0;
13 | var s1 = stream();
14 | var push = function() {
15 | s1(i++);
16 | };
17 | var s2 = afterSilence(50, s1);
18 | flyd.map(function(vs) {
19 | result.push(vs);
20 | }, s2);
21 | setTimeout(push, 20);
22 | setTimeout(push, 30);
23 | setTimeout(push, 40);
24 | setTimeout(push, 95);
25 | setTimeout(push, 100);
26 | setTimeout(push, 110);
27 | setTimeout(push, 120);
28 | setTimeout(push, 175);
29 | setTimeout(function() {
30 | assert.deepEqual(result, [
31 | [0, 1, 2],
32 | [3, 4, 5, 6],
33 | [7],
34 | ]);
35 | done();
36 | }, 240);
37 | });
38 | it('only emits values after specified silence', function(done) {
39 | var result = [];
40 | var i = 0;
41 | var s1 = stream();
42 | var push = function() {
43 | s1(i++);
44 | };
45 | var s2 = afterSilence(20, s1);
46 | flyd.map(function(vs) {
47 | result.push(vs);
48 | }, s2);
49 | setTimeout(push, 10);
50 | setTimeout(push, 20);
51 | setTimeout(push, 30);
52 | setTimeout(push, 40);
53 | setTimeout(function() {
54 | assert.equal(result.length, 0);
55 | }, 50);
56 | setTimeout(function() {
57 | assert.deepEqual(result, [[0, 1, 2, 3]]);
58 | done();
59 | }, 65);
60 | });
61 | });
62 |
--------------------------------------------------------------------------------
/examples/multiple-clicks/node_modules/flyd/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "0.12"
4 | - "0.10"
5 | - "iojs"
6 | after_success:
7 | - ./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage
8 |
--------------------------------------------------------------------------------
/examples/multiple-clicks/node_modules/flyd/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Simon Friis Vindum
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/examples/multiple-clicks/node_modules/flyd/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "flyd",
3 | "main": "flyd.js",
4 | "version": "0.0.1",
5 | "homepage": "https://github.com/paldepind/flyd",
6 | "authors": [
7 | "Simon Friis Vindum"
8 | ],
9 | "description": "The less is more, modular functional reactive programming library",
10 | "moduleType": [
11 | "amd",
12 | "globals",
13 | "node"
14 | ],
15 | "keywords": [
16 | "functional",
17 | "reactive",
18 | "modular"
19 | ],
20 | "license": "MIT",
21 | "ignore": [
22 | "**/.*",
23 | "node_modules",
24 | "bower_components",
25 | "test",
26 | "tests"
27 | ]
28 | }
29 |
--------------------------------------------------------------------------------
/examples/multiple-clicks/node_modules/flyd/coverage/lcov.info:
--------------------------------------------------------------------------------
1 | TN:
2 | SF:/home/simon/projects/flyd/flyd.js
3 | FN:1,(anonymous_1)
4 | FN:9,(anonymous_2)
5 | FN:13,isFunction
6 | FN:17,isUndefined
7 | FN:27,flushQueue
8 | FN:35,addDependency
9 | FN:42,checkCirc
10 | FN:48,removeListener
11 | FN:54,map
12 | FN:55,(anonymous_10)
13 | FN:58,reduce
14 | FN:59,(anonymous_12)
15 | FN:64,merge
16 | FN:65,(anonymous_14)
17 | FN:75,ap
18 | FN:77,(anonymous_16)
19 | FN:80,of
20 | FN:84,initialDepsNotMet
21 | FN:86,(anonymous_19)
22 | FN:94,updateStream
23 | FN:103,destroyStream
24 | FN:112,stream
25 | FN:113,s
26 | FN:124,(anonymous_24)
27 | FN:157,(anonymous_25)
28 | FN:168,transduce
29 | FN:170,(anonymous_27)
30 | FN:175,StreamTransformer
31 | FN:176,(anonymous_29)
32 | FN:177,(anonymous_30)
33 | FN:178,(anonymous_31)
34 | FNF:31
35 | FNH:29
36 | FNDA:1,(anonymous_1)
37 | FNDA:1,(anonymous_2)
38 | FNDA:336,isFunction
39 | FNDA:646,isUndefined
40 | FNDA:152,flushQueue
41 | FNDA:212,addDependency
42 | FNDA:17,checkCirc
43 | FNDA:2,removeListener
44 | FNDA:7,map
45 | FNDA:14,(anonymous_10)
46 | FNDA:1,reduce
47 | FNDA:4,(anonymous_12)
48 | FNDA:1,merge
49 | FNDA:8,(anonymous_14)
50 | FNDA:9,ap
51 | FNDA:21,(anonymous_16)
52 | FNDA:7,of
53 | FNDA:167,initialDepsNotMet
54 | FNDA:37,(anonymous_19)
55 | FNDA:167,updateStream
56 | FNDA:2,destroyStream
57 | FNDA:114,stream
58 | FNDA:537,s
59 | FNDA:109,(anonymous_24)
60 | FNDA:22,(anonymous_25)
61 | FNDA:3,transduce
62 | FNDA:15,(anonymous_27)
63 | FNDA:3,StreamTransformer
64 | FNDA:0,(anonymous_29)
65 | FNDA:0,(anonymous_30)
66 | FNDA:10,(anonymous_31)
67 | DA:1,1
68 | DA:2,1
69 | DA:3,0
70 | DA:4,1
71 | DA:5,1
72 | DA:7,0
73 | DA:13,1
74 | DA:14,336
75 | DA:17,1
76 | DA:18,646
77 | DA:22,1
78 | DA:23,1
79 | DA:25,1
80 | DA:27,1
81 | DA:28,152
82 | DA:29,15
83 | DA:30,5
84 | DA:35,1
85 | DA:36,212
86 | DA:37,69
87 | DA:38,69
88 | DA:42,1
89 | DA:43,17
90 | DA:44,2
91 | DA:48,1
92 | DA:49,2
93 | DA:50,2
94 | DA:51,2
95 | DA:54,1
96 | DA:55,14
97 | DA:58,1
98 | DA:59,1
99 | DA:60,4
100 | DA:64,1
101 | DA:65,1
102 | DA:66,8
103 | DA:67,8
104 | DA:69,1
105 | DA:70,1
106 | DA:75,1
107 | DA:76,9
108 | DA:77,21
109 | DA:80,1
110 | DA:81,7
111 | DA:84,1
112 | DA:85,167
113 | DA:86,34
114 | DA:87,37
115 | DA:89,34
116 | DA:91,167
117 | DA:94,1
118 | DA:95,167
119 | DA:96,154
120 | DA:97,154
121 | DA:98,152
122 | DA:99,152
123 | DA:100,152
124 | DA:103,1
125 | DA:104,2
126 | DA:105,1
127 | DA:107,1
128 | DA:108,3
129 | DA:112,1
130 | DA:113,1
131 | DA:114,537
132 | DA:115,222
133 | DA:116,2
134 | DA:117,2
135 | DA:119,220
136 | DA:120,220
137 | DA:121,17
138 | DA:122,15
139 | DA:124,203
140 | DA:126,218
141 | DA:128,315
142 | DA:129,190
143 | DA:131,315
144 | DA:134,114
145 | DA:135,114
146 | DA:136,114
147 | DA:137,114
148 | DA:138,114
149 | DA:139,114
150 | DA:140,114
151 | DA:142,114
152 | DA:143,114
153 | DA:144,114
154 | DA:145,114
155 | DA:147,114
156 | DA:148,21
157 | DA:149,21
158 | DA:150,21
159 | DA:151,8
160 | DA:154,114
161 | DA:155,53
162 | DA:156,53
163 | DA:157,21
164 | DA:158,22
165 | DA:161,53
166 | DA:163,61
167 | DA:165,112
168 | DA:168,1
169 | DA:169,3
170 | DA:170,3
171 | DA:171,15
172 | DA:175,1
173 | DA:176,1
174 | DA:177,1
175 | DA:178,10
176 | DA:180,1
177 | LF:110
178 | LH:108
179 | BRDA:2,1,0,0
180 | BRDA:2,1,1,1
181 | BRDA:2,2,0,1
182 | BRDA:2,2,1,0
183 | BRDA:4,3,0,1
184 | BRDA:4,3,1,0
185 | BRDA:14,4,0,336
186 | BRDA:14,4,1,90
187 | BRDA:14,4,2,90
188 | BRDA:14,4,3,55
189 | BRDA:36,5,0,69
190 | BRDA:36,5,1,143
191 | BRDA:43,6,0,2
192 | BRDA:43,6,1,15
193 | BRDA:67,7,0,7
194 | BRDA:67,7,1,1
195 | BRDA:70,8,0,1
196 | BRDA:70,8,1,0
197 | BRDA:85,9,0,34
198 | BRDA:85,9,1,133
199 | BRDA:89,10,0,21
200 | BRDA:89,10,1,13
201 | BRDA:95,11,0,13
202 | BRDA:95,11,1,154
203 | BRDA:99,12,0,110
204 | BRDA:99,12,1,42
205 | BRDA:104,13,0,1
206 | BRDA:104,13,1,1
207 | BRDA:108,14,0,2
208 | BRDA:108,14,1,1
209 | BRDA:114,15,0,222
210 | BRDA:114,15,1,315
211 | BRDA:115,16,0,2
212 | BRDA:115,16,1,220
213 | BRDA:115,17,0,222
214 | BRDA:115,17,1,222
215 | BRDA:120,18,0,17
216 | BRDA:120,18,1,203
217 | BRDA:128,19,0,190
218 | BRDA:128,19,1,125
219 | BRDA:128,20,0,315
220 | BRDA:128,20,1,216
221 | BRDA:147,21,0,21
222 | BRDA:147,21,1,93
223 | BRDA:150,22,0,8
224 | BRDA:150,22,1,13
225 | BRDA:154,23,0,53
226 | BRDA:154,23,1,61
227 | BRDA:156,24,0,21
228 | BRDA:156,24,1,32
229 | BRF:50
230 | BRH:46
231 | end_of_record
232 |
--------------------------------------------------------------------------------
/examples/multiple-clicks/node_modules/flyd/examples/multiple-clicks/index.html:
--------------------------------------------------------------------------------
1 | <!DOCTYPE html>
2 | <html>
3 | <head>
4 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 | <title>Multiple clicks</title>
6 | <link href='http://fonts.googleapis.com/css?family=Inconsolata|Josefin+Sans:400,300' rel='stylesheet' type='text/css'>
7 | <script type="text/javascript" src="build.js"></script>
8 | </head>
9 | <body>
10 | <button id="btn">Click me</button>
11 | <span id="msg">Double click it</span>
12 | <p>
13 | <a href="https://github.com/paldepind/flyd/blob/master/examples/multiple-clicks/script.js">See the source code</a>
14 | </p>
15 | </body>
16 | </html>
17 |
--------------------------------------------------------------------------------
/examples/multiple-clicks/node_modules/flyd/examples/multiple-clicks/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "multiple-clicks",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": ".build.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "Simon Friis Vindum",
10 | "license": "MIT",
11 | "dependencies": {
12 | "flyd": "0.0.x",
13 | "flyd-aftersilence": "0.0.x"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/examples/multiple-clicks/node_modules/flyd/examples/multiple-clicks/script.js:
--------------------------------------------------------------------------------
1 | var flyd = require('flyd');
2 | var afterSilence = require('flyd-aftersilence');
3 |
4 | document.addEventListener('DOMContentLoaded', function() {
5 | var btnElm = document.getElementById('btn');
6 | var msgElm = document.getElementById('msg');
7 |
8 | var clickStream = flyd.stream();
9 | btnElm.addEventListener('click', clickStream);
10 |
11 | var groupedClicks = afterSilence(250, clickStream);
12 | var nrStream = flyd.map(function(clicks) { return clicks.length; }, groupedClicks);
13 |
14 | flyd.map(function(nr) {
15 | msgElm.textContent = nr === 1 ? 'click' : nr + ' clicks';
16 | }, nrStream);
17 |
18 | flyd.map(function(nr) {
19 | msgElm.textContent = '';
20 | }, afterSilence(1000, nrStream));
21 | });
22 |
--------------------------------------------------------------------------------
/examples/multiple-clicks/node_modules/flyd/examples/secret-combination/index.html:
--------------------------------------------------------------------------------
1 | <!DOCTYPE html>
2 | <html>
3 | <head>
4 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 | <title>Secret combination</title>
6 | <link href='http://fonts.googleapis.com/css?family=Inconsolata|Josefin+Sans:400,300' rel='stylesheet' type='text/css'>
7 | <style>
8 | * {
9 | font-family: 'Josefin Sans', sans-serif;
10 | }
11 | body {
12 | text-align: center;
13 | font-size: 1.0em;
14 | }
15 | .column {
16 | text-align: left;
17 | }
18 | @media (min-width: 400px) {
19 | .column {
20 | display: inline-block;
21 | width: 21em;
22 | vertical-align: top;
23 | max-width: 100%;
24 | }
25 | }
26 | @media (min-width: 450px) {
27 | .center-column {
28 | width: 5em;
29 | }
30 | }
31 | @media (min-width: 800px) {
32 | .right-column {
33 | text-align: left;
34 | margin-left: .4em;
35 | }
36 | .center-column {
37 | text-align: center;
38 | }
39 | .left-column {
40 | text-align: right;
41 | margin-right: .4em;
42 | }
43 | }
44 | @media (min-width: 900px) {
45 | body { font-size: 1.1em; }
46 | }
47 | @media (min-width: 950px) {
48 | body { font-size: 1.2em; }
49 | }
50 | @media (min-width: 1050px) {
51 | body { font-size: 1.3em; }
52 | }
53 | @media (min-width: 1200px) {
54 | body { font-size: 1.4em; }
55 | }
56 | a, code {
57 | transition: .1s ease all;
58 | }
59 | h1 {
60 | font-weight: 300;
61 | font-size: 3.6em;
62 | }
63 | .title-container {
64 | }
65 | h1, h2, p {
66 | margin: 15px 0;
67 | }
68 | .title-container h1 {
69 | margin-top: 28px;
70 | }
71 | .title-container h2 {
72 | font-weight: 300;
73 | font-size: 1.8em;
74 | }
75 | code {
76 | font-family: 'Inconsolata';
77 | background: #ececec;
78 | padding: 0 .1em;
79 | }
80 | .code-block {
81 | white-space: pre;
82 | padding: .5em;
83 | display: block;
84 | font-size: .9em;
85 | }
86 | #sumBox {
87 | font-weight: bold;
88 | }
89 | .a-exe a {
90 | cursor: pointer;
91 | font-family: 'Inconsolata';
92 | color: #6851ff;
93 | background: #ececec;
94 | padding: 0 .1em;
95 | }
96 | .a-exe {
97 | -moz-user-select: none;
98 | -ms-user-select: none;
99 | -webkit-user-select: none;
100 | user-select: none;
101 | }
102 | .a-exe a:active {
103 | color: yellow;
104 | background: black;
105 | }
106 | </style>
107 | <script type="text/javascript" src="../../flyd.js"></script>
108 | <script type="text/javascript" src="script.js"></script>
109 | </script>
110 | </head>
111 | <body>
112 | <button id="btnA">A</button>
113 | <button id="btnB">B</button>
114 | <div id="message"></div>
115 | </body>
116 | </html>
117 |
--------------------------------------------------------------------------------
/examples/multiple-clicks/node_modules/flyd/examples/secret-combination/script.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | var stream = flyd.stream;
5 |
6 | var magicSeq = 'abbaba';
7 |
8 | var setMsg = function(msg) { message.innerHTML = msg; };
9 |
10 | document.addEventListener('DOMContentLoaded', function() {
11 | var click = stream(function(click) {
12 | btnA.addEventListener('click', click.bind(null, 'a'));
13 | btnB.addEventListener('click', click.bind(null, 'b'));
14 | });
15 | var corrects = flyd.reduce(function(cs, c) {
16 | var l = cs.length, correct = (c === magicSeq[l]);
17 | return !correct && l > 0 ? []
18 | : !correct && l === 0 ? undefined
19 | : l + 1 < magicSeq.length ? cs.concat(c)
20 | : (setMsg('Combination unlocked!'), []);
21 | }, [], click);
22 | var scheduled = flyd.map(function(cor) {
23 | if (cor.length === 1) return setTimeout(function() {
24 | setMsg('You\'re not fast enough, try again');
25 | corrects([]);
26 | }, 5000);
27 | }, corrects);
28 | flyd.map(function(c) { console.log(c); }, corrects);
29 | stream(function() {
30 | if (corrects().length === 0 && scheduled.val) clearTimeout(scheduled.val);
31 | });
32 | });
33 | })();
34 |
--------------------------------------------------------------------------------
/examples/multiple-clicks/node_modules/flyd/examples/sum/index.html:
--------------------------------------------------------------------------------
1 | <!DOCTYPE html>
2 | <html>
3 | <head>
4 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 | <title>Sum – a Flyd demo</title>
6 | <link href='http://fonts.googleapis.com/css?family=Inconsolata|Josefin+Sans:400,300' rel='stylesheet' type='text/css'>
7 | <style>
8 | * {
9 | font-family: 'Josefin Sans', sans-serif;
10 | }
11 | body {
12 | text-align: center;
13 | font-size: 1.0em;
14 | }
15 | .column {
16 | text-align: left;
17 | }
18 | @media (min-width: 400px) {
19 | .column {
20 | display: inline-block;
21 | width: 21em;
22 | vertical-align: top;
23 | max-width: 100%;
24 | }
25 | }
26 | @media (min-width: 450px) {
27 | .center-column {
28 | width: 5em;
29 | }
30 | }
31 | @media (min-width: 800px) {
32 | .right-column {
33 | text-align: left;
34 | margin-left: .4em;
35 | }
36 | .center-column {
37 | text-align: center;
38 | }
39 | .left-column {
40 | text-align: right;
41 | margin-right: .4em;
42 | }
43 | }
44 | @media (min-width: 900px) {
45 | body { font-size: 1.1em; }
46 | }
47 | @media (min-width: 950px) {
48 | body { font-size: 1.2em; }
49 | }
50 | @media (min-width: 1050px) {
51 | body { font-size: 1.3em; }
52 | }
53 | @media (min-width: 1200px) {
54 | body { font-size: 1.4em; }
55 | }
56 | a, code {
57 | transition: .1s ease all;
58 | }
59 | h1 {
60 | font-weight: 300;
61 | font-size: 3.6em;
62 | }
63 | .title-container {
64 | }
65 | h1, h2, p {
66 | margin: 15px 0;
67 | }
68 | .title-container h1 {
69 | margin-top: 28px;
70 | }
71 | code {
72 | font-family: 'Inconsolata';
73 | background: #ececec;
74 | padding: 0 .1em;
75 | }
76 | .code-block {
77 | white-space: pre;
78 | padding: .5em;
79 | display: block;
80 | font-size: .9em;
81 | }
82 | #sumBox {
83 | font-weight: bold;
84 | }
85 | .a-exe a {
86 | cursor: pointer;
87 | font-family: 'Inconsolata';
88 | color: #6851ff;
89 | background: #ececec;
90 | padding: 0 .1em;
91 | }
92 | .a-exe {
93 | -moz-user-select: none;
94 | -ms-user-select: none;
95 | -webkit-user-select: none;
96 | user-select: none;
97 | }
98 | .a-exe a:active {
99 | color: yellow;
100 | background: black;
101 | }
102 | </style>
103 | <script type="text/javascript" src="../../flyd.js"></script>
104 | <script type="text/javascript">
105 | var stream = flyd.stream;
106 | var x, y; // Let x and y be globals
107 | document.addEventListener('DOMContentLoaded', function() {
108 | var sumBox = document.getElementById('sumBox');
109 | var xBox = document.getElementById('xBox');
110 | var yBox = document.getElementById('yBox');
111 | x = stream(10);
112 | y = stream(20);
113 | var sum = stream(function() {
114 | if (typeof y() !== 'number' || typeof x() !== 'number') {
115 | // Use called x or y with invalid value
116 | console.log('Numbers only, please!');
117 | return;
118 | }
119 | return x() + y();
120 | });
121 | stream(function() {
122 | sumBox.innerHTML = sum();
123 | });
124 | stream(function() {
125 | xBox.innerHTML = x();
126 | });
127 | stream(function() {
128 | if (typeof y() !== 'number' || typeof x() !== 'number') {
129 | // Use called x or y with invalid value
130 | console.log('Numbers only, please!');
131 | }
132 | yBox.innerHTML = y();
133 | });
134 | // Do animations
135 | function animate(s, elm) {
136 | stream([s], function(s) {
137 | elm.style.background = 'black';
138 | elm.style.color = 'yellow';
139 | setTimeout(function() {
140 | elm.style.background = '#ececec';
141 | elm.style.color = 'black';
142 | }, 220);
143 | });
144 | }
145 | animate(x, xBox);
146 | animate(y, yBox);
147 | animate(sum, sumBox);
148 | });
149 | </script>
150 | </head>
151 | <body>
152 | <div class="title-container">
153 | <h1>Sum</h1>
154 | </div>
155 | <div class="column left-column a-exe">
156 | <h2>Execute</h2>
157 | <p>
158 | Also try calling <code>x</code> and <code>y</code> in your browser console.
159 | </p>
160 | <p>
161 | <a onclick="x(1)">x(1)</a>
162 | <a onclick="x(2)">x(2)</a>
163 | <a onclick="x(3)">x(3)</a>
164 | <a onclick="x(5)">x(5)</a>
165 | <a onclick="x(8)">x(8)</a>
166 | <a onclick="x(13)">x(13)</a>
167 | </p>
168 | <p>
169 | <a onclick="y(1)">y(1)</a>
170 | <a onclick="y(2)">y(2)</a>
171 | <a onclick="y(3)">y(3)</a>
172 | <a onclick="y(5)">y(5)</a>
173 | <a onclick="y(8)">y(8)</a>
174 | <a onclick="y(13)">y(13)</a>
175 | </p>
176 | <p>
177 | <a onclick="x(x()+1)">x(x() + 1)</a>
178 | <a onclick="x(x()-1)">x(x() - 1)</a>
179 | </p>
180 | <p>
181 | <a onclick="y(y()+1)">y(y() + 1)</a>
182 | <a onclick="y(y()-1)">y(y() - 1)</a>
183 | </p>
184 | </div>
185 | <div class="column center-column">
186 | <h2>Result</h2>
187 | <p>
188 | <code>x</code> is <code id="xBox">...</code>
189 | </p>
190 | <p>
191 | <code>y</code> is <code id="yBox">...</code>
192 | </p>
193 | <p>
194 | <code>sum</code> is <code id="sumBox">...</code>
195 | </p>
196 | </div>
197 | <div class="column right-column">
198 | <h2>Source code</h2>
199 | <code class="code-block">var x = stream(10);
200 | var y = stream(20);
201 | var sum = stream(function() {
202 | return x() + y();
203 | });
204 | var elm = document.getElementById('sumBox');
205 | stream(function() {
206 | elm.innerHTML = sum();
207 | });</code>
208 | </div>
209 | </body>
210 | </html>
211 |
--------------------------------------------------------------------------------
/examples/multiple-clicks/node_modules/flyd/flyd.js:
--------------------------------------------------------------------------------
1 | (function (root, factory) {
2 | if (typeof define === 'function' && define.amd) {
3 | define([], factory); // AMD. Register as an anonymous module.
4 | } else if (typeof exports === 'object') {
5 | module.exports = factory(); // NodeJS
6 | } else { // Browser globals (root is window)
7 | root.flyd = factory();
8 | }
9 | }(this, function () {
10 |
11 | 'use strict';
12 |
13 | function isFunction(obj) {
14 | return !!(obj && obj.constructor && obj.call && obj.apply);
15 | }
16 |
17 | function isUndefined(v) {
18 | return v === undefined;
19 | }
20 |
21 | // Globals
22 | var curStream;
23 | var nextId = 0;
24 | var queue = [];
25 |
26 | function flushQueue() {
27 | for (var q; q = queue.pop();) {
28 | for (var i = 0; i < q.l.length; ++i) {
29 | q.l[i](q.v);
30 | }
31 | }
32 | }
33 |
34 | function addDependency(to, from) {
35 | if (!(from.id in to.deps)) {
36 | to.deps[from.id] = from.listeners;
37 | from.listeners.push(to.update);
38 | }
39 | }
40 |
41 | function checkCirc(stream, id) {
42 | if (stream.deps[id]) {
43 | throw new Error('Circular dependency detected');
44 | }
45 | }
46 |
47 | function removeListener(listeners, cb) {
48 | var idx = listeners.indexOf(cb);
49 | listeners[idx] = listeners[listeners.length - 1];
50 | listeners.length--;
51 | }
52 |
53 | function map(s, f) {
54 | return stream([s], function() { return f(s()); }, true);
55 | }
56 |
57 | var reduce = curryN(3, function(f, acc, s) {
58 | var ns = stream([s], function() {
59 | return (acc = f(acc, s()));
60 | }, true);
61 | if (!ns.hasVal) ns(acc);
62 | return ns;
63 | });
64 |
65 | var merge = curryN(2, function(s1, s2) {
66 | return stream(function(n, changed) {
67 | var v1, v2;
68 | if (changed) return changed();
69 | else {
70 | v1 = s1(); v2 = s2();
71 | return v1 === undefined ? v2 : v1;
72 | }
73 | });
74 | });
75 |
76 | function ap(s2) {
77 | var s1 = this;
78 | return stream(function() { return s1()(s2()); });
79 | }
80 |
81 | function of(v) {
82 | return stream()(v);
83 | }
84 |
85 | function initialDepsNotMet(stream) {
86 | if (!isUndefined(stream.initialDeps)) {
87 | var met = stream.initialDeps.every(function(stream) {
88 | return stream.hasVal;
89 | });
90 | if (met) stream.initialDeps = undefined;
91 | }
92 | return !isUndefined(stream.initialDeps);
93 | }
94 |
95 | function updateStream(stream, cb, changed) {
96 | if (initialDepsNotMet(stream)) return;
97 | curStream = stream;
98 | var returnVal = cb(stream, changed);
99 | curStream = undefined;
100 | if (returnVal !== undefined) stream(returnVal);
101 | flushQueue();
102 | }
103 |
104 | function destroy(stream) {
105 | if (stream.listeners.length !== 0) {
106 | throw new Error('Trying to destroy stream with listeners attached');
107 | }
108 | for (var id in stream.deps) {
109 | if (stream.deps[id]) removeListener(stream.deps[id], stream.update);
110 | }
111 | }
112 |
113 | function isStream(stream) {
114 | return isFunction(stream) && 'id' in stream;
115 | }
116 |
117 | function streamToString() {
118 | return 'stream(' + this.val + ')';
119 | }
120 |
121 | function stream(arg) {
122 | function s(n) {
123 | if (arguments.length > 0) {
124 | if (!isUndefined(n) && n !== null && isFunction(n.then)) {
125 | n.then(s);
126 | return;
127 | }
128 | s.val = n;
129 | s.hasVal = true;
130 | if (!isUndefined(curStream)) {
131 | checkCirc(curStream, s.id);
132 | queue.push({v: s, l: s.listeners});
133 | } else {
134 | s.listeners.forEach(function(f) { f(s); });
135 | }
136 | return s;
137 | } else {
138 | if (curStream && curStream.dynamicDeps) {
139 | addDependency(curStream, s);
140 | }
141 | return s.val;
142 | }
143 | }
144 | s.hasVal = false;
145 | s.val = undefined;
146 | s.listeners = [];
147 | s.id = nextId++;
148 | s.deps = {};
149 | s.initialDeps = undefined;
150 | s.deps[s.id] = false;
151 | s.dynamicDeps = true;
152 |
153 | s.map = map.bind(null, s);
154 | s.ap = ap;
155 | s.of = of;
156 | s.toString = streamToString;
157 |
158 | if (arguments.length > 1) {
159 | s.initialDeps = arg;
160 | arg = arguments[1];
161 | if (arguments[2] === true) {
162 | s.dynamicDeps = false;
163 | }
164 | }
165 | if (arguments.length > 0) {
166 | if (isFunction(arg)) {
167 | s.update = updateStream.bind(null, s, arg);
168 | if (s.initialDeps) {
169 | s.initialDeps.forEach(function(stream) {
170 | addDependency(s, stream);
171 | });
172 | }
173 | s.update();
174 | } else {
175 | s.val = arg;
176 | s.hasVal = true;
177 | }
178 | }
179 | return s;
180 | }
181 |
182 | var transduce = curryN(2, function(xform, source) {
183 | xform = xform(new StreamTransformer(stream));
184 | return stream([source], function() {
185 | return xform.step(undefined, source());
186 | });
187 | });
188 |
189 | function StreamTransformer(res) { }
190 | StreamTransformer.prototype.init = function() { };
191 | StreamTransformer.prototype.result = function() { };
192 | StreamTransformer.prototype.step = function(s, v) { return v; };
193 |
194 | // Own curry implementation snatched from Ramda
195 | // Figure out something nicer later on
196 | var _ = {placeholder: true};
197 |
198 | // Detect both own and Ramda placeholder
199 | function isPlaceholder(p) {
200 | return p === _ || (p && p.ramda === 'placeholder');
201 | }
202 |
203 | function toArray(arg) {
204 | var arr = [];
205 | for (var i = 0; i < arg.length; ++i) {
206 | arr[i] = arg[i];
207 | }
208 | return arr;
209 | }
210 |
211 | // Modified versions of arity and curryN from Ramda
212 | function ofArity(n, fn) {
213 | if (arguments.length === 1) {
214 | return ofArity.bind(undefined, n);
215 | }
216 | switch (n) {
217 | case 0:
218 | return function () {
219 | return fn.apply(this, arguments);
220 | };
221 | case 1:
222 | return function (a0) {
223 | void a0;
224 | return fn.apply(this, arguments);
225 | };
226 | case 2:
227 | return function (a0, a1) {
228 | void a1;
229 | return fn.apply(this, arguments);
230 | };
231 | case 3:
232 | return function (a0, a1, a2) {
233 | void a2;
234 | return fn.apply(this, arguments);
235 | };
236 | case 4:
237 | return function (a0, a1, a2, a3) {
238 | void a3;
239 | return fn.apply(this, arguments);
240 | };
241 | case 5:
242 | return function (a0, a1, a2, a3, a4) {
243 | void a4;
244 | return fn.apply(this, arguments);
245 | };
246 | case 6:
247 | return function (a0, a1, a2, a3, a4, a5) {
248 | void a5;
249 | return fn.apply(this, arguments);
250 | };
251 | case 7:
252 | return function (a0, a1, a2, a3, a4, a5, a6) {
253 | void a6;
254 | return fn.apply(this, arguments);
255 | };
256 | case 8:
257 | return function (a0, a1, a2, a3, a4, a5, a6, a7) {
258 | void a7;
259 | return fn.apply(this, arguments);
260 | };
261 | case 9:
262 | return function (a0, a1, a2, a3, a4, a5, a6, a7, a8) {
263 | void a8;
264 | return fn.apply(this, arguments);
265 | };
266 | case 10:
267 | return function (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) {
268 | void a9;
269 | return fn.apply(this, arguments);
270 | };
271 | default:
272 | throw new Error('First argument to arity must be a non-negative integer no greater than ten');
273 | }
274 | }
275 |
276 | function curryN(length, fn) {
277 | return ofArity(length, function () {
278 | var n = arguments.length;
279 | var shortfall = length - n;
280 | var idx = n;
281 | while (--idx >= 0) {
282 | if (isPlaceholder(arguments[idx])) {
283 | shortfall += 1;
284 | }
285 | }
286 | if (shortfall <= 0) {
287 | return fn.apply(this, arguments);
288 | } else {
289 | var initialArgs = toArray(arguments);
290 | return curryN(shortfall, function () {
291 | var currentArgs = toArray(arguments);
292 | var combinedArgs = [];
293 | var idx = -1;
294 | while (++idx < n) {
295 | var val = initialArgs[idx];
296 | combinedArgs[idx] = isPlaceholder(val) ? currentArgs.shift() : val;
297 | }
298 | return fn.apply(this, combinedArgs.concat(currentArgs));
299 | });
300 | }
301 | });
302 | }
303 |
304 |
305 | return {
306 | stream: stream,
307 | isStream: isStream,
308 | transduce: transduce,
309 | merge: merge,
310 | reduce: reduce,
311 | destroy: destroy,
312 | map: curryN(2, function(f, s) { return map(s, f); }),
313 | curryN: curryN,
314 | _: _,
315 | };
316 |
317 | }));
318 |
--------------------------------------------------------------------------------
/examples/multiple-clicks/node_modules/flyd/perf/perf.js:
--------------------------------------------------------------------------------
1 | var _ = require('lodash');
2 | var Benchmark = require('benchmark.js');
3 |
4 | var flyd = require('../flyd');
5 | var oldFlyd = require('../flyd-old');
6 |
7 | var stream = flyd.stream;
8 |
9 | global.stream = flyd.stream;
10 | global.flyd = flyd;
11 | global.oldFlyd = oldFlyd;
12 | global.oldStream = oldFlyd.stream;
13 |
14 | // ************************************************
15 | // Util functions
16 |
17 | var suites = [];
18 |
19 | function getHz(bench) { // hz adjusted for margin of error
20 | var result = 1 / (bench.stats.mean + bench.stats.moe);
21 | return isFinite(result) ? result : 0;
22 | }
23 |
24 | function printFastest(suite) {
25 | var formatNumber = Benchmark.formatNumber,
26 | fastest = suite.filter('fastest'),
27 | fastestHz = getHz(fastest[0]),
28 | slowest = suite.filter('slowest'),
29 | slowestHz = getHz(slowest[0]),
30 | aHz = getHz(suite[0]),
31 | bHz = getHz(suite[1]);
32 | if (fastest.length > 1) {
33 | console.log('It\'s too close to call.');
34 | aHz = bHz = slowestHz;
35 | } else {
36 | var percent = ((fastestHz / slowestHz) - 1) * 100;
37 | console.log(' ' + fastest[0].name + ' is ' +
38 | formatNumber(percent < 1 ? percent.toFixed(2) : Math.round(percent)) +
39 | '% faster.');
40 | }
41 | }
42 |
43 | Benchmark.Suite.options.onStart = function() {
44 | console.log('\n' + this.name + ':');
45 | };
46 |
47 | Benchmark.Suite.options.onCycle = function(event) {
48 | console.log(' ' + event.target);
49 | };
50 |
51 | Benchmark.Suite.options.onComplete = function() {
52 | printFastest(this);
53 | suites.shift();
54 | if (suites.length) {
55 | suites[0].run({async: true});
56 | }
57 | };
58 |
59 | // ************************************************
60 | // Benchmarks!
61 |
62 | suites.push(Benchmark.Suite('dynamic dependencies').add('New', {
63 | setup: function() {
64 | var s = stream();
65 | stream(function() {
66 | return s();
67 | });
68 | },
69 | fn: function() {
70 | s(12);
71 | },
72 | }).add('Old', {
73 | setup: function() {
74 | var s = oldStream();
75 | oldStream(function() {
76 | return s();
77 | });
78 | },
79 | fn: function() {
80 | s(12);
81 | },
82 | }));
83 |
84 | suites.push(Benchmark.Suite('static dependencies').add('New', {
85 | setup: function() {
86 | var s = stream();
87 | stream([s], function() {
88 | return s();
89 | });
90 | },
91 | fn: function() {
92 | s(12);
93 | },
94 | }).add('Old', {
95 | setup: function() {
96 | var s = oldStream();
97 | oldStream([s], function() {
98 | return s();
99 | });
100 | },
101 | fn: function() {
102 | s(12);
103 | },
104 | }));
105 |
106 | suites.push(Benchmark.Suite('map').add('First', {
107 | setup: function() {
108 | var flyd = global.flyd;
109 | var stream = global.flyd.stream;
110 | function f(x) { return x; }
111 | var s1 = stream();
112 | var s2 = s1.map(f);
113 | var s3 = s2.map(f);
114 | var s4 = s3.map(f);
115 | var s5 = s4.map(f);
116 | },
117 | fn: function() {
118 | s1(12);
119 | },
120 | }).add('Second', {
121 | setup: function() {
122 | var flyd = global.flyd;
123 | var stream = global.flyd.stream;
124 | function f(x) { return x; }
125 | var s1 = stream();
126 | var s2 = s1.map(f);
127 | var s3 = s2.map(f);
128 | var s4 = s3.map(f);
129 | var s5 = s4.map(f);
130 | },
131 | fn: function() {
132 | s1(12);
133 | },
134 | }));
135 |
136 | suites.push(Benchmark.Suite('dynamic dependency graph').add('New', {
137 | setup: function() {
138 | var s1 = stream();
139 | var s2 = stream(function() {
140 | s1(); s1();
141 | });
142 | var s3 = stream(function() {
143 | s1(); s2(); s1();
144 | });
145 | var s4 = stream(function() {
146 | s1(); s2(); s3(); s1(); s3();
147 | });
148 | stream(function() {
149 | s3(); s2(); s1(); s3(); s4();
150 | });
151 | },
152 | fn: function() {
153 | s1(12);
154 | },
155 | }).add('Old', {
156 | setup: function() {
157 | var s1 = oldStream();
158 | var s2 = oldStream(function() {
159 | s1(); s1();
160 | });
161 | var s3 = oldStream(function() {
162 | s1(); s2(); s1();
163 | });
164 | var s4 = oldStream(function() {
165 | s1(); s2(); s3(); s1(); s3();
166 | });
167 | oldStream(function() {
168 | s3(); s2(); s1(); s3(); s4();
169 | });
170 | },
171 | fn: function() {
172 | s1(12);
173 | },
174 | }));
175 |
176 | suites[0].run({ 'async': true });
177 |
--------------------------------------------------------------------------------
/examples/multiple-clicks/node_modules/flyd/perf/test.js:
--------------------------------------------------------------------------------
1 | var _ = require('lodash');
2 | var Benchmark = require('benchmark.js');
3 |
4 | var flyd = require('../flyd');
5 | var oldFlyd = require('../flyd');
6 |
7 | var stream = flyd.stream;
8 | global.stream = flyd.stream;
9 | global.flyd = flyd;
10 | global.oldFlyd = oldFlyd;
11 |
12 | // ************************************************
13 | // Util functions
14 |
15 | var suites = [];
16 |
17 | function getHz(bench) { // hz adjusted for margin of error
18 | var result = 1 / (bench.stats.mean + bench.stats.moe);
19 | return isFinite(result) ? result : 0;
20 | }
21 |
22 | function printFastest(suite) {
23 | var formatNumber = Benchmark.formatNumber,
24 | fastest = suite.filter('fastest'),
25 | fastestHz = getHz(fastest[0]),
26 | slowest = suite.filter('slowest'),
27 | slowestHz = getHz(slowest[0]),
28 | aHz = getHz(suite[0]),
29 | bHz = getHz(suite[1]);
30 | if (fastest.length > 1) {
31 | console.log('It\'s too close to call.');
32 | aHz = bHz = slowestHz;
33 | } else {
34 | var percent = ((fastestHz / slowestHz) - 1) * 100;
35 | console.log(' ' + fastest[0].name + ' is ' +
36 | formatNumber(percent < 1 ? percent.toFixed(2) : Math.round(percent)) +
37 | '% faster.');
38 | }
39 | }
40 |
41 | Benchmark.Suite.options.onStart = function() {
42 | console.log('\n' + this.name + ':');
43 | };
44 |
45 | Benchmark.Suite.options.onCycle = function(event) {
46 | console.log(' ' + event.target);
47 | };
48 |
49 | Benchmark.Suite.options.onComplete = function() {
50 | printFastest(this);
51 | suites.shift();
52 | if (suites.length) {
53 | suites[0].run({async: true});
54 | }
55 | };
56 |
57 | // ************************************************
58 | // Benchmarks!
59 |
60 | suites.push(Benchmark.Suite('First map test').add('First', {
61 | setup: function() {
62 | function f(x) { return x; }
63 | var s1 = stream();
64 | var s2 = s1.map(f);
65 | var s3 = s2.map(f);
66 | var s4 = s3.map(f);
67 | var s5 = s4.map(f);
68 | },
69 | fn: function() {
70 | s1(12);
71 | },
72 | }).add('Second', {
73 | setup: function() {
74 | function f(x) { return x; }
75 | var s1 = stream();
76 | var s2 = s1.map(f);
77 | var s3 = s2.map(f);
78 | var s4 = s3.map(f);
79 | var s5 = s4.map(f);
80 | },
81 | fn: function() {
82 | s1(12);
83 | },
84 | }));
85 |
86 | suites.push(Benchmark.Suite('Second map test').add('First', {
87 | setup: function() {
88 | var flyd = global.flyd;
89 | var stream = global.flyd.stream;
90 | function f(x) { return x; }
91 | var s1 = stream();
92 | var s2 = s1.map(f);
93 | var s3 = s2.map(f);
94 | var s4 = s3.map(f);
95 | var s5 = s4.map(f);
96 | },
97 | fn: function() {
98 | s1(12);
99 | },
100 | }).add('Second', {
101 | setup: function() {
102 | var flyd = global.flyd;
103 | var stream = global.flyd.stream;
104 | function f(x) { return x; }
105 | var s1 = stream();
106 | var s2 = s1.map(f);
107 | var s3 = s2.map(f);
108 | var s4 = s3.map(f);
109 | var s5 = s4.map(f);
110 | },
111 | fn: function() {
112 | s1(12);
113 | },
114 | }));
115 |
116 | suites[0].run({ 'async': true });
117 |
--------------------------------------------------------------------------------
/examples/multiple-clicks/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "multiple-clicks",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": ".build.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "Simon Friis Vindum",
10 | "license": "MIT",
11 | "dependencies": {
12 | "flyd": "0.0.x",
13 | "flyd-aftersilence": "0.0.x"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/examples/multiple-clicks/script.js:
--------------------------------------------------------------------------------
1 | var flyd = require('../../lib');
2 | var afterSilence = require('../../module/aftersilence');
3 |
4 | document.addEventListener('DOMContentLoaded', function() {
5 | var btnElm = document.getElementById('btn');
6 | var msgElm = document.getElementById('msg');
7 |
8 | var clickStream = flyd.stream();
9 | btnElm.addEventListener('click', clickStream);
10 |
11 | var groupedClicks = afterSilence(250, clickStream);
12 | var nrStream = flyd.map(function(clicks) { return clicks.length; }, groupedClicks);
13 |
14 | flyd.map(function(nr) {
15 | msgElm.textContent = nr === 1 ? 'click' : nr + ' clicks';
16 | }, nrStream);
17 |
18 | flyd.map(function(nr) {
19 | msgElm.textContent = '';
20 | }, afterSilence(1000, nrStream));
21 | });
22 |
--------------------------------------------------------------------------------
/examples/ramda-transducer/README.md:
--------------------------------------------------------------------------------
1 | # Ramda transducer example
2 |
3 | ```javascript
4 | npm install
5 | node script
6 | ```
7 |
--------------------------------------------------------------------------------
/examples/ramda-transducer/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ramda-transducer-example",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "script.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "Simon Friis Vindum",
10 | "license": "MIT",
11 | "dependencies": {
12 | "flyd": "^0.1.0",
13 | "ramda": "^0.17.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/examples/ramda-transducer/script.js:
--------------------------------------------------------------------------------
1 | var R = require('ramda');
2 | var flyd = require('../../lib');
3 |
4 | // Let's create a stream of numbers
5 | var numbers = flyd.stream();
6 |
7 | var isEven = R.compose(R.identical(0), R.modulo(R.__, 2));
8 |
9 | // All even numbers multiplied by 3
10 | var drop3evenTimes3 = flyd.transduce(R.compose(
11 | R.drop(3),
12 | R.filter(isEven),
13 | R.map(R.multiply(3))
14 | ), numbers);
15 |
16 | flyd.map(function(n) { console.log(n); }, drop3evenTimes3);
17 |
18 | numbers(9)(4)(2)(8)(6)(5)(2);
19 |
--------------------------------------------------------------------------------
/examples/secret-combination/index.html:
--------------------------------------------------------------------------------
1 | <!DOCTYPE html>
2 | <html>
3 | <head>
4 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 | <title>Secret combination</title>
6 | <link href='http://fonts.googleapis.com/css?family=Inconsolata|Josefin+Sans:400,300' rel='stylesheet' type='text/css'>
7 | <style>
8 | * {
9 | font-family: 'Josefin Sans', sans-serif;
10 | }
11 | body {
12 | text-align: center;
13 | font-size: 1.0em;
14 | }
15 | .column {
16 | text-align: left;
17 | }
18 | @media (min-width: 400px) {
19 | .column {
20 | display: inline-block;
21 | width: 21em;
22 | vertical-align: top;
23 | max-width: 100%;
24 | }
25 | }
26 | @media (min-width: 450px) {
27 | .center-column {
28 | width: 5em;
29 | }
30 | }
31 | @media (min-width: 800px) {
32 | .right-column {
33 | text-align: left;
34 | margin-left: .4em;
35 | }
36 | .center-column {
37 | text-align: center;
38 | }
39 | .left-column {
40 | text-align: right;
41 | margin-right: .4em;
42 | }
43 | }
44 | @media (min-width: 900px) {
45 | body { font-size: 1.1em; }
46 | }
47 | @media (min-width: 950px) {
48 | body { font-size: 1.2em; }
49 | }
50 | @media (min-width: 1050px) {
51 | body { font-size: 1.3em; }
52 | }
53 | @media (min-width: 1200px) {
54 | body { font-size: 1.4em; }
55 | }
56 | a, code {
57 | transition: .1s ease all;
58 | }
59 | h1 {
60 | font-weight: 300;
61 | font-size: 3.6em;
62 | }
63 | .title-container {
64 | }
65 | h1, h2, p {
66 | margin: 15px 0;
67 | }
68 | .title-container h1 {
69 | margin-top: 28px;
70 | }
71 | .title-container h2 {
72 | font-weight: 300;
73 | font-size: 1.8em;
74 | }
75 | code {
76 | font-family: 'Inconsolata';
77 | background: #ececec;
78 | padding: 0 .1em;
79 | }
80 | .code-block {
81 | white-space: pre;
82 | padding: .5em;
83 | display: block;
84 | font-size: .9em;
85 | }
86 | #sumBox {
87 | font-weight: bold;
88 | }
89 | .a-exe a {
90 | cursor: pointer;
91 | font-family: 'Inconsolata';
92 | color: #6851ff;
93 | background: #ececec;
94 | padding: 0 .1em;
95 | }
96 | .a-exe {
97 | -moz-user-select: none;
98 | -ms-user-select: none;
99 | -webkit-user-select: none;
100 | user-select: none;
101 | }
102 | .a-exe a:active {
103 | color: yellow;
104 | background: black;
105 | }
106 | </style>
107 | <script type="text/javascript" src="build.js"></script>
108 | </head>
109 | <body>
110 | <button id="btnA">A</button>
111 | <button id="btnB">B</button>
112 | <div id="message"></div>
113 | <p>
114 | This is an implementation of the problem described in <a href="http://www.jayway.com/2014/09/16/comparing-core-async-and-rx-by-example/">Comparing Core Async and Rx by Example</a>
115 | </p>
116 | <p>
117 | <a href="https://github.com/paldepind/flyd/blob/master/examples/secret-combination/script.js">See the source code</a>
118 | </p>
119 | </body>
120 | </html>
121 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd-filter/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Simon Friis Vindum
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd-filter/README.md:
--------------------------------------------------------------------------------
1 | # flyd-filter
2 | Filter function for Flyd.
3 |
4 | # Usage
5 |
6 | ```javascript
7 | var numbers = flyd.stream();
8 | var largeNumbers = filter(over5, numbers);
9 | flyd.map(function(n) {
10 | // called with 6, 7 and 10
11 | }, largeNumbers);
12 | numbers(2)(6)(5)(3)(7)(10)(5);
13 |
14 | ```
15 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd-filter/filter.js:
--------------------------------------------------------------------------------
1 | var flyd = require('flyd');
2 |
3 | module.exports = function(fn, s) {
4 | return flyd.stream([s], function(self) {
5 | if (fn(s())) self(s.val);
6 | });
7 | };
8 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd-filter/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "flyd-filter",
3 | "version": "1.0.1",
4 | "description": "Filter function for Flyd.",
5 | "main": "filter.js",
6 | "directories": {
7 | "test": "test"
8 | },
9 | "scripts": {
10 | "test": "mocha"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "https://github.com/paldepind/flyd-filter.git"
15 | },
16 | "keywords": [
17 | "filter",
18 | "flyd"
19 | ],
20 | "author": {
21 | "name": "Simon Friis Vindum"
22 | },
23 | "license": "MIT",
24 | "bugs": {
25 | "url": "https://github.com/paldepind/flyd-filter/issues"
26 | },
27 | "homepage": "https://github.com/paldepind/flyd-filter",
28 | "devDependencies": {
29 | "flyd": "0.1.x"
30 | },
31 | "gitHead": "8fb8d361750daa31739d84ef68b74a84271cdae4",
32 | "readme": "# flyd-filter\nFilter function for Flyd.\n\n# Usage\n\n```javascript\nvar numbers = flyd.stream();\nvar largeNumbers = filter(over5, numbers);\nflyd.map(function(n) {\n // called with 6, 7 and 10\n}, largeNumbers);\nnumbers(2)(6)(5)(3)(7)(10)(5);\n\n```\n",
33 | "readmeFilename": "README.md",
34 | "_id": "flyd-filter@1.0.1",
35 | "_shasum": "643c538a644fa1e0b301ed00575b646295b850d6",
36 | "_from": "flyd-filter@>=1.0.0 <2.0.0"
37 | }
38 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd-filter/test/index.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var flyd = require('flyd');
3 |
4 | var filter = require('../filter.js');
5 |
6 | describe('filter', function() {
7 | it('only lets values passing the filter through', function() {
8 | function over5(n) {
9 | return n > 5;
10 | }
11 | var result = [];
12 | var numbers = flyd.stream();
13 | var largeNumbers = filter(over5, numbers);
14 | flyd.map(function(n) {
15 | result.push(n);
16 | }, largeNumbers);
17 | numbers(2)(6)(5)(3)(7)(10)(5);
18 | assert.deepEqual(result, [6, 7, 10]);
19 | });
20 | });
21 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd-inlast/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Simon Friis Vindum
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd-inlast/README.md:
--------------------------------------------------------------------------------
1 | # flyd-inlast
2 | Creates a stream with emits a list of all values from the source stream that where emitted in a specified duration.
3 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd-inlast/inlast.js:
--------------------------------------------------------------------------------
1 | var flyd = require('flyd');
2 |
3 | module.exports = flyd.curryN(2, function(dur, s) {
4 | var values = [];
5 | return flyd.stream([s], function(self) {
6 | setTimeout(function() {
7 | self(values = values.slice(1));
8 | }, dur);
9 | return (values = values.concat([s()]));
10 | });
11 | });
12 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd-inlast/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "flyd-inlast",
3 | "version": "0.0.1",
4 | "description": "Creates a stream with emits a list of all values from the source stream that where emitted in a specified duration.",
5 | "main": "inlast.js",
6 | "directories": {
7 | "test": "test"
8 | },
9 | "scripts": {
10 | "test": "mocha"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "https://github.com/paldepind/flyd-inlast.git"
15 | },
16 | "keywords": [
17 | "flyd",
18 | "inlast",
19 | "time",
20 | "duration"
21 | ],
22 | "author": {
23 | "name": "Simon Friis Vindum"
24 | },
25 | "license": "MIT",
26 | "bugs": {
27 | "url": "https://github.com/paldepind/flyd-inlast/issues"
28 | },
29 | "homepage": "https://github.com/paldepind/flyd-inlast",
30 | "dependencies": {
31 | "flyd": "^0.1.0"
32 | },
33 | "readme": "# flyd-inlast\nCreates a stream with emits a list of all values from the source stream that where emitted in a specified duration.\n",
34 | "readmeFilename": "README.md",
35 | "gitHead": "a952b1a8692a0ecdcc41cbb5cb4a4e57da5a4324",
36 | "_id": "flyd-inlast@0.0.1",
37 | "_shasum": "f5b98d171c34964db9e6e32cd0d22c4a5c0ea4d9",
38 | "_from": "flyd-inlast@>=0.0.0 <0.1.0"
39 | }
40 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd-inlast/test/index.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var flyd = require('flyd');
3 | var stream = flyd.stream;
4 |
5 | var inLast = require('../inlast.js');
6 |
7 | describe('inLast', function() {
8 | it('adds values', function(done) {
9 | var s = stream();
10 | var lastMs = inLast(50, s);
11 | s(1);
12 | setTimeout(function() {
13 | assert.deepEqual(lastMs(), [1]);
14 | s(2);
15 | }, 20);
16 | setTimeout(function() {
17 | assert.deepEqual(lastMs(), [1, 2]);
18 | done();
19 | }, 40);
20 | });
21 | it('adds and removes values', function(done) {
22 | var s = stream();
23 | var lastMs = inLast(50, s);
24 | s(1);
25 | setTimeout(function() {
26 | assert.deepEqual(lastMs(), [1]);
27 | s(2);
28 | }, 35);
29 | setTimeout(function() {
30 | assert.deepEqual(lastMs(), [1, 2]);
31 | s(3);
32 | }, 40);
33 | setTimeout(function() {
34 | assert.deepEqual(lastMs(), [2, 3]);
35 | s(4);
36 | }, 60);
37 | setTimeout(function() {
38 | assert.deepEqual(lastMs(), [2, 3, 4]);
39 | s(5);
40 | }, 80);
41 | setTimeout(function() {
42 | assert.deepEqual(lastMs(), [4, 5]);
43 | done();
44 | }, 100);
45 | });
46 | it('is updated when values come and go', function(done) {
47 | var result = [];
48 | var s = stream();
49 | var lastMs = inLast(50, s);
50 | flyd.map(function(a) { result.push(a); }, lastMs);
51 | s(1);
52 | setTimeout(function() { s(2); }, 35);
53 | setTimeout(function() { s(3); }, 40);
54 | // 1 leaves
55 | setTimeout(function() { s(4); }, 60);
56 | setTimeout(function() { s(5); }, 80);
57 | // 2 leaves
58 | // 3 leaves
59 | setTimeout(function() {
60 | assert.deepEqual(result, [
61 | [1],
62 | [1, 2],
63 | [1, 2, 3],
64 | [2, 3],
65 | [2, 3, 4],
66 | [2, 3, 4, 5],
67 | [3, 4, 5],
68 | [4, 5],
69 | ]);
70 | done();
71 | }, 100);
72 | });
73 | });
74 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd-lift/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Simon Friis Vindum
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd-lift/README.md:
--------------------------------------------------------------------------------
1 | # flyd-lift
2 | Lift function for [Flyd](https://github.com/paldepind/flyd).
3 |
4 | # Usage
5 |
6 | ```javascript
7 | var addThree = function(a, b, c) {
8 | return a + b + c;
9 | };
10 |
11 | var n1 = stream(1),
12 | n2 = stream(4),
13 | n3 = stream(9);
14 |
15 | var sum = lift(addThree, n1, n2, n3);
16 |
17 | sum(); // 14
18 | ```
19 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd-lift/flyd-lift.js:
--------------------------------------------------------------------------------
1 | var flyd = require('flyd');
2 |
3 | module.exports = function(f /* , streams */) {
4 | var streams = Array.prototype.slice.call(arguments, 1);
5 | var vals = [];
6 | return flyd.stream(streams, function() {
7 | for (var i = 0; i < streams.length; ++i) vals[i] = streams[i]();
8 | return f.apply(null, vals);
9 | });
10 | };
11 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd-lift/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "flyd-lift",
3 | "version": "1.0.2",
4 | "description": "Lift for Flyd.",
5 | "main": "flyd-lift.js",
6 | "directories": {
7 | "test": "test"
8 | },
9 | "dependencies": {
10 | "flyd": "0.1.x"
11 | },
12 | "devDependencies": {},
13 | "scripts": {
14 | "test": "mocha"
15 | },
16 | "repository": {
17 | "type": "git",
18 | "url": "https://github.com/paldepind/flyd-lift.git"
19 | },
20 | "keywords": [
21 | "flyd",
22 | "lift"
23 | ],
24 | "author": {
25 | "name": "Simon Friis Vindum"
26 | },
27 | "license": "MIT",
28 | "bugs": {
29 | "url": "https://github.com/paldepind/flyd-lift/issues"
30 | },
31 | "homepage": "https://github.com/paldepind/flyd-lift",
32 | "gitHead": "d1d1775dc9d7ef6898dac2601ba716e42efb279e",
33 | "readme": "# flyd-lift\nLift function for [Flyd](https://github.com/paldepind/flyd).\n\n# Usage\n\n```javascript\nvar addThree = function(a, b, c) {\n return a + b + c;\n};\n\nvar n1 = stream(1),\n n2 = stream(4),\n n3 = stream(9);\n\nvar sum = lift(addThree, n1, n2, n3);\n\nsum(); // 14\n```\n",
34 | "readmeFilename": "README.md",
35 | "_id": "flyd-lift@1.0.2",
36 | "_shasum": "b29bc378aee5f77fa90ae39f1451ab1611854ee0",
37 | "_from": "flyd-lift@1.0.2"
38 | }
39 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd-lift/test/index.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var flyd = require('flyd');
3 | var stream = flyd.stream;
4 | var lift = require('../flyd-lift.js');
5 |
6 | describe('lift', function() {
7 | it('applies a function to two streams', function() {
8 | var add = function(x, y) { return x + y; };
9 | var x = stream(3);
10 | var y = stream(4);
11 | var sum = lift(add, x, y);
12 | assert.equal(sum(), x() + y());
13 | x(12);
14 | assert.equal(sum(), x() + y());
15 | y(3);
16 | assert.equal(sum(), x() + y());
17 | });
18 | it('applies a function to five streams', function() {
19 | var add = function(a, b, c, d, e) { return a + b + c + d + e; };
20 | var a = stream(1);
21 | var b = stream(2);
22 | var c = stream(3);
23 | var d = stream(4);
24 | var e = stream(5);
25 | var sum = lift(add, a, b, c, d, e);
26 | assert.equal(sum(), a() + b() + c() + d() + e());
27 | e(12); d(2); b(0);
28 | assert.equal(sum(), a() + b() + c() + d() + e());
29 | a(3); c(3);
30 | assert.equal(sum(), a() + b() + c() + d() + e());
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd-sampleon/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Simon Friis Vindum
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd-sampleon/README.md:
--------------------------------------------------------------------------------
1 | # flyd-sampleon
2 | sampleOn for Flyd.
3 |
4 | Samples from the second stream every time an event occurs on the first
5 | stream.
6 |
7 | __Signature__
8 |
9 | `Stream a -> Stream b -> Stream b`
10 |
11 | __Usage__
12 |
13 | ```javascript
14 | // Assume `sendBtnClicked` emits whenever a send button is pressed and
15 | // `messageText` is a stream of the current content of an input field.
16 | // Then `sendMessage` emits the content of the text field whenever the button
17 | // is pressed.
18 | var sendMessage = sampleOn(sendBtnClicked, messageText);
19 | ```
20 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd-sampleon/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "flyd-sampleon",
3 | "version": "1.0.3",
4 | "description": "sampleOn for Flyd",
5 | "main": "sampleon.js",
6 | "directories": {
7 | "test": "test"
8 | },
9 | "scripts": {
10 | "test": "mocha"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "https://github.com/paldepind/flyd-sampleon.git"
15 | },
16 | "keywords": [
17 | "flyd",
18 | "sampleon"
19 | ],
20 | "author": {
21 | "name": "Simon Friis Vindum"
22 | },
23 | "license": "MIT",
24 | "bugs": {
25 | "url": "https://github.com/paldepind/flyd-sampleon/issues"
26 | },
27 | "homepage": "https://github.com/paldepind/flyd-sampleon",
28 | "dependencies": {
29 | "flyd": "0.1.x"
30 | },
31 | "readme": "# flyd-sampleon\nsampleOn for Flyd.\n\nSamples from the second stream every time an event occurs on the first\nstream.\n\n__Signature__\n\n`Stream a -> Stream b -> Stream b`\n\n__Usage__\n\n```javascript\n// Assume `sendBtnClicked` emits whenever a send button is pressed and\n// `messageText` is a stream of the current content of an input field.\n// Then `sendMessage` emits the content of the text field whenever the button\n// is pressed.\nvar sendMessage = sampleOn(sendBtnClicked, messageText);\n```\n",
32 | "readmeFilename": "README.md",
33 | "gitHead": "58189daed2195b44e1711796680d6b134d139685",
34 | "_id": "flyd-sampleon@1.0.3",
35 | "_shasum": "e4b6381ca35a0a4f08f3e4e31592fed382a74ac9",
36 | "_from": "flyd-sampleon@*"
37 | }
38 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd-sampleon/sampleon.js:
--------------------------------------------------------------------------------
1 | var flyd = require('flyd');
2 |
3 | module.exports = flyd.curryN(2, function(s1, s2) {
4 | return flyd.stream([s1], function() {
5 | return s2();
6 | });
7 | });
8 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd-sampleon/test/index.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var flyd = require('flyd');
3 | var stream = flyd.stream;
4 |
5 | var sampleOn = require('../sampleon.js');
6 |
7 | describe('sample On', function() {
8 | it('samples from second stream', function() {
9 | var result = [];
10 | var s1 = stream();
11 | var s2 = stream();
12 | var sampled = sampleOn(s1, s2);
13 | flyd.map(function(v) {
14 | result.push(v);
15 | }, sampled);
16 | s2(1);
17 | s1(1)(2)(3);
18 | s2(3)(4)(6);
19 | s1(5)(3);
20 | assert.deepEqual(result, [1, 1, 1, 6, 6]);
21 | });
22 | it('has not value until value flows on trigger stream', function() {
23 | var result = [];
24 | var s1 = stream();
25 | var s2 = stream(1);
26 | var sampled = sampleOn(s1, s2);
27 | flyd.map(function(v) {
28 | result.push(v);
29 | }, sampled);
30 | s2(1);
31 | s1(1)(2)(3);
32 | s2(3)(4)(6);
33 | s1(5)(3);
34 | assert.deepEqual(result, [1, 1, 1, 6, 6]);
35 | });
36 | });
37 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "0.12"
4 | - "0.10"
5 | - "iojs"
6 | after_success:
7 | - ./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage
8 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Simon Friis Vindum
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "flyd",
3 | "main": "flyd.js",
4 | "version": "0.0.1",
5 | "homepage": "https://github.com/paldepind/flyd",
6 | "authors": [
7 | "Simon Friis Vindum"
8 | ],
9 | "description": "The less is more, modular functional reactive programming library",
10 | "moduleType": [
11 | "amd",
12 | "globals",
13 | "node"
14 | ],
15 | "keywords": [
16 | "functional",
17 | "reactive",
18 | "modular"
19 | ],
20 | "license": "MIT",
21 | "ignore": [
22 | "**/.*",
23 | "node_modules",
24 | "bower_components",
25 | "test",
26 | "tests"
27 | ]
28 | }
29 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd/coverage/lcov.info:
--------------------------------------------------------------------------------
1 | TN:
2 | SF:/home/simon/projects/flyd/flyd.js
3 | FN:1,(anonymous_1)
4 | FN:9,(anonymous_2)
5 | FN:13,isFunction
6 | FN:17,isUndefined
7 | FN:27,flushQueue
8 | FN:35,addDependency
9 | FN:42,checkCirc
10 | FN:48,removeListener
11 | FN:54,map
12 | FN:55,(anonymous_10)
13 | FN:58,reduce
14 | FN:59,(anonymous_12)
15 | FN:64,merge
16 | FN:65,(anonymous_14)
17 | FN:75,ap
18 | FN:77,(anonymous_16)
19 | FN:80,of
20 | FN:84,initialDepsNotMet
21 | FN:86,(anonymous_19)
22 | FN:94,updateStream
23 | FN:103,destroyStream
24 | FN:112,stream
25 | FN:113,s
26 | FN:124,(anonymous_24)
27 | FN:157,(anonymous_25)
28 | FN:168,transduce
29 | FN:170,(anonymous_27)
30 | FN:175,StreamTransformer
31 | FN:176,(anonymous_29)
32 | FN:177,(anonymous_30)
33 | FN:178,(anonymous_31)
34 | FNF:31
35 | FNH:29
36 | FNDA:1,(anonymous_1)
37 | FNDA:1,(anonymous_2)
38 | FNDA:336,isFunction
39 | FNDA:646,isUndefined
40 | FNDA:152,flushQueue
41 | FNDA:212,addDependency
42 | FNDA:17,checkCirc
43 | FNDA:2,removeListener
44 | FNDA:7,map
45 | FNDA:14,(anonymous_10)
46 | FNDA:1,reduce
47 | FNDA:4,(anonymous_12)
48 | FNDA:1,merge
49 | FNDA:8,(anonymous_14)
50 | FNDA:9,ap
51 | FNDA:21,(anonymous_16)
52 | FNDA:7,of
53 | FNDA:167,initialDepsNotMet
54 | FNDA:37,(anonymous_19)
55 | FNDA:167,updateStream
56 | FNDA:2,destroyStream
57 | FNDA:114,stream
58 | FNDA:537,s
59 | FNDA:109,(anonymous_24)
60 | FNDA:22,(anonymous_25)
61 | FNDA:3,transduce
62 | FNDA:15,(anonymous_27)
63 | FNDA:3,StreamTransformer
64 | FNDA:0,(anonymous_29)
65 | FNDA:0,(anonymous_30)
66 | FNDA:10,(anonymous_31)
67 | DA:1,1
68 | DA:2,1
69 | DA:3,0
70 | DA:4,1
71 | DA:5,1
72 | DA:7,0
73 | DA:13,1
74 | DA:14,336
75 | DA:17,1
76 | DA:18,646
77 | DA:22,1
78 | DA:23,1
79 | DA:25,1
80 | DA:27,1
81 | DA:28,152
82 | DA:29,15
83 | DA:30,5
84 | DA:35,1
85 | DA:36,212
86 | DA:37,69
87 | DA:38,69
88 | DA:42,1
89 | DA:43,17
90 | DA:44,2
91 | DA:48,1
92 | DA:49,2
93 | DA:50,2
94 | DA:51,2
95 | DA:54,1
96 | DA:55,14
97 | DA:58,1
98 | DA:59,1
99 | DA:60,4
100 | DA:64,1
101 | DA:65,1
102 | DA:66,8
103 | DA:67,8
104 | DA:69,1
105 | DA:70,1
106 | DA:75,1
107 | DA:76,9
108 | DA:77,21
109 | DA:80,1
110 | DA:81,7
111 | DA:84,1
112 | DA:85,167
113 | DA:86,34
114 | DA:87,37
115 | DA:89,34
116 | DA:91,167
117 | DA:94,1
118 | DA:95,167
119 | DA:96,154
120 | DA:97,154
121 | DA:98,152
122 | DA:99,152
123 | DA:100,152
124 | DA:103,1
125 | DA:104,2
126 | DA:105,1
127 | DA:107,1
128 | DA:108,3
129 | DA:112,1
130 | DA:113,1
131 | DA:114,537
132 | DA:115,222
133 | DA:116,2
134 | DA:117,2
135 | DA:119,220
136 | DA:120,220
137 | DA:121,17
138 | DA:122,15
139 | DA:124,203
140 | DA:126,218
141 | DA:128,315
142 | DA:129,190
143 | DA:131,315
144 | DA:134,114
145 | DA:135,114
146 | DA:136,114
147 | DA:137,114
148 | DA:138,114
149 | DA:139,114
150 | DA:140,114
151 | DA:142,114
152 | DA:143,114
153 | DA:144,114
154 | DA:145,114
155 | DA:147,114
156 | DA:148,21
157 | DA:149,21
158 | DA:150,21
159 | DA:151,8
160 | DA:154,114
161 | DA:155,53
162 | DA:156,53
163 | DA:157,21
164 | DA:158,22
165 | DA:161,53
166 | DA:163,61
167 | DA:165,112
168 | DA:168,1
169 | DA:169,3
170 | DA:170,3
171 | DA:171,15
172 | DA:175,1
173 | DA:176,1
174 | DA:177,1
175 | DA:178,10
176 | DA:180,1
177 | LF:110
178 | LH:108
179 | BRDA:2,1,0,0
180 | BRDA:2,1,1,1
181 | BRDA:2,2,0,1
182 | BRDA:2,2,1,0
183 | BRDA:4,3,0,1
184 | BRDA:4,3,1,0
185 | BRDA:14,4,0,336
186 | BRDA:14,4,1,90
187 | BRDA:14,4,2,90
188 | BRDA:14,4,3,55
189 | BRDA:36,5,0,69
190 | BRDA:36,5,1,143
191 | BRDA:43,6,0,2
192 | BRDA:43,6,1,15
193 | BRDA:67,7,0,7
194 | BRDA:67,7,1,1
195 | BRDA:70,8,0,1
196 | BRDA:70,8,1,0
197 | BRDA:85,9,0,34
198 | BRDA:85,9,1,133
199 | BRDA:89,10,0,21
200 | BRDA:89,10,1,13
201 | BRDA:95,11,0,13
202 | BRDA:95,11,1,154
203 | BRDA:99,12,0,110
204 | BRDA:99,12,1,42
205 | BRDA:104,13,0,1
206 | BRDA:104,13,1,1
207 | BRDA:108,14,0,2
208 | BRDA:108,14,1,1
209 | BRDA:114,15,0,222
210 | BRDA:114,15,1,315
211 | BRDA:115,16,0,2
212 | BRDA:115,16,1,220
213 | BRDA:115,17,0,222
214 | BRDA:115,17,1,222
215 | BRDA:120,18,0,17
216 | BRDA:120,18,1,203
217 | BRDA:128,19,0,190
218 | BRDA:128,19,1,125
219 | BRDA:128,20,0,315
220 | BRDA:128,20,1,216
221 | BRDA:147,21,0,21
222 | BRDA:147,21,1,93
223 | BRDA:150,22,0,8
224 | BRDA:150,22,1,13
225 | BRDA:154,23,0,53
226 | BRDA:154,23,1,61
227 | BRDA:156,24,0,21
228 | BRDA:156,24,1,32
229 | BRF:50
230 | BRH:46
231 | end_of_record
232 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd/examples/multiple-clicks/index.html:
--------------------------------------------------------------------------------
1 | <!DOCTYPE html>
2 | <html>
3 | <head>
4 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 | <title>Multiple clicks</title>
6 | <link href='http://fonts.googleapis.com/css?family=Inconsolata|Josefin+Sans:400,300' rel='stylesheet' type='text/css'>
7 | <script type="text/javascript" src="build.js"></script>
8 | </head>
9 | <body>
10 | <button id="btn">Click me</button>
11 | <span id="msg">Double click it</span>
12 | <p>
13 | <a href="https://github.com/paldepind/flyd/blob/master/examples/multiple-clicks/script.js">See the source code</a>
14 | </p>
15 | </body>
16 | </html>
17 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd/examples/multiple-clicks/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "multiple-clicks",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": ".build.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "Simon Friis Vindum",
10 | "license": "MIT",
11 | "dependencies": {
12 | "flyd": "0.0.x",
13 | "flyd-aftersilence": "0.0.x"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd/examples/multiple-clicks/script.js:
--------------------------------------------------------------------------------
1 | var flyd = require('flyd');
2 | var afterSilence = require('flyd-aftersilence');
3 |
4 | document.addEventListener('DOMContentLoaded', function() {
5 | var btnElm = document.getElementById('btn');
6 | var msgElm = document.getElementById('msg');
7 |
8 | var clickStream = flyd.stream();
9 | btnElm.addEventListener('click', clickStream);
10 |
11 | var groupedClicks = afterSilence(250, clickStream);
12 | var nrStream = flyd.map(function(clicks) { return clicks.length; }, groupedClicks);
13 |
14 | flyd.map(function(nr) {
15 | msgElm.textContent = nr === 1 ? 'click' : nr + ' clicks';
16 | }, nrStream);
17 |
18 | flyd.map(function(nr) {
19 | msgElm.textContent = '';
20 | }, afterSilence(1000, nrStream));
21 | });
22 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd/examples/secret-combination/index.html:
--------------------------------------------------------------------------------
1 | <!DOCTYPE html>
2 | <html>
3 | <head>
4 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 | <title>Secret combination</title>
6 | <link href='http://fonts.googleapis.com/css?family=Inconsolata|Josefin+Sans:400,300' rel='stylesheet' type='text/css'>
7 | <style>
8 | * {
9 | font-family: 'Josefin Sans', sans-serif;
10 | }
11 | body {
12 | text-align: center;
13 | font-size: 1.0em;
14 | }
15 | .column {
16 | text-align: left;
17 | }
18 | @media (min-width: 400px) {
19 | .column {
20 | display: inline-block;
21 | width: 21em;
22 | vertical-align: top;
23 | max-width: 100%;
24 | }
25 | }
26 | @media (min-width: 450px) {
27 | .center-column {
28 | width: 5em;
29 | }
30 | }
31 | @media (min-width: 800px) {
32 | .right-column {
33 | text-align: left;
34 | margin-left: .4em;
35 | }
36 | .center-column {
37 | text-align: center;
38 | }
39 | .left-column {
40 | text-align: right;
41 | margin-right: .4em;
42 | }
43 | }
44 | @media (min-width: 900px) {
45 | body { font-size: 1.1em; }
46 | }
47 | @media (min-width: 950px) {
48 | body { font-size: 1.2em; }
49 | }
50 | @media (min-width: 1050px) {
51 | body { font-size: 1.3em; }
52 | }
53 | @media (min-width: 1200px) {
54 | body { font-size: 1.4em; }
55 | }
56 | a, code {
57 | transition: .1s ease all;
58 | }
59 | h1 {
60 | font-weight: 300;
61 | font-size: 3.6em;
62 | }
63 | .title-container {
64 | }
65 | h1, h2, p {
66 | margin: 15px 0;
67 | }
68 | .title-container h1 {
69 | margin-top: 28px;
70 | }
71 | .title-container h2 {
72 | font-weight: 300;
73 | font-size: 1.8em;
74 | }
75 | code {
76 | font-family: 'Inconsolata';
77 | background: #ececec;
78 | padding: 0 .1em;
79 | }
80 | .code-block {
81 | white-space: pre;
82 | padding: .5em;
83 | display: block;
84 | font-size: .9em;
85 | }
86 | #sumBox {
87 | font-weight: bold;
88 | }
89 | .a-exe a {
90 | cursor: pointer;
91 | font-family: 'Inconsolata';
92 | color: #6851ff;
93 | background: #ececec;
94 | padding: 0 .1em;
95 | }
96 | .a-exe {
97 | -moz-user-select: none;
98 | -ms-user-select: none;
99 | -webkit-user-select: none;
100 | user-select: none;
101 | }
102 | .a-exe a:active {
103 | color: yellow;
104 | background: black;
105 | }
106 | </style>
107 | <script type="text/javascript" src="../../flyd.js"></script>
108 | <script type="text/javascript" src="script.js"></script>
109 | </script>
110 | </head>
111 | <body>
112 | <button id="btnA">A</button>
113 | <button id="btnB">B</button>
114 | <div id="message"></div>
115 | </body>
116 | </html>
117 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd/examples/secret-combination/script.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | var stream = flyd.stream;
5 |
6 | var magicSeq = 'abbaba';
7 |
8 | var setMsg = function(msg) { message.innerHTML = msg; };
9 |
10 | document.addEventListener('DOMContentLoaded', function() {
11 | var click = stream();
12 | btnA.addEventListener('click', click.bind(null, 'a'));
13 | btnB.addEventListener('click', click.bind(null, 'b'));
14 | var corrects = flyd.reduce(function(cs, c) {
15 | var l = cs.length, correct = (c === magicSeq[l]);
16 | console.log(l, correct);
17 | return !correct && l > 0 ? []
18 | : !correct && l === 0 ? []
19 | : l + 1 < magicSeq.length ? cs.concat(c)
20 | : (setMsg('Combination unlocked!'), []);
21 | }, [], click);
22 | var scheduled = flyd.map(function(cor) {
23 | if (cor.length === 1) return setTimeout(function() {
24 | setMsg('You\'re not fast enough, try again');
25 | corrects([]);
26 | }, 5000);
27 | }, corrects);
28 | flyd.map(function(c) { console.log(c); }, corrects);
29 | stream([corrects], function() {
30 | if (corrects().length === 0 && scheduled.val) clearTimeout(scheduled.val);
31 | });
32 | });
33 | })();
34 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd/examples/sum/index.html:
--------------------------------------------------------------------------------
1 | <!DOCTYPE html>
2 | <html>
3 | <head>
4 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 | <title>Sum – a Flyd demo</title>
6 | <link href='http://fonts.googleapis.com/css?family=Inconsolata|Josefin+Sans:400,300' rel='stylesheet' type='text/css'>
7 | <style>
8 | * {
9 | font-family: 'Josefin Sans', sans-serif;
10 | }
11 | body {
12 | text-align: center;
13 | font-size: 1.0em;
14 | }
15 | .column {
16 | text-align: left;
17 | }
18 | @media (min-width: 400px) {
19 | .column {
20 | display: inline-block;
21 | width: 21em;
22 | vertical-align: top;
23 | max-width: 100%;
24 | }
25 | }
26 | @media (min-width: 450px) {
27 | .center-column {
28 | width: 5em;
29 | }
30 | }
31 | @media (min-width: 800px) {
32 | .right-column {
33 | text-align: left;
34 | margin-left: .4em;
35 | }
36 | .center-column {
37 | text-align: center;
38 | }
39 | .left-column {
40 | text-align: right;
41 | margin-right: .4em;
42 | }
43 | }
44 | @media (min-width: 900px) {
45 | body { font-size: 1.1em; }
46 | }
47 | @media (min-width: 950px) {
48 | body { font-size: 1.2em; }
49 | }
50 | @media (min-width: 1050px) {
51 | body { font-size: 1.3em; }
52 | }
53 | @media (min-width: 1200px) {
54 | body { font-size: 1.4em; }
55 | }
56 | a, code {
57 | transition: .1s ease all;
58 | }
59 | h1 {
60 | font-weight: 300;
61 | font-size: 3.6em;
62 | }
63 | .title-container {
64 | }
65 | h1, h2, p {
66 | margin: 15px 0;
67 | }
68 | .title-container h1 {
69 | margin-top: 28px;
70 | }
71 | code {
72 | font-family: 'Inconsolata';
73 | background: #ececec;
74 | padding: 0 .1em;
75 | }
76 | .code-block {
77 | white-space: pre;
78 | padding: .5em;
79 | display: block;
80 | font-size: .9em;
81 | }
82 | #sumBox {
83 | font-weight: bold;
84 | }
85 | .a-exe a {
86 | cursor: pointer;
87 | font-family: 'Inconsolata';
88 | color: #6851ff;
89 | background: #ececec;
90 | padding: 0 .1em;
91 | }
92 | .a-exe {
93 | -moz-user-select: none;
94 | -ms-user-select: none;
95 | -webkit-user-select: none;
96 | user-select: none;
97 | }
98 | .a-exe a:active {
99 | color: yellow;
100 | background: black;
101 | }
102 | </style>
103 | <script type="text/javascript" src="../../flyd.js"></script>
104 | <script type="text/javascript">
105 | var stream = flyd.stream;
106 | var x, y; // Let x and y be globals
107 | document.addEventListener('DOMContentLoaded', function() {
108 | var sumBox = document.getElementById('sumBox');
109 | var xBox = document.getElementById('xBox');
110 | var yBox = document.getElementById('yBox');
111 | x = stream(10);
112 | y = stream(20);
113 | var sum = stream([x, y], function() {
114 | return x() + y();
115 | });
116 | flyd.map(function(sum) {
117 | sumBox.innerHTML = sum;
118 | }, sum);
119 | flyd.map(function(x) {
120 | if (typeof x !== 'number') { // Use called x or y with invalid value
121 | console.log('Numbers only, please!');
122 | }
123 | xBox.innerHTML = x;
124 | }, x);
125 | flyd.map(function(y) {
126 | if (typeof y !== 'number') { // Use called x or y with invalid value
127 | console.log('Numbers only, please!');
128 | }
129 | yBox.innerHTML = y;
130 | }, y);
131 | // Do animations
132 | function animate(s, elm) {
133 | flyd.map(function() {
134 | elm.style.background = 'black';
135 | elm.style.color = 'yellow';
136 | setTimeout(function() {
137 | elm.style.background = '#ececec';
138 | elm.style.color = 'black';
139 | }, 220);
140 | }, s);
141 | }
142 | animate(x, xBox);
143 | animate(y, yBox);
144 | animate(sum, sumBox);
145 | });
146 | </script>
147 | </head>
148 | <body>
149 | <div class="title-container">
150 | <h1>Sum</h1>
151 | </div>
152 | <div class="column left-column a-exe">
153 | <h2>Execute</h2>
154 | <p>
155 | Also try calling <code>x</code> and <code>y</code> in your browser console.
156 | </p>
157 | <p>
158 | <a onclick="x(1)">x(1)</a>
159 | <a onclick="x(2)">x(2)</a>
160 | <a onclick="x(3)">x(3)</a>
161 | <a onclick="x(5)">x(5)</a>
162 | <a onclick="x(8)">x(8)</a>
163 | <a onclick="x(13)">x(13)</a>
164 | </p>
165 | <p>
166 | <a onclick="y(1)">y(1)</a>
167 | <a onclick="y(2)">y(2)</a>
168 | <a onclick="y(3)">y(3)</a>
169 | <a onclick="y(5)">y(5)</a>
170 | <a onclick="y(8)">y(8)</a>
171 | <a onclick="y(13)">y(13)</a>
172 | </p>
173 | <p>
174 | <a onclick="x(x()+1)">x(x() + 1)</a>
175 | <a onclick="x(x()-1)">x(x() - 1)</a>
176 | </p>
177 | <p>
178 | <a onclick="y(y()+1)">y(y() + 1)</a>
179 | <a onclick="y(y()-1)">y(y() - 1)</a>
180 | </p>
181 | </div>
182 | <div class="column center-column">
183 | <h2>Result</h2>
184 | <p>
185 | <code>x</code> is <code id="xBox">...</code>
186 | </p>
187 | <p>
188 | <code>y</code> is <code id="yBox">...</code>
189 | </p>
190 | <p>
191 | <code>sum</code> is <code id="sumBox">...</code>
192 | </p>
193 | </div>
194 | <div class="column right-column">
195 | <h2>Source code</h2>
196 | <code class="code-block">var x = stream(10);
197 | var y = stream(20);
198 | var sum = stream([x, y], function() {
199 | return x() + y();
200 | });
201 | var elm = document.getElementById('sumBox');
202 | flyd.map(function(s) {
203 | elm.innerHTML = s;
204 | }, sum);</code>
205 | </div>
206 | </body>
207 | </html>
208 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd/flyd.js:
--------------------------------------------------------------------------------
1 | (function (root, factory) {
2 | if (typeof define === 'function' && define.amd) {
3 | define([], factory); // AMD. Register as an anonymous module.
4 | } else if (typeof exports === 'object') {
5 | module.exports = factory(); // NodeJS
6 | } else { // Browser globals (root is window)
7 | root.flyd = factory();
8 | }
9 | }(this, function () {
10 |
11 | 'use strict';
12 |
13 | function isFunction(obj) {
14 | return !!(obj && obj.constructor && obj.call && obj.apply);
15 | }
16 |
17 | function isUndefined(v) {
18 | return v === undefined;
19 | }
20 |
21 | // Globals
22 | var queue = [];
23 | var isFlushingQueue = false;
24 |
25 | function flushQueue() {
26 | if (isFlushingQueue) return;
27 | isFlushingQueue = true;
28 | for (var s; s = queue.shift();) {
29 | s.inQueue = false;
30 | s.update();
31 | }
32 | isFlushingQueue = false;
33 | }
34 |
35 | function removeListener(listeners, s) {
36 | var idx = listeners.indexOf(s);
37 | listeners[idx] = listeners[listeners.length - 1];
38 | listeners.length--;
39 | }
40 |
41 | function map(s, f) {
42 | return stream([s], function() { return f(s()); });
43 | }
44 |
45 | var reduce = curryN(3, function(f, acc, s) {
46 | var ns = stream([s], function() {
47 | return (acc = f(acc, s()));
48 | });
49 | if (!ns.hasVal) ns(acc);
50 | return ns;
51 | });
52 |
53 | var merge = curryN(2, function(s1, s2) {
54 | return stream([s1, s2], function(n, changed) {
55 | var v1, v2;
56 | if (changed) return changed();
57 | else {
58 | v1 = s1(); v2 = s2();
59 | return v1 === undefined ? v2 : v1;
60 | }
61 | }, true);
62 | });
63 |
64 | function ap(s2) {
65 | var s1 = this;
66 | return stream([s1, s2], function() { return s1()(s2()); }, true);
67 | }
68 |
69 | function of(v) {
70 | return stream()(v);
71 | }
72 |
73 | function initialDepsNotMet(stream) {
74 | if (!stream.depsMet) {
75 | stream.depsMet = stream.deps.every(function(s) {
76 | return s.hasVal;
77 | });
78 | }
79 | return !stream.depsMet;
80 | }
81 |
82 | function updateStream() {
83 | if (initialDepsNotMet(this)) return;
84 | var returnVal = this.fn(this, this.depChanged);
85 | if (returnVal !== undefined) this(returnVal);
86 | }
87 |
88 | function destroy(stream) {
89 | if (stream.listeners.length !== 0) {
90 | throw new Error('Trying to destroy stream with listeners attached');
91 | }
92 | stream.deps.forEach(function(dep) { removeListener(dep.listeners, stream); });
93 | }
94 |
95 | function isStream(stream) {
96 | return isFunction(stream) && 'depsMet' in stream;
97 | }
98 |
99 | function streamToString() {
100 | return 'stream(' + this.val + ')';
101 | }
102 |
103 | function stream(arg, fn, waitForDeps) {
104 | function s(n) {
105 | if (arguments.length > 0) {
106 | if (!isUndefined(n) && n !== null && isFunction(n.then)) {
107 | n.then(s);
108 | return;
109 | }
110 | s.val = n;
111 | s.hasVal = true;
112 | s.listeners.forEach(function(st) {
113 | st.depChanged = s;
114 | if (!st.inQueue) {
115 | st.inQueue = true;
116 | queue.push(st);
117 | }
118 | });
119 | flushQueue();
120 | return s;
121 | } else {
122 | return s.val;
123 | }
124 | }
125 | s.hasVal = false;
126 | s.val = undefined;
127 | s.listeners = [];
128 | s.deps = [];
129 | s.depsMet = isUndefined(waitForDeps) ? false : true;
130 | s.depChanged = undefined;
131 | s.inQueue = true;
132 | s.fn = fn;
133 |
134 | s.map = map.bind(null, s);
135 | s.ap = ap;
136 | s.of = of;
137 | s.toString = streamToString;
138 |
139 | if (arguments.length > 1) {
140 | s.update = updateStream;
141 | s.deps = arg;
142 | arg.forEach(function(dep) {
143 | dep.listeners.push(s);
144 | });
145 | queue.push(s);
146 | flushQueue();
147 | } else if (arguments.length === 1) {
148 | s.val = arg;
149 | s.hasVal = true;
150 | }
151 | return s;
152 | }
153 |
154 | var transduce = curryN(2, function(xform, source) {
155 | xform = xform(new StreamTransformer(stream));
156 | return stream([source], function() {
157 | return xform.step(undefined, source());
158 | });
159 | });
160 |
161 | function StreamTransformer(res) { }
162 | StreamTransformer.prototype.init = function() { };
163 | StreamTransformer.prototype.result = function() { };
164 | StreamTransformer.prototype.step = function(s, v) { return v; };
165 |
166 | // Own curry implementation snatched from Ramda
167 | // Figure out something nicer later on
168 | var _ = {placeholder: true};
169 |
170 | // Detect both own and Ramda placeholder
171 | function isPlaceholder(p) {
172 | return p === _ || (p && p.ramda === 'placeholder');
173 | }
174 |
175 | function toArray(arg) {
176 | var arr = [];
177 | for (var i = 0; i < arg.length; ++i) {
178 | arr[i] = arg[i];
179 | }
180 | return arr;
181 | }
182 |
183 | // Modified versions of arity and curryN from Ramda
184 | function ofArity(n, fn) {
185 | if (arguments.length === 1) {
186 | return ofArity.bind(undefined, n);
187 | }
188 | switch (n) {
189 | case 0:
190 | return function () {
191 | return fn.apply(this, arguments);
192 | };
193 | case 1:
194 | return function (a0) {
195 | void a0;
196 | return fn.apply(this, arguments);
197 | };
198 | case 2:
199 | return function (a0, a1) {
200 | void a1;
201 | return fn.apply(this, arguments);
202 | };
203 | case 3:
204 | return function (a0, a1, a2) {
205 | void a2;
206 | return fn.apply(this, arguments);
207 | };
208 | case 4:
209 | return function (a0, a1, a2, a3) {
210 | void a3;
211 | return fn.apply(this, arguments);
212 | };
213 | case 5:
214 | return function (a0, a1, a2, a3, a4) {
215 | void a4;
216 | return fn.apply(this, arguments);
217 | };
218 | case 6:
219 | return function (a0, a1, a2, a3, a4, a5) {
220 | void a5;
221 | return fn.apply(this, arguments);
222 | };
223 | case 7:
224 | return function (a0, a1, a2, a3, a4, a5, a6) {
225 | void a6;
226 | return fn.apply(this, arguments);
227 | };
228 | case 8:
229 | return function (a0, a1, a2, a3, a4, a5, a6, a7) {
230 | void a7;
231 | return fn.apply(this, arguments);
232 | };
233 | case 9:
234 | return function (a0, a1, a2, a3, a4, a5, a6, a7, a8) {
235 | void a8;
236 | return fn.apply(this, arguments);
237 | };
238 | case 10:
239 | return function (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) {
240 | void a9;
241 | return fn.apply(this, arguments);
242 | };
243 | default:
244 | throw new Error('First argument to arity must be a non-negative integer no greater than ten');
245 | }
246 | }
247 |
248 | function curryN(length, fn) {
249 | return ofArity(length, function () {
250 | var n = arguments.length;
251 | var shortfall = length - n;
252 | var idx = n;
253 | while (--idx >= 0) {
254 | if (isPlaceholder(arguments[idx])) {
255 | shortfall += 1;
256 | }
257 | }
258 | if (shortfall <= 0) {
259 | return fn.apply(this, arguments);
260 | } else {
261 | var initialArgs = toArray(arguments);
262 | return curryN(shortfall, function () {
263 | var currentArgs = toArray(arguments);
264 | var combinedArgs = [];
265 | var idx = -1;
266 | while (++idx < n) {
267 | var val = initialArgs[idx];
268 | combinedArgs[idx] = isPlaceholder(val) ? currentArgs.shift() : val;
269 | }
270 | return fn.apply(this, combinedArgs.concat(currentArgs));
271 | });
272 | }
273 | });
274 | }
275 |
276 |
277 | return {
278 | stream: stream,
279 | isStream: isStream,
280 | transduce: transduce,
281 | merge: merge,
282 | reduce: reduce,
283 | destroy: destroy,
284 | map: curryN(2, function(f, s) { return map(s, f); }),
285 | curryN: curryN,
286 | _: _,
287 | };
288 |
289 | }));
290 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd/perf/perf.js:
--------------------------------------------------------------------------------
1 | var _ = require('lodash');
2 | var Benchmark = require('benchmark.js');
3 |
4 | var flyd = require('../flyd');
5 | var oldFlyd = require('../flyd-old');
6 |
7 | var stream = flyd.stream;
8 |
9 | global.stream = flyd.stream;
10 | global.flyd = flyd;
11 | global.oldFlyd = oldFlyd;
12 | global.oldStream = oldFlyd.stream;
13 |
14 | // ************************************************
15 | // Util functions
16 |
17 | var suites = [];
18 |
19 | function getHz(bench) { // hz adjusted for margin of error
20 | var result = 1 / (bench.stats.mean + bench.stats.moe);
21 | return isFinite(result) ? result : 0;
22 | }
23 |
24 | function printFastest(suite) {
25 | var formatNumber = Benchmark.formatNumber,
26 | fastest = suite.filter('fastest'),
27 | fastestHz = getHz(fastest[0]),
28 | slowest = suite.filter('slowest'),
29 | slowestHz = getHz(slowest[0]),
30 | aHz = getHz(suite[0]),
31 | bHz = getHz(suite[1]);
32 | if (fastest.length > 1) {
33 | console.log('It\'s too close to call.');
34 | aHz = bHz = slowestHz;
35 | } else {
36 | var percent = ((fastestHz / slowestHz) - 1) * 100;
37 | console.log(' ' + fastest[0].name + ' is ' +
38 | formatNumber(percent < 1 ? percent.toFixed(2) : Math.round(percent)) +
39 | '% faster.');
40 | }
41 | }
42 |
43 | Benchmark.Suite.options.onStart = function() {
44 | console.log('\n' + this.name + ':');
45 | };
46 |
47 | Benchmark.Suite.options.onCycle = function(event) {
48 | console.log(' ' + event.target);
49 | };
50 |
51 | Benchmark.Suite.options.onComplete = function() {
52 | printFastest(this);
53 | suites.shift();
54 | if (suites.length) {
55 | suites[0].run({async: true});
56 | }
57 | };
58 |
59 | // ************************************************
60 | // Benchmarks!
61 |
62 | suites.push(Benchmark.Suite('dynamic dependencies').add('New', {
63 | setup: function() {
64 | var s = stream();
65 | stream(function() {
66 | return s();
67 | });
68 | },
69 | fn: function() {
70 | s(12);
71 | },
72 | }).add('Old', {
73 | setup: function() {
74 | var s = oldStream();
75 | oldStream(function() {
76 | return s();
77 | });
78 | },
79 | fn: function() {
80 | s(12);
81 | },
82 | }));
83 |
84 | suites.push(Benchmark.Suite('static dependencies').add('New', {
85 | setup: function() {
86 | var s = stream();
87 | stream([s], function() {
88 | return s();
89 | });
90 | },
91 | fn: function() {
92 | s(12);
93 | },
94 | }).add('Old', {
95 | setup: function() {
96 | var s = oldStream();
97 | oldStream([s], function() {
98 | return s();
99 | });
100 | },
101 | fn: function() {
102 | s(12);
103 | },
104 | }));
105 |
106 | suites.push(Benchmark.Suite('map').add('First', {
107 | setup: function() {
108 | var flyd = global.flyd;
109 | var stream = global.flyd.stream;
110 | function f(x) { return x; }
111 | var s1 = stream();
112 | var s2 = s1.map(f);
113 | var s3 = s2.map(f);
114 | var s4 = s3.map(f);
115 | var s5 = s4.map(f);
116 | },
117 | fn: function() {
118 | s1(12);
119 | },
120 | }).add('Second', {
121 | setup: function() {
122 | var flyd = global.flyd;
123 | var stream = global.flyd.stream;
124 | function f(x) { return x; }
125 | var s1 = stream();
126 | var s2 = s1.map(f);
127 | var s3 = s2.map(f);
128 | var s4 = s3.map(f);
129 | var s5 = s4.map(f);
130 | },
131 | fn: function() {
132 | s1(12);
133 | },
134 | }));
135 |
136 | suites.push(Benchmark.Suite('dynamic dependency graph').add('New', {
137 | setup: function() {
138 | var s1 = stream();
139 | var s2 = stream(function() {
140 | s1(); s1();
141 | });
142 | var s3 = stream(function() {
143 | s1(); s2(); s1();
144 | });
145 | var s4 = stream(function() {
146 | s1(); s2(); s3(); s1(); s3();
147 | });
148 | stream(function() {
149 | s3(); s2(); s1(); s3(); s4();
150 | });
151 | },
152 | fn: function() {
153 | s1(12);
154 | },
155 | }).add('Old', {
156 | setup: function() {
157 | var s1 = oldStream();
158 | var s2 = oldStream(function() {
159 | s1(); s1();
160 | });
161 | var s3 = oldStream(function() {
162 | s1(); s2(); s1();
163 | });
164 | var s4 = oldStream(function() {
165 | s1(); s2(); s3(); s1(); s3();
166 | });
167 | oldStream(function() {
168 | s3(); s2(); s1(); s3(); s4();
169 | });
170 | },
171 | fn: function() {
172 | s1(12);
173 | },
174 | }));
175 |
176 | suites[0].run({ 'async': true });
177 |
--------------------------------------------------------------------------------
/examples/secret-combination/node_modules/flyd/perf/test.js:
--------------------------------------------------------------------------------
1 | var _ = require('lodash');
2 | var Benchmark = require('benchmark.js');
3 |
4 | var flyd = require('../flyd');
5 | var oldFlyd = require('../flyd');
6 |
7 | var stream = flyd.stream;
8 | global.stream = flyd.stream;
9 | global.flyd = flyd;
10 | global.oldFlyd = oldFlyd;
11 |
12 | // ************************************************
13 | // Util functions
14 |
15 | var suites = [];
16 |
17 | function getHz(bench) { // hz adjusted for margin of error
18 | var result = 1 / (bench.stats.mean + bench.stats.moe);
19 | return isFinite(result) ? result : 0;
20 | }
21 |
22 | function printFastest(suite) {
23 | var formatNumber = Benchmark.formatNumber,
24 | fastest = suite.filter('fastest'),
25 | fastestHz = getHz(fastest[0]),
26 | slowest = suite.filter('slowest'),
27 | slowestHz = getHz(slowest[0]),
28 | aHz = getHz(suite[0]),
29 | bHz = getHz(suite[1]);
30 | if (fastest.length > 1) {
31 | console.log('It\'s too close to call.');
32 | aHz = bHz = slowestHz;
33 | } else {
34 | var percent = ((fastestHz / slowestHz) - 1) * 100;
35 | console.log(' ' + fastest[0].name + ' is ' +
36 | formatNumber(percent < 1 ? percent.toFixed(2) : Math.round(percent)) +
37 | '% faster.');
38 | }
39 | }
40 |
41 | Benchmark.Suite.options.onStart = function() {
42 | console.log('\n' + this.name + ':');
43 | };
44 |
45 | Benchmark.Suite.options.onCycle = function(event) {
46 | console.log(' ' + event.target);
47 | };
48 |
49 | Benchmark.Suite.options.onComplete = function() {
50 | printFastest(this);
51 | suites.shift();
52 | if (suites.length) {
53 | suites[0].run({async: true});
54 | }
55 | };
56 |
57 | // ************************************************
58 | // Benchmarks!
59 |
60 | suites.push(Benchmark.Suite('First map test').add('First', {
61 | setup: function() {
62 | function f(x) { return x; }
63 | var s1 = stream();
64 | var s2 = s1.map(f);
65 | var s3 = s2.map(f);
66 | var s4 = s3.map(f);
67 | var s5 = s4.map(f);
68 | },
69 | fn: function() {
70 | s1(12);
71 | },
72 | }).add('Second', {
73 | setup: function() {
74 | function f(x) { return x; }
75 | var s1 = stream();
76 | var s2 = s1.map(f);
77 | var s3 = s2.map(f);
78 | var s4 = s3.map(f);
79 | var s5 = s4.map(f);
80 | },
81 | fn: function() {
82 | s1(12);
83 | },
84 | }));
85 |
86 | suites.push(Benchmark.Suite('Second map test').add('First', {
87 | setup: function() {
88 | var flyd = global.flyd;
89 | var stream = global.flyd.stream;
90 | function f(x) { return x; }
91 | var s1 = stream();
92 | var s2 = s1.map(f);
93 | var s3 = s2.map(f);
94 | var s4 = s3.map(f);
95 | var s5 = s4.map(f);
96 | },
97 | fn: function() {
98 | s1(12);
99 | },
100 | }).add('Second', {
101 | setup: function() {
102 | var flyd = global.flyd;
103 | var stream = global.flyd.stream;
104 | function f(x) { return x; }
105 | var s1 = stream();
106 | var s2 = s1.map(f);
107 | var s3 = s2.map(f);
108 | var s4 = s3.map(f);
109 | var s5 = s4.map(f);
110 | },
111 | fn: function() {
112 | s1(12);
113 | },
114 | }));
115 |
116 | suites[0].run({ 'async': true });
117 |
--------------------------------------------------------------------------------
/examples/secret-combination/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "secret-combination",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "build.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "Simon Friis Vindum",
10 | "license": "MIT",
11 | "dependencies": {
12 | "flyd": "0.1.x",
13 | "flyd-filter": "1.0.x",
14 | "flyd-inlast": "0.0.x",
15 | "flyd-lift": "1.0.x",
16 | "flyd-sampleon": "1.0.x"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/examples/secret-combination/script.js:
--------------------------------------------------------------------------------
1 | var flyd = require('../../lib');
2 | var stream = flyd.stream;
3 | var filter = require('../../module/filter');
4 | var lift = require('../../module/lift');
5 | var inLast = require('../../module/inlast');
6 | var sampleOn = require('../../module/sampleon');
7 |
8 | var magicSeq = 'abbaba';
9 | var seqLen = magicSeq.length;
10 | var maxTime = 5000;
11 |
12 | var setMsg = function(msg) { message.innerHTML = msg; };
13 |
14 | document.addEventListener('DOMContentLoaded', function() {
15 | var clicks = stream();
16 | btnA.addEventListener('click', clicks.bind(null, 'a'));
17 | btnB.addEventListener('click', clicks.bind(null, 'b'));
18 |
19 | var correctClicks = flyd.reduce(function(n, c) {
20 | return magicSeq[n] === c ? n + 1
21 | : magicSeq[0] === c ? 1
22 | : 0;
23 | }, 0, clicks);
24 |
25 | var clicksInLast5s = inLast(maxTime, clicks);
26 |
27 | lift(function(corrects, inLast5s) {
28 | var complete = corrects === seqLen, inTime = inLast5s.length >= seqLen;
29 | setMsg(complete && inTime ? 'Combination unlocked'
30 | : complete && !inTime ? "You're not fast enough, try again!"
31 | : corrects);
32 | }, correctClicks, sampleOn(clicks, clicksInLast5s));
33 |
34 | flyd.map(function(c) { console.log('cor', c); }, correctClicks);
35 | flyd.map(function(c) { console.log('lst', c); }, clicksInLast5s);
36 | });
37 |
--------------------------------------------------------------------------------
/examples/sum/index.html:
--------------------------------------------------------------------------------
1 | <!DOCTYPE html>
2 | <html>
3 | <head>
4 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 | <title>Sum – a Flyd demo</title>
6 | <link href='http://fonts.googleapis.com/css?family=Inconsolata|Josefin+Sans:400,300' rel='stylesheet' type='text/css'>
7 | <style>
8 | * {
9 | font-family: 'Josefin Sans', sans-serif;
10 | }
11 | body {
12 | text-align: center;
13 | font-size: 1.0em;
14 | }
15 | .column {
16 | text-align: left;
17 | }
18 | @media (min-width: 400px) {
19 | .column {
20 | display: inline-block;
21 | width: 21em;
22 | vertical-align: top;
23 | max-width: 100%;
24 | }
25 | }
26 | @media (min-width: 450px) {
27 | .center-column {
28 | width: 5em;
29 | }
30 | }
31 | @media (min-width: 800px) {
32 | .right-column {
33 | text-align: left;
34 | margin-left: .4em;
35 | }
36 | .center-column {
37 | text-align: center;
38 | }
39 | .left-column {
40 | text-align: right;
41 | margin-right: .4em;
42 | }
43 | }
44 | @media (min-width: 900px) {
45 | body { font-size: 1.1em; }
46 | }
47 | @media (min-width: 950px) {
48 | body { font-size: 1.2em; }
49 | }
50 | @media (min-width: 1050px) {
51 | body { font-size: 1.3em; }
52 | }
53 | @media (min-width: 1200px) {
54 | body { font-size: 1.4em; }
55 | }
56 | a, code {
57 | transition: .1s ease all;
58 | }
59 | h1 {
60 | font-weight: 300;
61 | font-size: 3.6em;
62 | }
63 | .title-container {
64 | }
65 | h1, h2, p {
66 | margin: 15px 0;
67 | }
68 | .title-container h1 {
69 | margin-top: 28px;
70 | }
71 | code {
72 | font-family: 'Inconsolata';
73 | background: #ececec;
74 | padding: 0 .1em;
75 | }
76 | .code-block {
77 | white-space: pre;
78 | padding: .5em;
79 | display: block;
80 | font-size: .9em;
81 | }
82 | #sumBox {
83 | font-weight: bold;
84 | }
85 | .a-exe a {
86 | cursor: pointer;
87 | font-family: 'Inconsolata';
88 | color: #6851ff;
89 | background: #ececec;
90 | padding: 0 .1em;
91 | }
92 | .a-exe {
93 | -moz-user-select: none;
94 | -ms-user-select: none;
95 | -webkit-user-select: none;
96 | user-select: none;
97 | }
98 | .a-exe a:active {
99 | color: yellow;
100 | background: black;
101 | }
102 | </style>
103 | <script type="text/javascript" src="build.js"></script>
104 | </head>
105 | <body>
106 | <div class="title-container">
107 | <h1>Sum</h1>
108 | </div>
109 | <div class="column left-column a-exe">
110 | <h2>Execute</h2>
111 | <p>
112 | Also try calling <code>x</code> and <code>y</code> in your browser console.
113 | </p>
114 | <p>
115 | <a onclick="x(1)">x(1)</a>
116 | <a onclick="x(2)">x(2)</a>
117 | <a onclick="x(3)">x(3)</a>
118 | <a onclick="x(5)">x(5)</a>
119 | <a onclick="x(8)">x(8)</a>
120 | <a onclick="x(13)">x(13)</a>
121 | </p>
122 | <p>
123 | <a onclick="y(1)">y(1)</a>
124 | <a onclick="y(2)">y(2)</a>
125 | <a onclick="y(3)">y(3)</a>
126 | <a onclick="y(5)">y(5)</a>
127 | <a onclick="y(8)">y(8)</a>
128 | <a onclick="y(13)">y(13)</a>
129 | </p>
130 | <p>
131 | <a onclick="x(x()+1)">x(x() + 1)</a>
132 | <a onclick="x(x()-1)">x(x() - 1)</a>
133 | </p>
134 | <p>
135 | <a onclick="y(y()+1)">y(y() + 1)</a>
136 | <a onclick="y(y()-1)">y(y() - 1)</a>
137 | </p>
138 | </div>
139 | <div class="column center-column">
140 | <h2>Result</h2>
141 | <p>
142 | <code>x</code> is <code id="xBox">...</code>
143 | </p>
144 | <p>
145 | <code>y</code> is <code id="yBox">...</code>
146 | </p>
147 | <p>
148 | <code>sum</code> is <code id="sumBox">...</code>
149 | </p>
150 | </div>
151 | <div class="column right-column">
152 | <h2>Source code</h2>
153 | <code class="code-block">var x = stream(10);
154 | var y = stream(20);
155 | var sum = flyd.combine(function(x, y) {
156 | return x() + y();
157 | }, [x, y]);
158 | var elm = document.getElementById('sumBox');
159 | flyd.map(function(s) {
160 | elm.innerHTML = s;
161 | }, sum);</code>
162 | </div>
163 | </body>
164 | </html>
165 |
--------------------------------------------------------------------------------
/examples/sum/script.js:
--------------------------------------------------------------------------------
1 | var flyd = require("../../lib");
2 | var stream = flyd.stream;
3 | var x, y; // Let x and y be globals
4 | document.addEventListener("DOMContentLoaded", function() {
5 | var sumBox = document.getElementById("sumBox");
6 | var xBox = document.getElementById("xBox");
7 | var yBox = document.getElementById("yBox");
8 | x = stream(10);
9 | y = stream(20);
10 | var sum = flyd.combine(
11 | function(x, y) {
12 | return x() + y();
13 | },
14 | [x, y]
15 | );
16 | flyd.map(function(sum) {
17 | sumBox.innerHTML = sum;
18 | }, sum);
19 | flyd.map(function(x) {
20 | if (typeof x !== "number") {
21 | // Use called x or y with invalid value
22 | console.log("Numbers only, please!");
23 | }
24 | xBox.innerHTML = x;
25 | }, x);
26 | flyd.map(function(y) {
27 | if (typeof y !== "number") {
28 | // Use called x or y with invalid value
29 | console.log("Numbers only, please!");
30 | }
31 | yBox.innerHTML = y;
32 | }, y);
33 | // Do animations
34 | function animate(s, elm) {
35 | flyd.map(function() {
36 | elm.style.background = "black";
37 | elm.style.color = "yellow";
38 | setTimeout(function() {
39 | elm.style.background = "#ececec";
40 | elm.style.color = "black";
41 | }, 220);
42 | }, s);
43 | }
44 | animate(x, xBox);
45 | animate(y, yBox);
46 | animate(sum, sumBox);
47 | });
48 |
--------------------------------------------------------------------------------
/examples/who-to-follow/index.html:
--------------------------------------------------------------------------------
1 | <!DOCTYPE html>
2 | <html>
3 | <head>
4 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 | <title>Who to follow</title>
6 | <link href='http://fonts.googleapis.com/css?family=Inconsolata|Josefin+Sans:400,300' rel='stylesheet' type='text/css'>
7 | <script type="text/javascript" src="build.js"></script>
8 | <style>
9 | * {
10 | font-family: 'Josefin Sans', sans-serif;
11 | }
12 | body {
13 | font-family: Josefin Sans;
14 | font-family: sans-serif;
15 | padding: 10px;
16 | font-size: 1.1em;
17 | }
18 | h2 {
19 | margin: 0;
20 | font-weight: bold;
21 | display: inline-block;
22 | }
23 | #refresh {
24 | font-size: 80%;
25 | margin-left: 10px;
26 | }
27 | .container {
28 | border: 2px solid #ECECEC;
29 | }
30 | .header {
31 | background: #ECECEC;
32 | padding: 5px;
33 | }
34 | .suggestions {
35 | border: 2px solid #ECECEC;
36 | }
37 | ul {
38 | margin: 0;
39 | padding: 0;
40 | }
41 | li {
42 | list-style: outside none none;
43 | padding: 5px;
44 | height: 40px;
45 | }
46 | li img {
47 | width: 40px;
48 | height: 40px;
49 | border-radius: 20px;
50 | vertical-align: middle;
51 | }
52 | </style>
53 | </head>
54 | <body>
55 | <div class="container">
56 | <div class="header">
57 | <h2>Who to follow</h2><a href="#" id="refresh">Refresh</a>
58 | </div>
59 | <ul class="suggestions">
60 | <li>
61 | <img />
62 | <a href="#" target="_blank" class="username">this will not be displayed</a>
63 | <a href="#" id="remove0" class="close">x</a>
64 | </li>
65 | <li>
66 | <img />
67 | <a href="#" target="_blank" class="username">neither this</a>
68 | <a href="#" id="remove1" class="close">x</a>
69 | </li>
70 | <li>
71 | <img />
72 | <a href="#" target="_blank" class="username">nor this</a>
73 | <a href="#" id="remove2" class="close">x</a>
74 | </li>
75 | </ul>
76 | </div>
77 | <p>
78 | <a href="https://github.com/paldepind/flyd/blob/master/examples/who-to-follow/script.js">See the source code</a>
79 | </p>
80 | </body>
81 | </html>
82 |
--------------------------------------------------------------------------------
/examples/who-to-follow/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "who-to-follow",
3 | "version": "1.0.0",
4 | "private": "true",
5 | "description": "",
6 | "main": "script.js",
7 | "scripts": {
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "author": "",
11 | "license": "MIT",
12 | "dependencies": {
13 | "flyd": "^0.1.6",
14 | "whatwg-fetch": "^0.9.0"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/examples/who-to-follow/script.js:
--------------------------------------------------------------------------------
1 | var flyd = require('../../lib');
2 | require('whatwg-fetch');
3 |
4 | document.addEventListener('DOMContentLoaded', function() {
5 | var suggestionsContainerElm = document.querySelector('.suggestions');
6 | var suggestionsElms = suggestionsContainerElm.children;
7 |
8 | function update(model, action) { // Take action & model, return updated model
9 | if (action.type === 'refresh') {
10 | return {loaded: [], suggested: []};
11 | } else if (action.type === 'loaded') {
12 | return {loaded: action.data, suggested: action.data.slice(0, 3)};
13 | } else if (action.type === 'remove') {
14 | return {
15 | loaded: model.loaded,
16 | suggested: model.suggested.map(function(sug, i) {
17 | return action.nr === i ? model.loaded[Math.floor(Math.random()*model.loaded.length)]
18 | : sug;
19 | })
20 | };
21 | }
22 | }
23 |
24 | function render(model) { // Take model, modify DOM
25 | if (model.suggested.length === 0) {
26 | suggestionsContainerElm.style.visibility = 'hidden';
27 | } else {
28 | suggestionsContainerElm.style.visibility = 'visible';
29 | model.suggested.forEach(function(user, i) {
30 | var suggestionElm = suggestionsElms[i];
31 | var usernameElm = suggestionElm.querySelector('.username');
32 | usernameElm.href = user.html_url;
33 | usernameElm.textContent = user.login;
34 | var imgEl = suggestionElm.querySelector('img');
35 | imgEl.src = '';
36 | imgEl.src = user.avatar_url;
37 | });
38 | }
39 | }
40 |
41 | var initialState = {
42 | loaded: [],
43 | suggested: [],
44 | };
45 |
46 | // Streams
47 | var action$ = flyd.stream();
48 | var model$ = flyd.scan(update, initialState, action$);
49 | flyd.map(render, model$);
50 |
51 | function makeRequest() {
52 | var randomOffset = Math.floor(Math.random()*500);
53 | return fetch('https://api.github.com/users?since=' + randomOffset)
54 | .then(function(res) { return res.json(); })
55 | .then(function(data) { action$({type: 'loaded', data: data}); });
56 | }
57 | makeRequest();
58 | function sendRemoveAction(idx) {
59 | action$({type: 'remove', nr: idx});
60 | }
61 | document.getElementById('refresh').addEventListener('click', makeRequest);
62 | document.getElementById('remove0').addEventListener('click', sendRemoveAction.bind(null, 0));
63 | document.getElementById('remove1').addEventListener('click', sendRemoveAction.bind(null, 1));
64 | document.getElementById('remove2').addEventListener('click', sendRemoveAction.bind(null, 2));
65 | });
66 |
--------------------------------------------------------------------------------
/flyd.min.js:
--------------------------------------------------------------------------------
1 | !function(n,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):n.flyd=t()}(this,function(){"use strict";var n=function(n,t){switch(n){case 0:return function(){return t.apply(this,arguments)};case 1:return function(n){return t.apply(this,arguments)};case 2:return function(n,e){return t.apply(this,arguments)};case 3:return function(n,e,r){return t.apply(this,arguments)};case 4:return function(n,e,r,u){return t.apply(this,arguments)};case 5:return function(n,e,r,u,a){return t.apply(this,arguments)};case 6:return function(n,e,r,u,a,i){return t.apply(this,arguments)};case 7:return function(n,e,r,u,a,i,s){return t.apply(this,arguments)};case 8:return function(n,e,r,u,a,i,s,o){return t.apply(this,arguments)};case 9:return function(n,e,r,u,a,i,s,o,d){return t.apply(this,arguments)};case 10:return function(n,e,r,u,a,i,s,o,d,f){return t.apply(this,arguments)};default:throw new Error("First argument to _arity must be a non-negative integer no greater than ten")}};var t=function(n){return null!=n&&"object"==typeof n&&!0===n["@@functional/placeholder"]};var e=function(n){return function e(r){return 0===arguments.length||t(r)?e:n.apply(this,arguments)}};var r=function e(r,u,a){return function(){for(var i=[],s=0,o=r,d=0;d<u.length||s<arguments.length;){var f;d<u.length&&(!t(u[d])||s>=arguments.length)?f=u[d]:(f=arguments[s],s+=1),i[d]=f,t(f)||(o-=1),d+=1}return o<=0?a.apply(this,i):n(o,e(r,i,a))}},u=function(n){return function r(u,a){switch(arguments.length){case 0:return r;case 1:return t(u)?r:e(function(t){return n(u,t)});default:return t(u)&&t(a)?r:t(u)?e(function(t){return n(t,a)}):t(a)?e(function(t){return n(u,t)}):n(u,a)}}}(function(t,u){return 1===t?e(u):n(t,r(t,[],u))});function a(){return!0}var i,s=[],o=[],d=-1,f=!1,c=!1;var p={};function l(n,t){var e,r,u,i,s=w([],a);for(u=[],i=[],e=0;e<t.length;++e)void 0!==t[e]&&(u.push(t[e]),void 0!==t[e].end&&i.push(t[e].end));return(r=w(u,n)).depsChanged=[],r.fnArgs=r.deps.concat([r,r.depsChanged]),r.end=s,s.listeners.push(r),S(i,s),s.deps=i,A(r),r}function h(n,t){return l(function(t,e){e(n(t.val))},[t])}function v(n){return h(n,this)}function g(n){return n(this)}function y(n){return m(n,this)}function m(n,t){var e=p.stream(1),r=p.on(function(){var n=e()-1;e(n),n<=0&&e.end(!0)});r(t.end);var u=p.stream(),a=p.combine(function(t,a){u.end(!0);var i=n(t());e(e()+1),r(i.end),u=h(a,i)},[t]);return p.endsOn(e.end,a),a}function C(n,t){return l(function(n,t,e){e(n.val(t.val))},[t,n])}function U(n){return C(n,this)}function V(n){return C(this,n)}function M(){return"stream("+this.val+")"}function b(){function n(t){return 0===arguments.length?n.val:(function n(t,e){e.val=t;e.hasVal=!0;void 0===i?(c=!0,function(n){var t,e,r,u=n.listeners;for(t=0;t<u.length;++t)(r=u[t]).end===n?N(r):(void 0!==r.depsChanged&&r.depsChanged.push(n),r.shouldUpdate=!0,O(r));for(;d>=0;--d)!0===(e=o[d]).shouldUpdate&&A(e),e.queued=!1}(e),s.length>0&&x(),c=!1):i===e?function(n,t){var e,r;for(e=0;e<t.length;++e)(r=t[e]).end!==n?(void 0!==r.depsChanged&&r.depsChanged.push(n),r.shouldUpdate=!0):N(r)}(e,e.listeners):q(function(e){n(t,e)},e)}(t,n),n)}return n.hasVal=!1,n.val=void 0,n.updaters=[],n.listeners=[],n.queued=!1,n.end=void 0,n.ap=U,n["fantasy-land/map"]=n.map=v,n["fantasy-land/ap"]=V,n["fantasy-land/of"]=n.of=p.stream,n["fantasy-land/chain"]=n.chain=y,n.pipe=g,n.constructor=p.stream,n.toJSON=function(){return n.val},n.toString=M,n}function w(n,t){var e=b();return e.fn=t,e.deps=n,e.depsMet=!1,e.depsChanged=n.length>0?[]:void 0,e.shouldUpdate=!1,S(n,e),e}function A(n){var t;if((!(t=n).end||!0!==t.end.val)&&function(n){return!0===n.depsMet||function(n){return n.depsMet=n.deps.every(function(n){return n.hasVal}),n.depsMet}(n)}(n))if(void 0===i){i=n,n.depsChanged&&(n.fnArgs[n.fnArgs.length-1]=n.depsChanged);var e=n.fn.apply(n.fn,n.fnArgs);void 0!==e&&n(e),i=void 0,void 0!==n.depsChanged&&(n.depsChanged=[]),n.shouldUpdate=!1,!1===(f||c)&&x(),function(n){return n.listeners.some(function(n){return n.shouldUpdate})}(n)&&(c?n.listeners.forEach(function(n){n.shouldUpdate&&q(A,n)}):n(n.val))}else q(A,n)}function O(n){var t,e=n.listeners;if(!1===n.queued){for(n.queued=!0,t=0;t<e.length;++t)O(e[t]);o[++d]=n}}function q(n,t){s.push(t),t.updaters.push(n),t.shouldUpdate=!0}function x(){for(f=!0;s.length>0;){var n=s.shift(),t=n.updaters.shift();t&&n.shouldUpdate&&t(n)}f=!1}function S(n,t){for(var e=0;e<n.length;++e)n[e].listeners.push(t)}function j(n,t){t[t.indexOf(n)]=t[t.length-1],t.length--}function E(n){for(var t=0;t<n.deps.length;++t)j(n,n.deps[t].listeners);n.deps.length=0}function N(n){void 0!==n.deps&&E(n),void 0!==n.end&&E(n.end)}function P(){}return p.stream=function(n){var t=w([],a),e=b();return e.end=t,e.fnArgs=[],t.listeners.push(e),arguments.length>0&&e(n),e},p.stream["fantasy-land/of"]=p.stream.of=p.stream,p.combine=u(2,l),p.isStream=function(n){return!!((t=n)&&t.constructor&&t.call&&t.apply)&&"hasVal"in n;var t},p.immediate=function(n){return!1===n.depsMet&&(n.depsMet=!0,A(n)),n},p.endsOn=function(n,t){return E(t.end),n.listeners.push(t.end),t.end.deps.push(n),t},p.map=u(2,h),p.chain=u(2,m),p.ap=u(2,C),p.on=u(2,function(n,t){return l(function(t){n(t.val)},[t])}),p.scan=u(3,function(n,t,e){var r=l(function(e,r){r(t=n(t,e.val))},[e]);return r.hasVal||r(t),r}),p.merge=u(2,function(n,t){var e=p.immediate(l(function(n,t,e,r){r[0]?e(r[0]()):n.hasVal?e(n.val):t.hasVal&&e(t.val)},[n,t]));return p.endsOn(l(function(){return!0},[n.end,t.end]),e),e}),p.transduce=u(2,function(n,t){return n=n(new P),l(function(t,e){var r=n["@@transducer/step"](void 0,t.val);return r&&!0===r["@@transducer/reduced"]?(e.end(!0),r["@@transducer/value"]):r},[t])}),p.curryN=u,p.fromPromise=function(n){var t=p.stream();return n.then(function(n){t(n),t.end(!0)}),t},p.flattenPromise=function(n){return l(function(n,t){n().then(t)},[n])},P.prototype["@@transducer/init"]=function(){},P.prototype["@@transducer/result"]=function(){},P.prototype["@@transducer/step"]=function(n,t){return t},p});
2 |
--------------------------------------------------------------------------------
/index.d.ts:
--------------------------------------------------------------------------------
1 | type CurriedFunction2<T1, T2, R> = ((t1: T1, t2: T2) => R) & ((t1: T1, ...rest: Array<void>) => (t2: T2) => R);
2 |
3 | declare namespace flyd {
4 | interface Stream<T> {
5 | (): T;
6 | (value: T): Stream<T>;
7 | (value: Promise<T> | PromiseLike<T>): Stream<T>;
8 |
9 |
10 | map<V>(project: (value: T) => V): Stream<V>;
11 | ap<A, B>(this: Stream<(value: A) => B>, stream: Stream<A>): Stream<B>;
12 | chain<V>(project: (value: T) => Stream<V>): Stream<V>;
13 | of<V>(...values: V[]): Stream<V>;
14 |
15 | pipe<V>(operator: (input: Stream<T>) => Stream<V>): Stream<V>;
16 |
17 | ['fantasy-land/map']<V>(project: (value: T) => V): Stream<V>;
18 | ['fantasy-land/ap']<V>(fn: (value: Stream<T>) => V): Stream<V>;
19 | ['fantasy-land/chain']<V>(project: (value: T) => Stream<V>): Stream<V>;
20 | ['fantasy-land/of']<V>(...values: V[]): Stream<V>;
21 |
22 | end: Stream<boolean>;
23 | val: T;
24 | hasVal: boolean;
25 | }
26 |
27 | interface Combine {
28 | <T, R>(fn: (value: Stream<T>, self: Stream<R>) => R | void, streams: [Stream<T>]): Stream<R>;
29 | <T, T1, R>(
30 | fn: (value: Stream<T>, t1: Stream<T1>, self: Stream<R>) => R | void,
31 | streams: [Stream<T>, Stream<T1>]
32 | ): Stream<R>;
33 | <T, T1, T2, R>(
34 | fn: (value: Stream<T>, t1: Stream<T1>, t2: Stream<T2>, self: Stream<R>) => R | void,
35 | streams: [Stream<T>, Stream<T1>, Stream<T2>]
36 | ): Stream<R>;
37 |
38 | <T, T1, T2, T3, R>(
39 | fn: (value: Stream<T>, t1: Stream<T1>, t2: Stream<T2>, t3: Stream<T3>, self: Stream<R>) => R | void,
40 | streams: [Stream<T>, Stream<T1>, Stream<T2>, Stream<T3>]
41 | ): Stream<R>;
42 | }
43 |
44 | interface CreateStream {
45 | <T>(): Stream<T>;
46 | <T>(value: T): Stream<T>;
47 | <T>(value: Promise<T> | PromiseLike<T>): Stream<T>;
48 | (): Stream<void>;
49 | }
50 |
51 | interface Static {
52 | stream: CreateStream;
53 |
54 | immediate<T>(stream: Stream<T>): Stream<T>;
55 | isStream(stream: any): boolean;
56 |
57 | combine: Combine;
58 | endsOn<T>(end$: Stream<any>, stream: Stream<T>): Stream<T>;
59 |
60 | map<T, V>(accessor: (value: T) => V): (stream: Stream<T>) => Stream<V>;
61 | map<T, V>(accessor: (value: T) => V, stream: Stream<T>): Stream<V>;
62 |
63 | ap<A, B>(value$: Stream<A>, transform$: Stream<(value: A) => B>): Stream<B>;
64 | ap<A>(value$: Stream<A>): <B>(transform$: Stream<(value: A) => B>) => Stream<B>
65 |
66 | chain<T, V>(accessor: (value: T) => Stream<V>): (stream: Stream<T>) => Stream<V>;
67 | chain<T, V>(accessor: (value: T) => Stream<V>, stream: Stream<T>): Stream<V>;
68 |
69 | on<T>(onfn: (value: T) => void): (stream: Stream<T>) => Stream<void>;
70 | on<T>(onfn: (value: T) => void, stream: Stream<T>): Stream<void>;
71 |
72 | scan<T, V>(reducer: (acc: T, value: V) => T, initial: T, stream: Stream<V>): Stream<T>;
73 | scan<T, V>(reducer: (acc: T, value: V) => T, initial: T): (stream: Stream<V>) => Stream<T>;
74 | scan<T, V>(reducer: (acc: T, value: V) => T): (initial: T) => (stream: Stream<V>) => Stream<T>;
75 |
76 | merge<T, V>(stream1: Stream<T>, stream2: Stream<V>): Stream<T | V>;
77 | merge<T>(stream1: Stream<T>): <V>(stream2: Stream<V>) => Stream<T | V>;
78 |
79 | transduce<T, V>(mapfn: Function, stream: Stream<T>): Stream<V>;
80 | transduce<T, V>(mapfn: Function): (stream: Stream<T>) => Stream<V>;
81 |
82 | fromPromise<T>(promise: PromiseLike<T>): Stream<T>;
83 | flattenPromise<T>(promise$: Stream<PromiseLike<T>>): Stream<T>;
84 |
85 | curryN(length: number, fn: (...args: Array<any>) => void): Function;
86 | }
87 | }
88 |
89 | declare module 'flyd' {
90 | const f: flyd.Static;
91 | export = f;
92 | }
93 |
94 | declare module 'flyd/module/aftersilence' {
95 | interface aftersilence {
96 | <T>(delay: number, stream: flyd.Stream<T>): flyd.Stream<T[]>;
97 | <T>(delay: number): (stream: flyd.Stream<T>) => flyd.Stream<T[]>;
98 | }
99 | export = aftersilence;
100 | }
101 | declare module 'flyd/module/droprepeats' {
102 | interface dropRepeats {
103 | <T>(s: flyd.Stream<T>): flyd.Stream<T>;
104 | }
105 | interface dropRepeatsWith {
106 | <T>(isEqual: (a: T, b: T) => boolean, stream: flyd.Stream<T>): flyd.Stream<T>;
107 | <T>(isEqual: (a: T, b: T) => boolean): (stream: flyd.Stream<T>) => flyd.Stream<T>;
108 | }
109 |
110 | export const dropRepeats: dropRepeats;
111 | export const dropRepeatsWith: dropRepeatsWith;
112 | }
113 |
114 | declare module 'flyd/module/every' {
115 | interface every {
116 | (ms: number): flyd.Stream<true>;
117 | }
118 | const _every: every;
119 | export = _every;
120 | }
121 |
122 | declare module 'flyd/module/filter' {
123 | interface Filter {
124 | <T, V extends T>(project: (val: T) => val is V, stream: flyd.Stream<T>): flyd.Stream<V>;
125 | <T, V extends T>(project: (val: T) => val is V): (stream: flyd.Stream<T>) => flyd.Stream<V>;
126 | <T>(predicate: (val: T) => any, stream: flyd.Stream<T>): flyd.Stream<T>;
127 | <T>(predicate: (val: T) => any): (stream: flyd.Stream<T>) => flyd.Stream<T>;
128 | }
129 | const _Filter: Filter;
130 | export = _Filter;
131 | }
132 |
133 | declare module 'flyd/module/forwardto' {
134 | interface ForwardTo {
135 | <T, V>(stream: flyd.Stream<V>, project: (value: V) => T): flyd.Stream<T>;
136 | <V>(stream: flyd.Stream<V>): <T>(project: (value: V) => T) => flyd.Stream<T>;
137 | }
138 | const _ForwardTo: ForwardTo;
139 | export = _ForwardTo;
140 | }
141 |
142 | declare module 'flyd/module/inlast' {
143 | interface InLast {
144 | <T>(ms: number, stream: flyd.Stream<T>): flyd.Stream<T[]>;
145 | (ms: number): <T>(stream: flyd.Stream<T>) => flyd.Stream<T[]>;
146 | }
147 |
148 | const _InLast: InLast;
149 | export = _InLast;
150 | }
151 |
152 | declare module 'flyd/module/keepwhen' {
153 | interface KeepWhen {
154 | <T>(when: flyd.Stream<boolean>, stream: flyd.Stream<T>): flyd.Stream<T>;
155 | (when: flyd.Stream<boolean>): <T>(stream: flyd.Stream<T>) => flyd.Stream<T>;
156 | }
157 | const _KeepWhen: KeepWhen;
158 | export = _KeepWhen;
159 | }
160 |
161 | declare module 'flyd/module/lift' {
162 | interface Lift {
163 | <T1, T2, R>(liftFn: (t1: T1, t2: T2) => R, s1: flyd.Stream<T1>, s2: flyd.Stream<T2>): flyd.Stream<R>;
164 | <T1, T2, T3, R>(liftFn: (t1: T1, t2: T2, t3: T3) => R, s1: flyd.Stream<T1>, s2: flyd.Stream<T2>, s3: flyd.Stream<T3>): flyd.Stream<R>;
165 | <T1, T2, T3, T4, R>(liftFn: (t1: T1, t2: T2, t3: T3, t4: T4) => R, s1: flyd.Stream<T1>, s2: flyd.Stream<T2>, s3: flyd.Stream<T3>, s4: flyd.Stream<T4>): flyd.Stream<R>;
166 | <T>(liftFn: (...rest: any[]) => T, ...streams: flyd.Stream<any>[]): flyd.Stream<T>;
167 | }
168 |
169 | const _Lift: Lift;
170 | export = _Lift;
171 | }
172 |
173 | declare module 'flyd/module/mergeall' {
174 | interface MergeAll {
175 | <T1, T2>(streams: [flyd.Stream<T1>, flyd.Stream<T2>]): flyd.Stream<T1 | T2>;
176 | <T1, T2, T3>(streams: [flyd.Stream<T1>, flyd.Stream<T2>, flyd.Stream<T3>]): flyd.Stream<T1 | T2 | T3>;
177 | <T>(streams: flyd.Stream<T>[]): flyd.Stream<T>;
178 | }
179 | const _MergeAll: MergeAll;
180 | export = _MergeAll;
181 | }
182 |
183 | declare module 'flyd/module/obj' {
184 | interface ObjModule {
185 | streamProps<T>(obj: T): { [P in keyof T]: flyd.Stream<T[P]> };
186 | stream<T extends { [key: string]: flyd.Stream<any> }>(obj: T): flyd.Stream<{ [P in keyof T]: T[P]['val'] }>;
187 | extractProps(obj: any): any;
188 | }
189 |
190 | const _ObjModule: ObjModule;
191 | export = _ObjModule;
192 | }
193 |
194 | declare module 'flyd/module/previous' {
195 | type previous = <T>(stream: flyd.Stream<T>) => flyd.Stream<T>;
196 | const _previous: previous;
197 | export = _previous;
198 | }
199 |
200 | declare module 'flyd/module/sampleon' {
201 | interface SampleOn {
202 | <T>(samplewhen: flyd.Stream<any>, stream: flyd.Stream<T>): flyd.Stream<T>;
203 | (samplewhen: flyd.Stream<any>): <T>(stream: flyd.Stream<T>) => flyd.Stream<T>;
204 | }
205 | const _SampleOn: SampleOn;
206 | export = _SampleOn;
207 | }
208 |
209 | declare module 'flyd/module/scanmerge' {
210 | type ScanFn<T, V> = (acc: T, value: V) => T;
211 | interface ScanMerge {
212 | <T, V>(pairs: Array<[flyd.Stream<V>, ScanFn<T, V>]>, initial: T): flyd.Stream<T>;
213 | <T, V>(pairs: Array<[flyd.Stream<V>, ScanFn<T, V>]>): (initial: T) => flyd.Stream<T>;
214 | }
215 | const _ScanMerge: ScanMerge;
216 | export = _ScanMerge;
217 | }
218 |
219 | declare module 'flyd/module/switchlatest' {
220 | interface SwitchLatest {
221 | <T>(stream: flyd.Stream<flyd.Stream<T>>): flyd.Stream<T>;
222 | }
223 | const _SwitchLatest: SwitchLatest;
224 | export = _SwitchLatest;
225 | }
226 |
227 | declare module 'flyd/module/takeuntil' {
228 | interface takeuntil {
229 | <T, V>(source: flyd.Stream<T>, end: flyd.Stream<V>): flyd.Stream<T>;
230 | <T>(source: flyd.Stream<T>): <V>(end: flyd.Stream<V>) => flyd.Stream<T>;
231 | }
232 | const _takeuntil: takeuntil;
233 | export = _takeuntil;
234 | }
235 |
--------------------------------------------------------------------------------
/module/aftersilence/README.md:
--------------------------------------------------------------------------------
1 | # flyd-aftersilence
2 | Buffers values from a source stream into an array and emits the array once the source stream has had the specified duration of silence.
3 |
4 | __Graph__
5 |
6 | ```marbles
7 | (ticks represent 10ms)
8 | a: {-1-2-3--5-6-}
9 | afterSilence(20, a): {--------.---}
10 | [1,2,3]
11 | ```
12 |
13 | __Signature__
14 |
15 | `(Integer, Stream a) -> Stream b`
16 |
17 | __Example__
18 |
19 | ```javascript
20 | const afterSilence = require('flyd/module/aftersilence')
21 |
22 | const source = flyd.stream()
23 | const result = flyd.afterSilence(100, source)
24 |
25 | source(1); source(2); source(3)
26 | result() // undefined
27 |
28 | // wait 100ms and print result
29 | setTimeout(() => console.log(result()), 100)
30 | // -> prints [1,2,3]
31 | ```
32 |
--------------------------------------------------------------------------------
/module/aftersilence/index.js:
--------------------------------------------------------------------------------
1 | var flyd = require('../../lib');
2 |
3 | module.exports = flyd.curryN(2, function(dur, s) {
4 | var scheduled;
5 | var buffer = [];
6 | return flyd.combine(function(s, self) {
7 | buffer.push(s());
8 | clearTimeout(scheduled);
9 | scheduled = setTimeout(function() {
10 | self(buffer);
11 | buffer = [];
12 | }, dur);
13 | }, [s]);
14 | });
15 |
--------------------------------------------------------------------------------
/module/aftersilence/test/index.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var flyd = require('../../../lib');
3 | var stream = flyd.stream;
4 |
5 | var afterSilence = require('../index.js');
6 |
7 | // KISS way of testing time dependent code :)
8 |
9 | describe('afterSilence', function() {
10 | it('correctly buffers values', function(done) {
11 | var result = [];
12 | var i = 0;
13 | var s1 = stream();
14 | var push = function() {
15 | s1(i++);
16 | };
17 | var s2 = afterSilence(50, s1);
18 | flyd.map(function(vs) {
19 | result.push(vs);
20 | }, s2);
21 | setTimeout(push, 20);
22 | setTimeout(push, 30);
23 | setTimeout(push, 40);
24 | setTimeout(push, 95);
25 | setTimeout(push, 100);
26 | setTimeout(push, 110);
27 | setTimeout(push, 120);
28 | setTimeout(push, 175);
29 | setTimeout(function() {
30 | assert.deepEqual(result, [
31 | [0, 1, 2],
32 | [3, 4, 5, 6],
33 | [7]
34 | ]);
35 | done();
36 | }, 240);
37 | });
38 | it('only emits values after specified silence', function(done) {
39 | var result = [];
40 | var i = 0;
41 | var s1 = stream();
42 | var push = function() {
43 | s1(i++);
44 | };
45 | var s2 = afterSilence(20, s1);
46 | flyd.map(function(vs) {
47 | result.push(vs);
48 | }, s2);
49 | setTimeout(push, 10);
50 | setTimeout(push, 20);
51 | setTimeout(push, 30);
52 | setTimeout(push, 40);
53 | setTimeout(function() {
54 | assert.equal(result.length, 0);
55 | }, 50);
56 | setTimeout(function() {
57 | assert.deepEqual(result, [[0, 1, 2, 3]]);
58 | done();
59 | }, 65);
60 | });
61 | });
62 |
--------------------------------------------------------------------------------
/module/batchwhen/README.md:
--------------------------------------------------------------------------------
1 | # flyd-batchwhen
2 |
3 | Batches values from the second stream (sA) based on the the first stream (sBool)
4 | as a control signal. When sBool is false, sA are passed through as a single
5 | element list. When sBool is true, then values feom sA are batched into a list,
6 | and the batch is emitted when sBool returns to false. This function is convenient
7 | for throttling user inputs.
8 |
9 | # Usage
10 |
11 | ```js
12 | var action$ = flyd.stream()
13 | var throttle$ = flyd.stream(false)
14 | var batchedAction$ = flyd.batchWhen(throttle$, action$)
15 |
16 | action$(1)
17 | // batchedAction$ => [1]
18 | action$(2)
19 | // batchedAction$ => [2]
20 | throttle$(true)
21 | action$(3)
22 | action$(4)
23 | throttle$(false)
24 | // batchedAction$ => [3, 4]
25 | throttle$(true)
26 | throttle$(false)
27 | ```
--------------------------------------------------------------------------------
/module/batchwhen/index.js:
--------------------------------------------------------------------------------
1 | var flyd = require('../../lib');
2 | var dropRepeats = require('../droprepeats').dropRepeats;
3 | var contains = require('ramda/src/contains');
4 |
5 | // Stream bool -> Stream a -> Stream a
6 | module.exports = flyd.curryN(2, function(sBool, sA) {
7 | var batch = [];
8 |
9 | var ns = flyd.combine(function(sBool, sA, self, changed) {
10 |
11 | var sBoolChanged = contains(sBool, changed);
12 | var sAChanged = contains(sA, changed);
13 |
14 |
15 | if (sA() !== undefined) {
16 | // if A is undefined then we dont batch anything
17 | if (sBoolChanged) {
18 | if (sAChanged) {
19 | if (sBool()) {
20 | // if Bool and A change and were batching then
21 | // push to the batch
22 | batch.push(sA());
23 | } else {
24 | // if Bool and A change and we're not batching
25 | // anymore, then push the batch
26 | batch.push(sA());
27 | self(batch);
28 | batch = [];
29 | }
30 | } else {
31 | if (!sBool()) {
32 | // if Bool changed but A didnt then push the batch
33 | // if there were any batching
34 | if (batch.length > 0) {
35 | self(batch);
36 | batch = [];
37 | }
38 | }
39 | }
40 | } else if (sAChanged) {
41 | if (sBool()) {
42 | // if we're batching then push to the batch
43 | batch.push(sA());
44 | } else {
45 | // otherwise send it alone
46 | self([sA()]);
47 | }
48 | } else {
49 | // when we just initialize
50 | // if theres a value in A
51 | if (sBool()) {
52 | batch.push(sA());
53 | } else {
54 | self([sA()]);
55 | }
56 | }
57 | }
58 |
59 | }, [dropRepeats(sBool), sA]);
60 |
61 | return ns;
62 | });
63 |
--------------------------------------------------------------------------------
/module/batchwhen/test/index.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var flyd = require('../../../lib');
3 | var stream = flyd.stream;
4 |
5 | var batchWhen = require('../index.js');
6 |
7 | describe('batchWhen', function() {
8 | it('batches the second stream with the first stream, initally false', function() {
9 | var result = [];
10 | var s = stream(1);
11 | var b = stream(false);
12 | var k = batchWhen(b, s);
13 | flyd.map(function(v) {
14 | result.push(v);
15 | }, k);
16 | s(2);
17 | b(true);
18 | s(3);
19 | s(4);
20 | b(false);
21 | b(true);
22 | b(false);
23 | s(5);
24 | assert.deepEqual(result, [[1], [2], [3, 4], [5]]);
25 | });
26 |
27 | it('batches the second stream with the first stream, initially true', function() {
28 | var result = [];
29 | var s = stream(1);
30 | var b = stream(true);
31 | var k = batchWhen(b, s);
32 | flyd.map(function(v) {
33 | result.push(v);
34 | }, k);
35 | s(2);
36 | b(false);
37 | s(3);
38 | s(4);
39 | b(true);
40 | b(false);
41 | b(true);
42 | b(false);
43 | s(5);
44 | assert.deepEqual(result, [[1, 2], [3], [4], [5]]);
45 | });
46 |
47 | it('batches the second stream with the first stream, initially true, with no value', function() {
48 | var result = [];
49 | var s = stream();
50 | var b = stream(true);
51 | var k = batchWhen(b, s);
52 | flyd.map(function(v) {
53 | result.push(v);
54 | }, k);
55 | s(2);
56 | s(3);
57 | b(false);
58 | s(4);
59 | b(true);
60 | b(false);
61 | b(true);
62 | b(false);
63 | s(5);
64 | assert.deepEqual(result, [[2, 3], [4], [5]]);
65 | });
66 |
67 | it('batches the second stream with the first stream, initially false, with no value', function() {
68 | var result = [];
69 | var s = stream();
70 | var b = stream(false);
71 | var k = batchWhen(b, s);
72 | flyd.map(function(v) {
73 | result.push(v);
74 | }, k);
75 | s(2);
76 | b(true);
77 | s(3);
78 | s(4);
79 | b(false);
80 | b(true);
81 | b(false);
82 | s(5);
83 | assert.deepEqual(result, [[2], [3, 4], [5]]);
84 | });
85 |
86 | });
87 |
--------------------------------------------------------------------------------
/module/diff/README.md:
--------------------------------------------------------------------------------
1 | # flyd-diff
2 |
3 | Similar to map, but this function gets both the previous and the current value of the stream.
4 |
5 | __Graph__
6 |
7 | ```
8 | a: {-1-1-2-3-5-}
9 |
10 | diff(add, a): {---2-3-5-8-}
11 | ```
12 |
13 | __Signature__
14 |
15 | `((a, a) -> a) -> Stream a -> Stream a`
16 |
17 | __Usage__
18 |
19 | ```
20 | const diff = require('flyd/module/diff')
21 |
22 | const velocity = flyd.stream(0)
23 | const acceleration = diff((previous, current) => current - previous, velocity)
24 |
25 | velocity(2)(5)
26 | acceleration() // 3
27 |
28 | velocity(1)
29 | acceleration() // -4
30 | ```
31 |
--------------------------------------------------------------------------------
/module/diff/index.js:
--------------------------------------------------------------------------------
1 | var flyd = require('../../lib');
2 |
3 | var previous = require('../previous');
4 |
5 | module.exports = flyd.curryN(2, function(diffFunc, s) {
6 | var prevS = previous(s);
7 | return flyd.combine(function() {
8 | return diffFunc(prevS(), s());
9 | }, [s, prevS]);
10 | });
11 |
--------------------------------------------------------------------------------
/module/diff/test/index.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var flyd = require('../../../lib');
3 | var stream = flyd.stream;
4 |
5 | var diff = require('../index.js');
6 |
7 | describe('diff', function() {
8 | it('calls the diff function with the previous and new value', function() {
9 | var s = stream(1);
10 | var returnArguments = function() {
11 | return Array.prototype.slice.call(arguments);
12 | };
13 | var d = diff(returnArguments, s);
14 | s(1)(2)(3);
15 | assert.deepEqual(d(), [2, 3]);
16 | });
17 |
18 | it('starts streaming after the second value is pushed into the source stream', function() {
19 | var s = stream();
20 | var calls = 0;
21 | flyd.on();
22 | diff(function() { calls += 1; }, s);
23 | s(1);
24 | assert.equal(calls, 0);
25 | s(2);
26 | assert.equal(calls, 1);
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/module/droprepeats/README.md:
--------------------------------------------------------------------------------
1 | # flyd-droprepeats
2 |
3 | Drops consecutively repeated values from a
4 | [Flyd](https://github.com/paldepind/flyd) stream. Equality is determined by reference.
5 |
6 | ## dropRepeats(s)
7 |
8 | __Graph__
9 |
10 | ```
11 | a: {---11--12-2-3-4-}
12 | dropRepeats(a): {---1----2---3-4-}
13 | ```
14 |
15 | __Signature__
16 |
17 | `Stream a -> Stream a`
18 |
19 | __Usage__
20 |
21 | ```js
22 | const dropRepeats = require('flyd/module/droprepeats').dropRepeats
23 |
24 | const s = flyd.stream()
25 | const noRepeats = dropRepeats(s)
26 | const collect = flyd.scan((ls, n) => ls.concat(n), [], noRepeats)
27 | s(1)(2)(2)(3)
28 | collect() // [1, 2, 3]
29 | ```
30 |
31 | ## dropRepeatsWith(fn, s)
32 |
33 | Drops repeated values from stream `s`, but also takes a function `fn` that
34 | will be used to determine equality.
35 |
36 | __Signature__
37 |
38 | `(a -> a -> Boolean) -> Stream a -> Stream a`
39 |
40 | __Usage__
41 |
42 | ```js
43 | const dropRepeatsWith = require('flyd/module/droprepeats').dropRepeatsWith
44 | const s = flyd.stream()
45 |
46 | // Ramda's `equals` determines equality by value
47 | const R = require('ramda')
48 | const noRepeats = dropRepeatsWith(R.equals, s)
49 | const collect = flyd.scan((ls, n) => ls.concat(n), [], noRepeats)
50 | s({ foo: 'bar' })
51 | s({ foo: 'bar' })
52 | collect() // [{ foo: 'bar' }]
53 | ```
54 |
--------------------------------------------------------------------------------
/module/droprepeats/index.js:
--------------------------------------------------------------------------------
1 | var flyd = require('../../lib');
2 |
3 | function dropRepeatsWith(eq, s) {
4 | var prev;
5 | return flyd.combine(function(s, self) {
6 | if (!self.hasVal || !eq(s.val, prev)) {
7 | self(s.val);
8 | prev = s.val;
9 | }
10 | }, [s]);
11 | }
12 |
13 | exports.dropRepeats = function(s) {
14 | return dropRepeatsWith(strictEq, s);
15 | };
16 |
17 | exports.dropRepeatsWith = flyd.curryN(2, dropRepeatsWith);
18 |
19 | function strictEq(a, b) {
20 | return a === b;
21 | }
22 |
--------------------------------------------------------------------------------
/module/droprepeats/test/index.js:
--------------------------------------------------------------------------------
1 | var flyd = require('../../../lib');
2 | var stream = flyd.stream;
3 | var dropRepeats = require('../').dropRepeats;
4 | var dropRepeatsWith = require('../').dropRepeatsWith;
5 | var R = require('ramda');
6 | var assert = require('assert');
7 |
8 | var collect = flyd.scan(R.flip(R.append), []);
9 |
10 | describe('dropRepeats', function() {
11 | it('drops consecutive repeated values', function() {
12 | var s = stream();
13 | var all = collect(dropRepeats(s));
14 | s(1)(2)(2)(3);
15 | assert.deepEqual(all(), [1, 2, 3]);
16 | });
17 |
18 | it('doesn\'t determine equality by value', function() {
19 | var s = stream();
20 | var all = collect(dropRepeats(s));
21 | s({ foo: 'bar' });
22 | s({ foo: 'bar' });
23 | assert.deepEqual(all(), [
24 | { foo: 'bar' },
25 | { foo: 'bar' }
26 | ]);
27 | });
28 | });
29 |
30 | describe('dropRepeatsWith', function() {
31 | it('takes a function for using custom equality logic', function() {
32 | var s = stream();
33 | var all = collect(dropRepeatsWith(R.equals, s));
34 | s({ foo: 'bar' });
35 | s({ foo: 'bar' });
36 | assert.deepEqual(all(), [
37 | { foo: 'bar' }
38 | ]);
39 | });
40 |
41 | it('always includes first value so we can safely test for equality', function() {
42 | var s = stream();
43 | var all = collect(dropRepeatsWith(function(a, b) {
44 | return a[0] === b[0] || a[1] === b[1];
45 | }, s));
46 | s([1, 2]);
47 | s([1, 3]);
48 | s([2, 3]);
49 | assert.deepEqual(all(), [
50 | [1, 2],
51 | [2, 3]
52 | ]);
53 | });
54 |
55 | it('is curried', function() {
56 | var s = stream();
57 | var equalsDropper = dropRepeatsWith(R.equals);
58 | var all = collect(equalsDropper(s));
59 | s({ foo: 'bar' });
60 | s({ foo: 'bar' });
61 | assert.deepEqual(all(), [
62 | { foo: 'bar' }
63 | ]);
64 | });
65 | });
66 |
--------------------------------------------------------------------------------
/module/every/README.md:
--------------------------------------------------------------------------------
1 | # flyd-every
2 | Takes a number of milliseconds `ms` and creates a stream of the current time updated every `ms`.
3 |
4 | The stream emits current timestamp values using `Date.now()` (eg `1475273004713`)
5 |
6 | __Graph__
7 |
8 | ```
9 | (ticks represent 10ms)
10 | every(30): {--t--t--t--t--t-->
11 | ```
12 |
13 | __Signature__
14 |
15 | `Number -> Stream Number`
16 |
17 | __Usage__
18 |
19 | ```javascript
20 | const every = require('flyd/module/every')
21 | const everySecond = every(1000)
22 |
23 | // Print once every second
24 | flyd.on(time => console.log('Current time is', time), everySecond)
25 |
26 | // count every second
27 | const count = flyd.scan(n => n + 1, 0, everySecond)
28 | flyd.map(c => console.log(c), count) // 0 ... 1 ... 2 ... 3 ... 4 ... 5
29 | ```
30 |
--------------------------------------------------------------------------------
/module/every/index.js:
--------------------------------------------------------------------------------
1 | var flyd = require('../../lib');
2 |
3 | module.exports = function(dur) {
4 | var s = flyd.stream();
5 | var target = Date.now();
6 | function timer() {
7 | if (s.end()) return;
8 | var now = Date.now();
9 | target += dur;
10 | s(now);
11 | setTimeout(timer, target - now);
12 | }
13 | timer();
14 | return s;
15 | };
16 |
--------------------------------------------------------------------------------
/module/every/test/browsertest/index.html:
--------------------------------------------------------------------------------
1 | <!DOCTYPE html>
2 | <html>
3 | <head>
4 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 | <title>Every drift test</title>
6 | <script type="text/javascript" src="build.js"></script>
7 | </head>
8 | <body>
9 | </body>
10 | </html>
11 |
--------------------------------------------------------------------------------
/module/every/test/browsertest/script.js:
--------------------------------------------------------------------------------
1 | var flyd = require('flyd');
2 | var every = require('../every.js');
3 |
4 | var startTime;
5 | var dur = 1000;
6 | var ticks = 0;
7 | var e = every(dur);
8 | flyd.map(function(t) {
9 | startTime === undefined ? startTime = t : ++ticks;
10 | console.log(t);
11 | console.log('Drift: ' + (startTime + (ticks * dur) - t));
12 | // console.log(t);
13 | }, e);
14 |
--------------------------------------------------------------------------------
/module/every/test/index.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var flyd = require('../../../lib');
3 | var every = require('../index.js');
4 |
5 | describe('every', function() {
6 | var e;
7 | afterEach(function() {
8 | e.end(true);
9 | });
10 | it('invokes callback the correct amount of times', function(done) {
11 | var times = 0;
12 | e = every(50);
13 | flyd.map(function() { ++times; }, e);
14 | setTimeout(function() {
15 | assert.equal(5, times);
16 | done();
17 | }, 225);
18 | });
19 | it('ends', function(done) {
20 | var times = 0;
21 | e = every(50);
22 | var endVal;
23 | flyd.map(function() { ++times; }, e);
24 | setTimeout(function() {
25 | assert.equal(5, times);
26 | endVal = e();
27 | e.end(true);
28 | setTimeout(function() {
29 | assert.equal(endVal, e());
30 | done();
31 | }, 225);
32 | }, 225);
33 | });
34 | });
35 |
--------------------------------------------------------------------------------
/module/filter/README.md:
--------------------------------------------------------------------------------
1 | # flyd-filter
2 |
3 | Using a predicate function, select only the elements of a stream that the predicate function finds truthy.
4 |
5 | __Graph__
6 |
7 | ```
8 | a: {1--2--3--4--5--}
9 | filter(isEven, a): {---2-----4-----}
10 | ```
11 |
12 | __Signature__
13 |
14 | `(a -> Boolean) -> Stream a -> Stream a`
15 |
16 | __Usage__
17 |
18 | ```javascript
19 | const filter = require('flyd/module/filter')
20 |
21 | const numbers = flyd.stream()
22 | const largeNumbers = filter(n => n > 5, numbers)
23 |
24 | // Collect large numbers into an array
25 | const collect = flyd.scan((ls, n) => ls.concat(n), [], largeNumbers)
26 |
27 | numbers(2)(6)(5)(3)(7)(10)(5);
28 | collect() // [6, 7, 10]
29 | ```
30 |
--------------------------------------------------------------------------------
/module/filter/index.js:
--------------------------------------------------------------------------------
1 | var flyd = require('../../lib');
2 |
3 | module.exports = flyd.curryN(2, function(fn, s) {
4 | return flyd.combine(function(s, self) {
5 | if (fn(s())) self(s.val);
6 | }, [s]);
7 | });
8 |
--------------------------------------------------------------------------------
/module/filter/test/index.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var flyd = require('../../../lib');
3 |
4 | var filter = require('../index.js');
5 |
6 | function over5(n) {
7 | return n > 5;
8 | }
9 |
10 | describe('filter', function() {
11 | it('only lets values passing the filter through', function() {
12 | var result = [];
13 | var numbers = flyd.stream();
14 | var largeNumbers = filter(over5, numbers);
15 | flyd.map(function(n) {
16 | result.push(n);
17 | }, largeNumbers);
18 | numbers(2)(6)(5)(3)(7)(10)(5);
19 | assert.deepEqual(result, [6, 7, 10]);
20 | });
21 | it('is curried', function() {
22 | var numbers = flyd.stream();
23 | assert(filter(over5)(numbers));
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/module/forwardto/README.md:
--------------------------------------------------------------------------------
1 | # flyd-forwardto
2 |
3 | Forward values from one stream into another existing stream.
4 |
5 | Create a new stream that passes all values through a function and forwards them
6 | to a target stream.
7 |
8 | __Graph__
9 |
10 | ```
11 | a: {1---2---3---}
12 | forwardTo(a, parseInt): {--2---3---2-}
13 | flyd.map(square, a): {1-4-4-9-9-4-}
14 | ```
15 |
16 | __Signature__
17 |
18 | `Stream b -> (a -> b) -> Stream a`
19 |
20 | __Example__
21 |
22 | ```javascript
23 | const forwardTo = require('flyd/module/forwardto')
24 | const R = require('ramda')
25 |
26 | // A stream of numbers
27 | const numbers = flyd.stream()
28 | // Another stream that squares the numbers
29 | const squaredNumbers = flyd.map(R.square, numbers)
30 |
31 | // A stream of numbers as strings
32 | // we want to convert them to ints and forward them into the numbers stream above:
33 | const stringNumbers = forwardTo(numbers, parseInt)
34 |
35 | stringNumbers('7')
36 | squaredNumbers() // -> 49
37 | numbers(4)
38 | squaredNumbers() // -> 16
39 | stringNumbers('9')
40 | squaredNumbers() // -> 81
41 | ```
42 |
43 |
--------------------------------------------------------------------------------
/module/forwardto/index.js:
--------------------------------------------------------------------------------
1 | var flyd = require('../../lib');
2 |
3 | module.exports = flyd.curryN(2, function(targ, fn) {
4 | var s = flyd.stream();
5 | flyd.map(function(v) { targ(fn(v)); }, s);
6 | return s;
7 | });
8 |
--------------------------------------------------------------------------------
/module/forwardto/test/index.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var flyd = require('../../../lib');
3 | var forwardTo = require('../index.js');
4 |
5 | describe('forwardTo', function() {
6 | it('forwards values', function() {
7 | var result = [];
8 | var target = flyd.stream();
9 | function fn1(v) { result.push(v); }
10 | function fn2(v) { result.push(2 * v); return v; }
11 | flyd.map(fn1, target);
12 | var fw = forwardTo(target, fn2);
13 | fw(1)(2)(3);
14 | assert.deepEqual(result, [2, 1, 4, 2, 6, 3]);
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/module/inlast/README.md:
--------------------------------------------------------------------------------
1 | # flyd-inlast
2 |
3 | Creates a stream that emits an array of all values from a source stream which where emitted in a specified duration.
4 |
5 | Using a duration `ms`, it will collect all values that are emitted within an `ms` time period, buffering them into an array.
6 |
7 | "Get a list of values that were emitted from a stream __in the last__ n milliseconds"
8 |
9 | Also see [aftersilence](/module/aftersilence).
10 |
11 | __Graph__
12 |
13 | ```
14 | (each tick is 10ms)
15 | a: {--2----3--4-----}
16 | inlast(40, a): {--.----.--.-----}
17 | [2] [3][3,4]
18 | ```
19 |
20 | __Signature__
21 |
22 | ```
23 | Integer -> Stream a -> Stream [a]
24 | ```
25 |
26 | __Usage__
27 |
28 | ```js
29 | const inlast = require('flyd/module/inlast')
30 |
31 | const s = flyd.stream()
32 | const in = inlast(100, s)
33 | in() // -> []
34 | s(1)(2)(3); in() // -> [1,2,3]
35 |
36 | // emit a first value, wait 200ms, then emit a second value.
37 | // in stream will only emit the second most recent value, discarding the older one.
38 | s(1)
39 | setTimeout(()=> {
40 | s(2)
41 | in() // -> [2]
42 | }, 200)
43 | ```
44 |
--------------------------------------------------------------------------------
/module/inlast/index.js:
--------------------------------------------------------------------------------
1 | var flyd = require('../../lib');
2 |
3 | module.exports = flyd.curryN(2, function(dur, s) {
4 | var values = [];
5 | return flyd.combine(function(s, self) {
6 | setTimeout(function() {
7 | self(values = values.slice(1));
8 | }, dur);
9 | return (values = values.concat([s()]));
10 | }, [s]);
11 | });
12 |
--------------------------------------------------------------------------------
/module/inlast/test/index.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var flyd = require('../../../lib');
3 | var stream = flyd.stream;
4 |
5 | var inLast = require('../index.js');
6 |
7 | describe('inLast', function() {
8 | it('adds values', function(done) {
9 | var s = stream();
10 | var lastMs = inLast(50, s);
11 | s(1);
12 | setTimeout(function() {
13 | assert.deepEqual(lastMs(), [1]);
14 | s(2);
15 | }, 20);
16 | setTimeout(function() {
17 | assert.deepEqual(lastMs(), [1, 2]);
18 | done();
19 | }, 40);
20 | });
21 | it('adds and removes values', function(done) {
22 | var s = stream();
23 | var lastMs = inLast(50, s);
24 | s(1);
25 | setTimeout(function() {
26 | assert.deepEqual(lastMs(), [1]);
27 | s(2);
28 | }, 35);
29 | setTimeout(function() {
30 | assert.deepEqual(lastMs(), [1, 2]);
31 | s(3);
32 | }, 40);
33 | setTimeout(function() {
34 | assert.deepEqual(lastMs(), [2, 3]);
35 | s(4);
36 | }, 60);
37 | setTimeout(function() {
38 | assert.deepEqual(lastMs(), [2, 3, 4]);
39 | s(5);
40 | }, 80);
41 | setTimeout(function() {
42 | assert.deepEqual(lastMs(), [4, 5]);
43 | done();
44 | }, 100);
45 | });
46 | it('is updated when values come and go', function(done) {
47 | var result = [];
48 | var s = stream();
49 | var lastMs = inLast(50, s);
50 | flyd.map(function(a) { result.push(a); }, lastMs);
51 | s(1);
52 | setTimeout(function() { s(2); }, 35);
53 | setTimeout(function() { s(3); }, 40);
54 | // 1 leaves
55 | setTimeout(function() { s(4); }, 60);
56 | setTimeout(function() { s(5); }, 80);
57 | // 2 leaves
58 | // 3 leaves
59 | setTimeout(function() {
60 | assert.deepEqual(result, [
61 | [1],
62 | [1, 2],
63 | [1, 2, 3],
64 | [2, 3],
65 | [2, 3, 4],
66 | [2, 3, 4, 5],
67 | [3, 4, 5],
68 | [4, 5]
69 | ]);
70 | done();
71 | }, 100);
72 | });
73 | });
74 |
--------------------------------------------------------------------------------
/module/keepwhen/README.md:
--------------------------------------------------------------------------------
1 | # flyd-keepwhen
2 |
3 | Keeps values from the second stream when the first stream is true (truth is tested with `!== false`).
4 |
5 | __Graph__
6 |
7 | ```
8 | a: {-t---f---t----}
9 | b: {---1---2---3--}
10 | keepWhen(a, b): {---1-------3--}
11 | ```
12 |
13 | __Signature__
14 |
15 | `Stream Boolean -> Stream a -> Stream a`
16 |
17 | __Usage__
18 |
19 | ```
20 | const keepWhen = require('flyd/module/keepwhen')
21 |
22 | const source = flyd.stream()
23 | const test = flyd.stream()
24 | const result = keepWhen(test, source)
25 |
26 | // when stream must !== false
27 | source(1)
28 | result() // -> 1
29 | source(2)
30 | result() // -> 2
31 | test(true)
32 | source(3)
33 | result() // -> 3
34 | test(false)
35 | source(4)
36 | result() // -> 3
37 | test('hi')
38 | source(5)
39 | result() // -> 5
40 | // null or undefined are considered truthy for source
41 | test(null)
42 | source(6)
43 | result() // -> 6
44 | // only false will prevent values from emitting
45 | test(false)
46 | source(7)
47 | result() // -> 6
48 | ```
49 |
--------------------------------------------------------------------------------
/module/keepwhen/index.js:
--------------------------------------------------------------------------------
1 | var flyd = require('../../lib');
2 |
3 | // Stream bool -> Stream a -> Stream a
4 | module.exports = flyd.curryN(2, function(sBool, sA) {
5 | return flyd.combine(function(sA, self) {
6 | if (sBool() !== false) self(sA());
7 | }, [sA]);
8 | });
9 |
--------------------------------------------------------------------------------
/module/keepwhen/test/index.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var flyd = require('../../../lib');
3 | var stream = flyd.stream;
4 |
5 | var keepWhen = require('../index.js');
6 |
7 | describe('keepWhen', function() {
8 | it('keeps values from second stream when first is true', function() {
9 | var result = [];
10 | var s = stream(1);
11 | var b = stream(false);
12 | var k = keepWhen(b, s);
13 | flyd.map(function(v) {
14 | result.push(v);
15 | }, k);
16 | s(2);
17 | b(true);
18 | s(3)(4);
19 | b(false);
20 | s(5);
21 | b(true);
22 | s(6);
23 | assert.deepEqual(result, [3, 4, 6]);
24 | });
25 | it('doesnt emit anything until second stream has a value', function() {
26 | var result = [];
27 | var s = stream();
28 | var b = stream(false);
29 | var k = keepWhen(b, s);
30 | flyd.map(function(v) {
31 | result.push(v);
32 | }, k);
33 | b(true)(false)(true);
34 | s(3)(4);
35 | assert.deepEqual(result, [3, 4]);
36 | });
37 | });
38 |
--------------------------------------------------------------------------------
/module/lift/README.md:
--------------------------------------------------------------------------------
1 | # flyd-lift
2 |
3 | Merge the latest values from multiple streams into a single stream using a function.
4 |
5 | Emits a new value every time any source stream has a new value.
6 |
7 | __Graph__
8 |
9 | ```
10 | a: {---1----2----}
11 | b: {-----1----2--}
12 | lift(add, a, b): {-----2--3-4--}
13 | ```
14 |
15 | __Signature__
16 |
17 | `( ((a, b, ...) -> c), (Stream a, Stream b, ...) ) -> Stream c`
18 |
19 | __Usage__
20 |
21 | ```javascript
22 | const lift = require('flyd/module/lift')
23 |
24 | const n1 = flyd.stream(1)
25 | const n2 = flyd.stream(4)
26 | const n3 = flyd.stream(9)
27 |
28 | const addThree = (a, b, c) => a + b + c
29 | const sum = lift(addThree, n1, n2, n3)
30 |
31 | sum() // 14
32 |
33 | n2(5)
34 | sum() // 15
35 | ```
36 |
--------------------------------------------------------------------------------
/module/lift/index.js:
--------------------------------------------------------------------------------
1 | var flyd = require('../../lib');
2 |
3 | module.exports = function(f /* , streams */) {
4 | var streams = Array.prototype.slice.call(arguments, 1);
5 | var vals = [];
6 | return flyd.combine(function() {
7 | for (var i = 0; i < streams.length; ++i) vals[i] = streams[i]();
8 | return f.apply(null, vals);
9 | }, streams);
10 | };
11 |
--------------------------------------------------------------------------------
/module/lift/test/index.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var flyd = require('../../../lib');
3 | var stream = flyd.stream;
4 | var lift = require('../index.js');
5 |
6 | describe('lift', function() {
7 | it('applies a function to two streams', function() {
8 | var add = function(x, y) { return x + y; };
9 | var x = stream(3);
10 | var y = stream(4);
11 | var sum = lift(add, x, y);
12 | assert.equal(sum(), x() + y());
13 | x(12);
14 | assert.equal(sum(), x() + y());
15 | y(3);
16 | assert.equal(sum(), x() + y());
17 | });
18 | it('applies a function to five streams', function() {
19 | var add = function(a, b, c, d, e) { return a + b + c + d + e; };
20 | var a = stream(1);
21 | var b = stream(2);
22 | var c = stream(3);
23 | var d = stream(4);
24 | var e = stream(5);
25 | var sum = lift(add, a, b, c, d, e);
26 | assert.equal(sum(), a() + b() + c() + d() + e());
27 | e(12); d(2); b(0);
28 | assert.equal(sum(), a() + b() + c() + d() + e());
29 | a(3); c(3);
30 | assert.equal(sum(), a() + b() + c() + d() + e());
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/module/mergeall/README.md:
--------------------------------------------------------------------------------
1 | # flyd-mergeall
2 | Flyd module for merging several streams into one.
3 |
4 | __Graph__
5 |
6 | ```
7 | a: {---1---2---3---}
8 | b: {--1-----2-----3}
9 | mergeAll([a,b]): {--11---22--3--3}
10 | ```
11 |
12 | __Signature__
13 |
14 | `[Stream a] -> Stream a`
15 |
16 | __Example__
17 |
18 | ```javascript
19 | const mergeAll = require('flyd/module/mergeall')
20 |
21 | const s1 = flyd.stream()
22 | const s2 = flyd.stream()
23 | const s3 = flyd.stream()
24 | var merged = mergeAll([s1, s2, s3])
25 | s1(1)
26 | merged() // 1
27 | s2(2)
28 | merged() // 2
29 | s3(3)
30 | merged() // 3
31 | ```
32 |
33 |
--------------------------------------------------------------------------------
/module/mergeall/index.js:
--------------------------------------------------------------------------------
1 | var flyd = require('../../lib');
2 |
3 | module.exports = function mergeAll(streams) {
4 | var s = flyd.immediate(flyd.combine(function() {
5 | var self = arguments[arguments.length - 2];
6 | if (arguments[arguments.length - 1][0]) {
7 | self(arguments[arguments.length - 1][0]());
8 | return;
9 | }
10 | [].slice.call(arguments, 0, arguments.length - 2)
11 | .some(function(s1) {
12 | if (s1.hasVal) {
13 | self(s1.val);
14 | return true;
15 | }
16 | });
17 | }, streams));
18 | flyd.endsOn(flyd.combine(function() {
19 | return true;
20 | }, streams.map(function(sm) { return sm.end; })), s);
21 | return s;
22 | };
23 |
24 |
--------------------------------------------------------------------------------
/module/mergeall/test/index.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var flyd = require('../../../lib');
3 | var stream = flyd.stream;
4 |
5 | var mergeAll = require('../index.js');
6 |
7 | describe('mergeAll', function() {
8 | it('merges multiple streams', function() {
9 | var s1 = stream();
10 | var s2 = stream();
11 | var s3 = stream();
12 | var merged = mergeAll([s1, s2, s3]);
13 | s1(1);
14 | assert.equal(merged(), 1);
15 | s2(2);
16 | assert.equal(merged(), 2);
17 | s3(3);
18 | assert.equal(merged(), 3);
19 | s2('hello');
20 | assert.equal(merged(), 'hello');
21 | });
22 | it('has initial value', function() {
23 | var s1 = stream(1);
24 | var s2 = stream(2);
25 | var s3 = stream();
26 | var merged = mergeAll([s1, s2, s3]);
27 | assert.equal(merged(), 1);
28 | s3(3);
29 | assert.equal(merged(), 3);
30 | });
31 | it('ends when all the merged streams end', function() {
32 | var s1 = stream();
33 | var s2 = stream();
34 | var s3 = stream();
35 | var merged = mergeAll([s1, s2, s3]);
36 | s1.end(true);
37 | assert.equal(s1.end(), true);
38 | assert.equal(merged.end(), undefined);
39 | s2.end(true);
40 | assert.equal(s2.end(), true);
41 | assert.equal(merged.end(), undefined);
42 | s3.end(true);
43 | assert.equal(s3.end(), true);
44 | assert.equal(merged.end(), true);
45 | });
46 | });
47 |
--------------------------------------------------------------------------------
/module/obj/README.md:
--------------------------------------------------------------------------------
1 | # flyd-obj
2 |
3 | Functions for working with Flyd stream in objects.
4 |
5 | - Convert object values from plain values into streams with __streamProps__
6 | - Convert object values from streams into plain values with __extractProps__
7 | - Convert a plain object with stream values into a single stream of plain objects with __stream__
8 |
9 | These functions perform these conversions recursively in nested objects.
10 |
11 | ## streamProps(obj)
12 |
13 | Given an object of normal values, turn every value into a stream. It will
14 | stream nested properties recursively.
15 |
16 | __Signature__
17 |
18 | `Object a -> Object (Stream a)`
19 |
20 | __Usage__
21 |
22 | ```js
23 | const flydObj = require('flyd/module/object')
24 | const obj = {x: 1, y: {z: 2}}
25 | const objOfStreams = flydObj.streamProps(obj)
26 |
27 | objOfStreams.x() // 1
28 | objOfStreams.y.z() // 2
29 | ```
30 |
31 | ## extractProps(obj)
32 |
33 | Given an object that contains streams for values, extract everything into an
34 | object of regular values. It will extract nested properties recursively.
35 |
36 | __Signature__
37 |
38 | `Object (Stream a) -> Object a`
39 |
40 | __Usage__
41 |
42 | ```js
43 | const objOfStreams = {x: flyd.stream(1), y: {z: flyd.stream(2)}}
44 | const obj = flydObj.extractProps(objOfStreams)
45 | //obj is {x: 1, y: {z: 2}}
46 | ```
47 |
48 | ## stream(obj)
49 |
50 | Given an object containing streams, combine all the streams into a single stream of plain objects.
51 |
52 | __Signature__
53 |
54 | `Object (Stream a) -> Stream (Object a)`
55 |
56 | __Usage__
57 |
58 | ```js
59 | const click = flyd.stream()
60 | const message = flyd.map(() => 'Hello world!', state.click)
61 | const state = {click, message}
62 |
63 | const stateStream = flydObj.stream(state)
64 |
65 | stateStream() // {click: undefined, message: undefined}
66 |
67 | click(true)
68 | stateStream() // {click: true, message: 'Hello World!'}
69 | ```
70 |
71 |
--------------------------------------------------------------------------------
/module/obj/index.js:
--------------------------------------------------------------------------------
1 | var flyd = require('../../lib');
2 |
3 | function isPlainObject(obj) {
4 | return obj !== null && typeof obj === 'object' && Object.getPrototypeOf(obj) === Object.prototype;
5 | }
6 |
7 | var streamProps = function(from) {
8 | var to = {};
9 | for (var key in from) {
10 | if (from.hasOwnProperty(key)) {
11 | to[key] = isPlainObject(from[key]) ? streamProps(from[key]) : flyd.stream(from[key]);
12 | }
13 | }
14 | return to;
15 | };
16 |
17 | var extractProps = function(obj) {
18 | var newObj = {};
19 | for (var key in obj) {
20 | if (obj.hasOwnProperty(key)) {
21 | newObj[key] = isPlainObject(obj[key]) ? extractProps(obj[key])
22 | : flyd.isStream(obj[key]) ? obj[key]()
23 | : obj[key];
24 | }
25 | }
26 | return newObj;
27 | };
28 |
29 | var stream = function(obj) {
30 | var streams = Object.keys(obj).map(function(key) {
31 | return isPlainObject(obj[key]) ? stream(obj[key])
32 | : flyd.isStream(obj[key]) ? obj[key]
33 | : flyd.stream(obj[key]);
34 | });
35 | return flyd.combine(function() {
36 | return extractProps(obj);
37 | }, streams);
38 | };
39 |
40 | module.exports = {
41 | streamProps: streamProps,
42 | extractProps: extractProps,
43 | stream: stream
44 | };
45 |
--------------------------------------------------------------------------------
/module/obj/test/index.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var flyd = require('../../../lib');
3 | var stream = flyd.stream;
4 |
5 | var obj = require('../index.js');
6 |
7 | describe('stream props', function() {
8 | it('converts the properties in an object to streams', function() {
9 | var o = {one: 1, two: 2, three: 3};
10 | var oS = obj.streamProps(o);
11 | assert.equal(o.one, oS.one());
12 | assert.equal(o.two, oS.two());
13 | assert.equal(o.three, oS.three());
14 | });
15 | it('handles converting nested properties to nested streams', function() {
16 | var o = {nested: {value: 'val', deeper: {deepVal: 'deepVal'}}};
17 | var oS = obj.streamProps(o);
18 | assert.equal(o.nested.value, oS.nested.value());
19 | assert.equal(o.nested.deeper.deepVal, oS.nested.deeper.deepVal());
20 | });
21 | });
22 |
23 | describe('stream object', function() {
24 | var o = {one: 1, two: 2, three: 3};
25 | it('returns a stream', function() {
26 | var oS = obj.stream(obj.streamProps(o));
27 | assert(flyd.isStream(oS));
28 | });
29 | it('flow unwrapped object down stream when props change', function() {
30 | var oS = obj.streamProps(o);
31 | var result = [];
32 | flyd.map(function(o) { result.push(o); }, obj.stream(oS));
33 | oS.one(4);
34 | oS.three(4);
35 | oS.two(4);
36 | assert.deepEqual(result, [
37 | {one: 1, two: 2, three: 3},
38 | {one: 4, two: 2, three: 3},
39 | {one: 4, two: 2, three: 4},
40 | {one: 4, two: 4, three: 4}
41 | ]);
42 | });
43 | it('handles prop changes in nested objects', function() {
44 | var o = {nested: {value: 'val', deeper: {deepVal: 'deepVal'}}};
45 | var oS = obj.streamProps(o);
46 | var result = [];
47 | flyd.map(function(o) { result.push(o); }, obj.stream(oS));
48 | oS.nested.value('val2');
49 | oS.nested.deeper.deepVal('deepVal2');
50 | oS.nested.value('val3');
51 | assert.deepEqual(result, [
52 | {nested: {value: 'val', deeper: {deepVal: 'deepVal'}}},
53 | {nested: {value: 'val2', deeper: {deepVal: 'deepVal'}}},
54 | {nested: {value: 'val2', deeper: {deepVal: 'deepVal2'}}},
55 | {nested: {value: 'val3', deeper: {deepVal: 'deepVal2'}}}
56 | ]);
57 | });
58 | it('retains the values of non-streams', function() {
59 | var oS = {nested: {value: stream('val'), deeper: {constant: 'constantVal'}}};
60 | var result = [];
61 | flyd.map(function(o) { result.push(o); }, obj.stream(oS));
62 | oS.nested.value('val2');
63 | oS.nested.value('val3');
64 | assert.deepEqual(result, [
65 | {nested: {value: 'val', deeper: {constant: 'constantVal'}}},
66 | {nested: {value: 'val2', deeper: {constant: 'constantVal'}}},
67 | {nested: {value: 'val3', deeper: {constant: 'constantVal'}}}
68 | ]);
69 | });
70 | });
71 |
72 | describe('extract', function() {
73 | it('extracts the values from streams in object', function() {
74 | var oS = {one: stream(1), two: stream(2), three: stream(3)};
75 | var o = obj.extractProps(oS);
76 | assert.equal(o.one, oS.one());
77 | assert.equal(o.two, oS.two());
78 | assert.equal(o.three, oS.three());
79 | });
80 | it('handles values that are not streams', function() {
81 | var oS = {one: stream(1), undef: undefined, nll: null, two: 2};
82 | var o = obj.extractProps(oS);
83 | assert.equal(o.one, oS.one());
84 | assert.equal(o.undef, oS.undef);
85 | assert.equal(o.nll, oS.nll);
86 | assert.equal(o.two, oS.two);
87 | });
88 | it('handles nested values', function() {
89 | var oS = {nested: {value: stream('val'), deeper: {deepVal: stream('deepVal'), constant: 3}}};
90 | var o = obj.extractProps(oS);
91 | assert.equal(o.nested.value, oS.nested.value());
92 | assert.equal(o.nested.deeper.deepVal, oS.nested.deeper.deepVal());
93 | assert.equal(o.nested.deeper.constant, oS.nested.deeper.constant);
94 | });
95 | });
96 |
--------------------------------------------------------------------------------
/module/previous/README.md:
--------------------------------------------------------------------------------
1 | # flyd-previous
2 |
3 | Returns a stream that is always one value behind the original stream.
4 |
5 | __Graph__
6 |
7 | ```
8 | a: {---1---2---3---4}
9 | previous(a): {-------1---2---3}
10 | ```
11 |
12 | __Signature__
13 |
14 | `Stream a -> Stream a`
15 |
16 | __Usage__
17 |
18 | ```
19 | const previous = require('flyd/module/previous')
20 |
21 | const s = flyd.stream()
22 | const prev = previous(s)
23 |
24 | s(1)
25 | prev() // undefined
26 | s(2)
27 | prev() // 1
28 | s(3)
29 | prev() // 2
30 | ```
31 |
--------------------------------------------------------------------------------
/module/previous/index.js:
--------------------------------------------------------------------------------
1 | var flyd = require('../../lib');
2 |
3 | module.exports = function(s) {
4 | var previousValue;
5 | return flyd.combine(skipFirstCall(function(s, self) {
6 | self(previousValue);
7 | previousValue = s();
8 | }), [s]);
9 | };
10 |
11 | function skipFirstCall(func) {
12 | var functionToCall = function() {
13 | functionToCall = func;
14 | }
15 | return function() {
16 | return functionToCall.apply(this, arguments);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/module/previous/test/index.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var flyd = require('../../../lib');
3 | var stream = flyd.stream;
4 |
5 | var previous = require('../index.js');
6 |
7 | describe('previous', function() {
8 | it('is always one value behind the source stream', function() {
9 | var s = stream(1);
10 | var p = previous(s);
11 | s(2)(3)(4);
12 | assert.equal(p(), 3);
13 | });
14 |
15 | it('starts streaming after the second value is pushed into the source stream', function() {
16 | var s = stream();
17 | var p = previous(s);
18 | var calls = 0;
19 | flyd.on(function() { calls += 1; }, p);
20 | s(1);
21 | assert.equal(calls, 0);
22 | s(2);
23 | assert.equal(calls, 1);
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/module/sampleon/README.md:
--------------------------------------------------------------------------------
1 | # flyd-sampleon
2 |
3 | Sample from the second stream every time an event occurs on the first
4 | stream.
5 |
6 | __Graph__
7 |
8 | ```
9 | a: {--t--t--t-------t}
10 | b: {---1---2---3---4-}
11 | sampleOn(a, b): {-----1--2-------4}
12 | ```
13 |
14 | __Signature__
15 |
16 | `Stream a -> Stream b -> Stream b`
17 |
18 | __Usage__
19 |
20 | ```javascript
21 | const sampleOn = require('flyd/module/sampleon')
22 |
23 | const sample = flyd.stream()
24 | const on = flyd.stream()
25 | const result = sampleOn(on, sample)
26 |
27 | on(true)
28 | result() // undefined
29 |
30 | sample(1)
31 | on(true)
32 | result() // 1
33 |
34 | sample(2)
35 | sample(3)
36 | on(true)
37 | result() // 3
38 | ```
39 |
--------------------------------------------------------------------------------
/module/sampleon/index.js:
--------------------------------------------------------------------------------
1 | var flyd = require('../../lib');
2 |
3 | module.exports = flyd.curryN(2, function(s1, s2) {
4 | return flyd.combine(function() {
5 | return s2();
6 | }, [s1]);
7 | });
8 |
--------------------------------------------------------------------------------
/module/sampleon/test/index.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var flyd = require('../../../lib');
3 | var stream = flyd.stream;
4 |
5 | var sampleOn = require('../index.js');
6 |
7 | describe('sample On', function() {
8 | it('samples from second stream', function() {
9 | var result = [];
10 | var s1 = stream();
11 | var s2 = stream();
12 | var sampled = sampleOn(s1, s2);
13 | flyd.map(function(v) {
14 | result.push(v);
15 | }, sampled);
16 | s2(1);
17 | s1(1)(2)(3);
18 | s2(3)(4)(6);
19 | s1(5)(3);
20 | assert.deepEqual(result, [1, 1, 1, 6, 6]);
21 | });
22 | it('has not value until value flows on trigger stream', function() {
23 | var result = [];
24 | var s1 = stream();
25 | var s2 = stream(1);
26 | var sampled = sampleOn(s1, s2);
27 | flyd.map(function(v) {
28 | result.push(v);
29 | }, sampled);
30 | s2(1);
31 | s1(1)(2)(3);
32 | s2(3)(4)(6);
33 | s1(5)(3);
34 | assert.deepEqual(result, [1, 1, 1, 6, 6]);
35 | });
36 | });
37 |
--------------------------------------------------------------------------------
/module/scanmerge/README.md:
--------------------------------------------------------------------------------
1 | # flyd-scanmerge
2 | Flyd module for conveniently merging and scanning several streams into one.
3 |
4 | scanmerge takes an array of pairs of streams and scan functions. It merges all those streams using the given functions into a single stream.
5 |
6 | A common use case is to take many UI event streams, pair each one with an updater function, so they all combine into a single UI state object.
7 |
8 | __Graph__
9 |
10 | ```
11 | n1: {2---3----2---3}
12 | n2: {--2---2----1--}
13 | scanMerge([[n1, add], [n2, sub]], 0): {2-0-3-1--3-2-5}
14 | ```
15 |
16 | __Signature__
17 |
18 | `[[Stream b, (a, b -> a)]] -> a -> Stream a`
19 |
20 | __Usage__
21 |
22 | ```javascript
23 | const scanMerge = require('flyd/module/scanmerge')
24 | const add = flyd.stream(0)
25 | const sub = flyd.stream(0)
26 | const mult = flyd.stream(1)
27 | const res = scanMerge([
28 | [add, function(sum, n) { return sum + n; }]
29 | , [sub, function(sum, n) { return sum - n; }]
30 | , [mult, function(sum, n) { return sum * n; }]
31 | ], 0)
32 | add(5); sub(8); sub(4); add(12); mult(3)
33 | res() // 15
34 | ```
35 |
36 | ```javascript
37 | const append = flyd.stream()
38 | const remove = flyd.stream()
39 | const items = scanMerge([
40 | [append, (list, elem) => list.concat(elem)],
41 | , [remove, (list, item) => list.filter(elm => elm !== item)]
42 | ], [])
43 | append(1)(2)(3)(4)(5)
44 | remove(3)
45 | items() // [1,2,4,5]
46 | ```
47 |
--------------------------------------------------------------------------------
/module/scanmerge/index.js:
--------------------------------------------------------------------------------
1 | var flyd = require('../../lib');
2 |
3 | module.exports = flyd.curryN(2, function(pairs, acc) {
4 | var streams = pairs.map(function(p) { return p[0]; });
5 | // use immediate because we want each stream to fire regardless of if the others have ever had a value
6 | return flyd.immediate(flyd.combine(function() {
7 | var changed = arguments[arguments.length - 1];
8 | // var self = arguments[arguments.length - 2];
9 | // because of atomic updates we can have more than one changed
10 | // meaning more than one function should be fired, lets do it in order so its predictable
11 | for (var p = 0; p < pairs.length; p++) {
12 | // because changed is an array of references it doesn't matter if we pull the first match in the case of multiple matches
13 | var idx = changed.indexOf(pairs[p][0]);
14 | if (idx !== -1) {
15 | acc = pairs[p][1](acc, changed[idx]());
16 | }
17 | }
18 | return acc;
19 | }, streams));
20 | });
21 |
--------------------------------------------------------------------------------
/module/scanmerge/test/index.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var flyd = require('../../../lib');
3 | var stream = flyd.stream;
4 |
5 | var scanMerge = require('../index');
6 |
7 | describe('scanMerge', function() {
8 | it('scans and merges multiple streams', function() {
9 | var add = stream();
10 | var sub = stream();
11 | var sum = scanMerge([
12 | [add, function(sum, n) { return sum + n; }],
13 | [sub, function(sum, n) { return sum - n; }]
14 | ], 0);
15 | add(5); sub(8); sub(4); add(12);
16 | assert.equal(sum(), 5);
17 | });
18 | it('initially has initial value', function() {
19 | var add = stream(2);
20 | var sub = stream(4);
21 | var sum = scanMerge([
22 | [add, function(sum, n) { return sum + n; }],
23 | [sub, function(sum, n) { return sum - n; }]
24 | ], 0);
25 | assert.equal(sum(), 0);
26 | });
27 | it('handles second example', function() {
28 | var addItem = flyd.stream();
29 | var rmItem = flyd.stream();
30 | var items = scanMerge([
31 | [addItem, function(list, item) { return list.concat([item]); }],
32 | [rmItem, function(list, item) {
33 | return list.filter(function(elm) { return elm !== item; });
34 | }]
35 | ], []);
36 | addItem(1)(2)(3)(4)(5);
37 | rmItem(3);
38 | assert.deepEqual(items(), [1, 2, 4, 5]);
39 | });
40 | });
41 |
--------------------------------------------------------------------------------
/module/switchlatest/README.md:
--------------------------------------------------------------------------------
1 | # flyd-switchlatest
2 |
3 | Flattens a stream of streams. The result stream reflects changes from the
4 | last stream only.
5 |
6 | __Graph__
7 |
8 | ```
9 | a: {--.----.----}
10 | {ab} {a-b}
11 | switchLatest(a): {--ab---a-b--}
12 | ```
13 |
14 | __Signature__
15 |
16 | `Stream (Stream a) -> Stream b`
17 |
18 | __Usage__
19 |
20 | ```javascript
21 | const switchLatest = require('flyd/module/switchlatest')
22 |
23 | const chatrooms = flyd.stream()
24 | // For each chatroom on the chatrooms stream, create a stream of chat messages.
25 | // This gives us a series of streams nested within a parent stream.
26 | const messages = flyd.map(createMessageStream, chatrooms)
27 |
28 | // Create a single, unnested stream of chat messages
29 | const currentMessages = switchLatest(messagesStreams)
30 | ```
31 |
32 |
--------------------------------------------------------------------------------
/module/switchlatest/index.js:
--------------------------------------------------------------------------------
1 | var flyd = require('../../lib');
2 | var takeUntil = require('../takeuntil');
3 | var drop = require('ramda/src/drop');
4 |
5 | var dropCurrentValue = flyd.transduce(drop(1));
6 |
7 | module.exports = function(s) {
8 | return flyd.combine(function(stream$, self) {
9 | var value$ = stream$();
10 | flyd.on(self, takeUntil(value$, dropCurrentValue(stream$)));
11 | }, [s]);
12 | };
13 |
--------------------------------------------------------------------------------
/module/switchlatest/test/index.js:
--------------------------------------------------------------------------------
1 | var flyd = require('../../../lib');
2 | var stream = flyd.stream;
3 | var assert = require('assert');
4 |
5 | var switchLatest = require('../index.js');
6 |
7 | describe('switchLatest', function() {
8 | it('emits values from first stream in stream', function() {
9 | var result = [];
10 | var source = stream();
11 | var is = stream();
12 | var s = switchLatest(source);
13 | flyd.map(function(v) { result.push(v); }, s);
14 | source(is);
15 | is(1)(2)(3);
16 | assert.deepEqual(result, [1, 2, 3]);
17 | });
18 | it('emits values from first and second stream in stream', function() {
19 | var result = [];
20 | var source = stream();
21 | var is1 = stream();
22 | var is2 = stream();
23 | var s = switchLatest(source);
24 | flyd.map(function(v) { result.push(v); }, s);
25 | source(is1);
26 | is1(1);
27 | source(is2);
28 | is1(-1);
29 | is2(2)(3);
30 | assert.deepEqual(result, [1, 2, 3]);
31 | });
32 | it('ends when source stream ends', function() {
33 | var result = [];
34 | var source = stream();
35 | var is = stream();
36 | var s = switchLatest(source);
37 | flyd.map(function(v) { result.push(v); }, s);
38 | source(is); is(1)(2);
39 | assert.deepEqual(result, [1, 2]);
40 | assert(!source.ended);
41 | source.end(true);
42 | assert.equal(true, source.end());
43 | });
44 | });
45 |
--------------------------------------------------------------------------------
/module/takeuntil/README.md:
--------------------------------------------------------------------------------
1 | # flyd-takeuntil
2 | Emit values from a stream until a second stream emits a value.
3 |
4 | __Graph__
5 |
6 | ```
7 | a: {---1---2---3---4}
8 | b: {---------x------}
9 | takeUntil(a, b): {---1---2--------}
10 | ```
11 |
12 | __Signature__
13 |
14 | `Stream a -> Stream b -> Stream a`
15 |
16 | __Usage__
17 |
18 | ```javascript
19 | const takeUntil = require('flyd/module/takeuntil')
20 |
21 | const source = flyd.stream()
22 | const end = flyd.stream()
23 | const result = takeUntil(source, end)
24 |
25 | source(1)(2)
26 | result() // 2
27 | source(3)
28 | result() // 3
29 |
30 | end(true)
31 | result() // 3
32 | source(4)(5)
33 | result() // 3
34 | ```
35 |
--------------------------------------------------------------------------------
/module/takeuntil/index.js:
--------------------------------------------------------------------------------
1 | var flyd = require('../../lib');
2 |
3 | module.exports = flyd.curryN(2, function(src, term) {
4 | return flyd.endsOn(flyd.merge(term, src.end), flyd.combine(function(src, self) {
5 | self(src());
6 | }, [src]));
7 | });
8 |
--------------------------------------------------------------------------------
/module/takeuntil/test/index.js:
--------------------------------------------------------------------------------
1 | var flyd = require('../../../lib');
2 | var stream = flyd.stream;
3 | var assert = require('assert');
4 |
5 | var takeUntil = require('../index');
6 |
7 | describe('takeUntil', function() {
8 | it('emits values from first stream', function() {
9 | var result = [];
10 | var source = stream();
11 | var terminator = stream();
12 | var s = takeUntil(source, terminator);
13 | flyd.map(function(v) { result.push(v); }, s);
14 | source(1)(2)(3);
15 | assert.deepEqual(result, [1, 2, 3]);
16 | });
17 | it('ends when value emitted from second stream', function() {
18 | var result = [];
19 | var source = stream();
20 | var terminator = stream();
21 | var s = takeUntil(source, terminator);
22 | flyd.map(function(v) { result.push(v); }, s);
23 | s(1);
24 | terminator(true);
25 | s(2);
26 | assert.deepEqual(result, [1]);
27 | assert(s.end());
28 | });
29 | it('ends if source stream ends', function() {
30 | var result = [];
31 | var source = stream();
32 | var terminator = stream();
33 | var s = takeUntil(source, terminator);
34 | flyd.map(function(v) { result.push(v); }, s);
35 | s(1);
36 | source.end(true);
37 | s(2);
38 | assert.deepEqual(result, [1]);
39 | assert(s.end());
40 | });
41 | });
42 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "flyd",
3 | "version": "0.2.8",
4 | "description": "The less is more, modular, functional reactive programming library",
5 | "main": "lib/index.js",
6 | "unpkg": "flyd.min.js",
7 | "directories": {
8 | "example": "examples",
9 | "test": "test"
10 | },
11 | "dependencies": {
12 | "ramda": "^0.25.0",
13 | "whatwg-fetch": "^3.0.0"
14 | },
15 | "devDependencies": {
16 | "benchmark": "^1.0.0",
17 | "bluebird": "^2.9.13",
18 | "browserify": "^10.2.4",
19 | "coveralls": "^2.11.2",
20 | "eslint": "^2.7.0",
21 | "istanbul": "^0.3.15",
22 | "mocha": "^2.2.1",
23 | "mocha-lcov-reporter": "0.0.2",
24 | "np": "^2.19.0",
25 | "rollup": "^0.56.2",
26 | "rollup-plugin-commonjs": "^8.3.0",
27 | "rollup-plugin-node-resolve": "^3.0.3",
28 | "rollup-plugin-replace": "^2.0.0",
29 | "rollup-plugin-uglify": "^3.0.0",
30 | "transducers.js": "0.3.x"
31 | },
32 | "scripts": {
33 | "test-lib": "mocha",
34 | "test": "eslint --fix lib/ test/ module/ && mocha test/*.js module/**/test/*.js",
35 | "docs": "documentation -f md lib/index.js > API.md",
36 | "perf": "./perf/run-benchmarks",
37 | "coverage": "istanbul cover _mocha -- -R spec",
38 | "post-to-coveralls-io": "istanbul cover _mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | coveralls && rm -rf ./coverage",
39 | "build": "rollup -c rollup.config.dev.js && rollup -c rollup.config.js && node ./build-examples.js",
40 | "release": "np"
41 | },
42 | "repository": {
43 | "type": "git",
44 | "url": "https://github.com/paldepind/flyd.git"
45 | },
46 | "keywords": [
47 | "functional",
48 | "reactive",
49 | "modular",
50 | "library"
51 | ],
52 | "author": "Simon Friis Vindum",
53 | "license": "MIT",
54 | "bugs": {
55 | "url": "https://github.com/paldepind/flyd/issues"
56 | },
57 | "homepage": "https://github.com/paldepind/flyd",
58 | "testling": {
59 | "harness": "mocha",
60 | "files": "test/*.js",
61 | "browsers": [
62 | "ie/8..latest",
63 | "firefox/16..latest",
64 | "firefox/nightly",
65 | "chrome/22..latest",
66 | "chrome/canary",
67 | "opera/12..latest",
68 | "opera/next",
69 | "safari/5.1..latest",
70 | "ipad/6.0..latest",
71 | "iphone/6.0..latest",
72 | "android-browser/4.2..latest"
73 | ]
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/perf/perf.js:
--------------------------------------------------------------------------------
1 | var Benchmark = require('benchmark');
2 |
3 |
4 | // Attach benchmarks' dependencies to the global
5 | // scope, since the current version of benchmark.js
6 | // doesn't allow for anything simpler
7 | global.stream = require('../flyd').stream;
8 | global.oldStream = require('../flyd-old').stream;
9 |
10 | // ************************************************
11 | // Util functions
12 |
13 | var suites = [];
14 |
15 | function getHz(bench) { // hz adjusted for margin of error
16 | var result = 1 / (bench.stats.mean + bench.stats.moe);
17 | return isFinite(result) ? result : 0;
18 | }
19 |
20 | function printFastest(suite) {
21 | var formatNumber = Benchmark.formatNumber,
22 | fastest = suite.filter('fastest'),
23 | fastestHz = getHz(fastest[0]),
24 | slowest = suite.filter('slowest'),
25 | slowestHz = getHz(slowest[0]),
26 | aHz = getHz(suite[0]),
27 | bHz = getHz(suite[1]);
28 | if (fastest.length > 1) {
29 | console.log('It\'s too close to call.');
30 | aHz = bHz = slowestHz;
31 | } else {
32 | var percent = ((fastestHz / slowestHz) - 1) * 100;
33 | console.log(' ' + fastest[0].name + ' is ' +
34 | formatNumber(percent < 1 ? percent.toFixed(2) : Math.round(percent)) +
35 | '% faster.');
36 | }
37 | }
38 |
39 | Benchmark.Suite.options.onStart = function() {
40 | console.log('\n' + this.name + ':');
41 | };
42 |
43 | Benchmark.Suite.options.onCycle = function(event) {
44 | console.log(' ' + event.target);
45 | };
46 |
47 | Benchmark.Suite.options.onComplete = function() {
48 | printFastest(this);
49 | suites.shift();
50 | if (suites.length) {
51 | suites[0].run({async: true});
52 | }
53 | };
54 |
55 | // ************************************************
56 | // Benchmarks!
57 |
58 | suites.push(Benchmark.Suite('dynamic dependencies').add('New', {
59 | setup: function() {
60 | var s = stream();
61 | stream(function() {
62 | return s();
63 | });
64 | },
65 | fn: function() {
66 | s(12);
67 | },
68 | }).add('Old', {
69 | setup: function() {
70 | var s = oldStream();
71 | oldStream(function() {
72 | return s();
73 | });
74 | },
75 | fn: function() {
76 | s(12);
77 | },
78 | }));
79 |
80 | suites.push(Benchmark.Suite('static dependencies').add('New', {
81 | setup: function() {
82 | var s = stream();
83 | stream([s], function() {
84 | return s();
85 | });
86 | },
87 | fn: function() {
88 | s(12);
89 | },
90 | }).add('Old', {
91 | setup: function() {
92 | var s = oldStream();
93 | oldStream([s], function() {
94 | return s();
95 | });
96 | },
97 | fn: function() {
98 | s(12);
99 | },
100 | }));
101 |
102 | suites.push(Benchmark.Suite('map').add('First', {
103 | setup: function() {
104 | function f(x) { return x; }
105 | var s1 = stream();
106 | var s2 = s1.map(f);
107 | var s3 = s2.map(f);
108 | var s4 = s3.map(f);
109 | var s5 = s4.map(f);
110 | },
111 | fn: function() {
112 | s1(12);
113 | },
114 | }).add('Second', {
115 | setup: function() {
116 | function f(x) { return x; }
117 | var s1 = stream();
118 | var s2 = s1.map(f);
119 | var s3 = s2.map(f);
120 | var s4 = s3.map(f);
121 | var s5 = s4.map(f);
122 | },
123 | fn: function() {
124 | s1(12);
125 | },
126 | }));
127 |
128 | suites.push(Benchmark.Suite('dynamic dependency graph').add('New', {
129 | setup: function() {
130 | var s1 = stream();
131 | var s2 = stream(function() {
132 | s1(); s1();
133 | });
134 | var s3 = stream(function() {
135 | s1(); s2(); s1();
136 | });
137 | var s4 = stream(function() {
138 | s1(); s2(); s3(); s1(); s3();
139 | });
140 | stream(function() {
141 | s3(); s2(); s1(); s3(); s4();
142 | });
143 | },
144 | fn: function() {
145 | s1(12);
146 | },
147 | }).add('Old', {
148 | setup: function() {
149 | var s1 = oldStream();
150 | var s2 = oldStream(function() {
151 | s1(); s1();
152 | });
153 | var s3 = oldStream(function() {
154 | s1(); s2(); s1();
155 | });
156 | var s4 = oldStream(function() {
157 | s1(); s2(); s3(); s1(); s3();
158 | });
159 | oldStream(function() {
160 | s3(); s2(); s1(); s3(); s4();
161 | });
162 | },
163 | fn: function() {
164 | s1(12);
165 | },
166 | }));
167 |
168 | suites[0].run({ 'async': true });
169 |
--------------------------------------------------------------------------------
/perf/run-benchmarks:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ## Retrieve older version of the source, to be compared
4 | ## in performance against the current version.
5 |
6 | DIRECTORY_CONTAINING_THIS_SCRIPT=$( cd $(dirname $0) ; pwd -P )
7 | REPOSITORY_ROOT="$DIRECTORY_CONTAINING_THIS_SCRIPT/.."
8 |
9 |
10 | SOURCE_FILENAME="flyd"
11 | SOURCE_FILENAME_WITH_EXTENSION="$SOURCE_FILENAME.js"
12 |
13 | OLD_VERSION_FILENAME="$SOURCE_FILENAME-old"
14 | OLD_VERSION_FILENAME_WITH_EXTENSION="$OLD_VERSION_FILENAME.js"
15 |
16 |
17 | # The first passed argument is the number of commits (in the
18 | # current branch) you want to 'undo' in order to get
19 | # to the desired old version.
20 | # It defaults to 1.
21 | if [ "$1" -eq "$1" ] 2>/dev/null && [ "$1" -gt "0" ] 2>/dev/null
22 | then
23 | how_many_commits_back="$1"
24 | else
25 | how_many_commits_back="1"
26 | fi
27 |
28 |
29 | # Leave a copy of the old version's source
30 | # in the root of the repository
31 |
32 | cd "$REPOSITORY_ROOT"
33 |
34 | git checkout HEAD~$how_many_commits_back -- $SOURCE_FILENAME_WITH_EXTENSION
35 |
36 | cp $SOURCE_FILENAME_WITH_EXTENSION $OLD_VERSION_FILENAME_WITH_EXTENSION
37 |
38 | git checkout HEAD -- $SOURCE_FILENAME_WITH_EXTENSION
39 |
40 |
41 |
42 | ## Run the benchmarks
43 | cd "$DIRECTORY_CONTAINING_THIS_SCRIPT"
44 |
45 | node perf.js
46 |
47 |
48 |
49 | ## Remove the old version of the source
50 | cd "$REPOSITORY_ROOT"
51 |
52 | rm $OLD_VERSION_FILENAME_WITH_EXTENSION
53 |
--------------------------------------------------------------------------------
/rollup.config.dev.js:
--------------------------------------------------------------------------------
1 | import resolve from 'rollup-plugin-node-resolve';
2 | import commonjs from 'rollup-plugin-commonjs';
3 | import replace from 'rollup-plugin-replace';
4 |
5 | export default [{
6 | input: './lib/index.js',
7 | output: {
8 | file: './flyd.js',
9 | name: 'flyd',
10 | format: 'umd'
11 | },
12 | plugins: [
13 | resolve(),
14 | commonjs()
15 | ]
16 | }, {
17 | input: './lib/index.js',
18 | output: {
19 | file: './es/index.js',
20 | format: 'es'
21 | },
22 | external: ['ramda/src/curryN'],
23 | plugins: [
24 | commonjs(),
25 | // below can be optimized after the rollup issue resolved
26 | // https://github.com/rollup/rollup/issues/2491
27 | replace({
28 | 'ramda/src/curryN': 'ramda/es/curryN'
29 | })
30 | ]
31 | }];
32 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import resolve from 'rollup-plugin-node-resolve';
2 | import commonjs from 'rollup-plugin-commonjs';
3 | import uglify from 'rollup-plugin-uglify';
4 |
5 | export default {
6 | input: './lib/index.js',
7 | output: {
8 | file: './flyd.min.js',
9 | name: 'flyd',
10 | format: 'umd'
11 | },
12 | plugins: [
13 | resolve(),
14 | commonjs(),
15 | uglify()
16 | ]
17 | };
--------------------------------------------------------------------------------