├── .gitattributes ├── .editorconfig ├── examples ├── ramda-transducer │ ├── README.md │ ├── package.json │ └── script.js ├── secret-combination │ ├── node_modules │ │ ├── flyd-inlast │ │ │ ├── README.md │ │ │ ├── inlast.js │ │ │ ├── LICENSE │ │ │ ├── package.json │ │ │ └── test │ │ │ │ └── index.js │ │ ├── flyd-filter │ │ │ ├── filter.js │ │ │ ├── README.md │ │ │ ├── test │ │ │ │ └── index.js │ │ │ ├── LICENSE │ │ │ └── package.json │ │ ├── flyd-sampleon │ │ │ ├── sampleon.js │ │ │ ├── README.md │ │ │ ├── test │ │ │ │ └── index.js │ │ │ ├── LICENSE │ │ │ └── package.json │ │ ├── flyd │ │ │ ├── .travis.yml │ │ │ ├── examples │ │ │ │ ├── multiple-clicks │ │ │ │ │ ├── package.json │ │ │ │ │ ├── index.html │ │ │ │ │ └── script.js │ │ │ │ ├── secret-combination │ │ │ │ │ ├── script.js │ │ │ │ │ └── index.html │ │ │ │ └── sum │ │ │ │ │ └── index.html │ │ │ ├── bower.json │ │ │ ├── LICENSE │ │ │ ├── perf │ │ │ │ ├── test.js │ │ │ │ └── perf.js │ │ │ ├── coverage │ │ │ │ └── lcov.info │ │ │ └── flyd.js │ │ └── flyd-lift │ │ │ ├── flyd-lift.js │ │ │ ├── README.md │ │ │ ├── test │ │ │ └── index.js │ │ │ ├── LICENSE │ │ │ └── package.json │ ├── package.json │ ├── script.js │ └── index.html ├── multiple-clicks │ ├── node_modules │ │ ├── flyd │ │ │ ├── .travis.yml │ │ │ ├── examples │ │ │ │ ├── multiple-clicks │ │ │ │ │ ├── package.json │ │ │ │ │ ├── index.html │ │ │ │ │ ├── script.js │ │ │ │ │ └── build.js │ │ │ │ ├── secret-combination │ │ │ │ │ ├── script.js │ │ │ │ │ └── index.html │ │ │ │ └── sum │ │ │ │ │ └── index.html │ │ │ ├── bower.json │ │ │ ├── LICENSE │ │ │ ├── perf │ │ │ │ ├── test.js │ │ │ │ └── perf.js │ │ │ ├── coverage │ │ │ │ └── lcov.info │ │ │ └── flyd.js │ │ └── flyd-aftersilence │ │ │ ├── aftersilence.js │ │ │ ├── README.md │ │ │ ├── LICENSE │ │ │ ├── test │ │ │ └── index.js │ │ │ └── package.json │ ├── package.json │ ├── index.html │ └── script.js ├── who-to-follow │ ├── package.json │ ├── index.html │ └── script.js ├── drag-and-drop │ ├── index.html │ └── script.js └── sum │ ├── script.js │ └── index.html ├── .travis.yml ├── .gitignore ├── module ├── sampleon │ ├── index.js │ ├── README.md │ └── test │ │ └── index.js ├── filter │ ├── index.js │ ├── test │ │ └── index.js │ └── README.md ├── forwardto │ ├── index.js │ ├── test │ │ └── index.js │ └── README.md ├── takeuntil │ ├── index.js │ ├── README.md │ └── test │ │ └── index.js ├── keepwhen │ ├── index.js │ ├── test │ │ └── index.js │ └── README.md ├── diff │ ├── index.js │ ├── README.md │ └── test │ │ └── index.js ├── every │ ├── test │ │ ├── browsertest │ │ │ ├── index.html │ │ │ └── script.js │ │ └── index.js │ ├── index.js │ └── README.md ├── inlast │ ├── index.js │ ├── README.md │ └── test │ │ └── index.js ├── lift │ ├── index.js │ ├── README.md │ └── test │ │ └── index.js ├── aftersilence │ ├── index.js │ ├── README.md │ └── test │ │ └── index.js ├── switchlatest │ ├── index.js │ ├── README.md │ └── test │ │ └── index.js ├── previous │ ├── index.js │ ├── README.md │ └── test │ │ └── index.js ├── droprepeats │ ├── index.js │ ├── README.md │ └── test │ │ └── index.js ├── mergeall │ ├── README.md │ ├── index.js │ └── test │ │ └── index.js ├── batchwhen │ ├── README.md │ ├── index.js │ └── test │ │ └── index.js ├── scanmerge │ ├── index.js │ ├── test │ │ └── index.js │ └── README.md └── obj │ ├── index.js │ ├── README.md │ └── test │ └── index.js ├── rollup.config.js ├── bower.json ├── rollup.config.dev.js ├── HISTORY.md ├── LICENSE ├── perf ├── run-benchmarks └── perf.js ├── .eslintrc.json ├── package.json ├── flyd.min.js ├── index.d.ts └── API.md /.gitattributes: -------------------------------------------------------------------------------- 1 | * eol=lf -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | indent_style = space 3 | indent_size = 2 4 | -------------------------------------------------------------------------------- /examples/ramda-transducer/README.md: -------------------------------------------------------------------------------- 1 | # Ramda transducer example 2 | 3 | ```javascript 4 | npm install 5 | node script 6 | ``` 7 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### Node template 2 | # Logs 3 | logs 4 | *.log 5 | 6 | # Dependency directory 7 | node_modules 8 | bower_components 9 | 10 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/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 | -------------------------------------------------------------------------------- /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-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 | -------------------------------------------------------------------------------- /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/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/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/every/test/browsertest/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |13 | See the source code 14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /examples/multiple-clicks/node_modules/flyd/examples/multiple-clicks/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |13 | See the source code 14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /examples/secret-combination/node_modules/flyd/examples/multiple-clicks/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |13 | See the source code 14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /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/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/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/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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | ``` -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /examples/drag-and-drop/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |26 | See the source code 27 |
28 | 29 | 30 | -------------------------------------------------------------------------------- /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/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/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/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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/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/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/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/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/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/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/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-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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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/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/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/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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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-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 | -------------------------------------------------------------------------------- /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/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/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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /examples/who-to-follow/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |78 | See the source code 79 |
80 | 81 | 82 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /examples/multiple-clicks/node_modules/flyd/examples/secret-combination/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |114 | This is an implementation of the problem described in Comparing Core Async and Rx by Example 115 |
116 |117 | See the source code 118 |
119 | 120 | 121 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /examples/sum/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
112 | Also try calling x and y in your browser console.
113 |
115 | x(1) 116 | x(2) 117 | x(3) 118 | x(5) 119 | x(8) 120 | x(13) 121 |
122 |123 | y(1) 124 | y(2) 125 | y(3) 126 | y(5) 127 | y(8) 128 | y(13) 129 |
130 |131 | x(x() + 1) 132 | x(x() - 1) 133 |
134 |135 | y(y() + 1) 136 | y(y() - 1) 137 |
138 |
142 | x is ...
143 |
145 | y is ...
146 |
148 | sum is ...
149 |
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);
162 |
155 | Also try calling x and y in your browser console.
156 |
158 | x(1) 159 | x(2) 160 | x(3) 161 | x(5) 162 | x(8) 163 | x(13) 164 |
165 |166 | y(1) 167 | y(2) 168 | y(3) 169 | y(5) 170 | y(8) 171 | y(13) 172 |
173 |174 | x(x() + 1) 175 | x(x() - 1) 176 |
177 |178 | y(y() + 1) 179 | y(y() - 1) 180 |
181 |
185 | x is ...
186 |
188 | y is ...
189 |
191 | sum is ...
192 |
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);
205 |
158 | Also try calling x and y in your browser console.
159 |
161 | x(1) 162 | x(2) 163 | x(3) 164 | x(5) 165 | x(8) 166 | x(13) 167 |
168 |169 | y(1) 170 | y(2) 171 | y(3) 172 | y(5) 173 | y(8) 174 | y(13) 175 |
176 |177 | x(x() + 1) 178 | x(x() - 1) 179 |
180 |181 | y(y() + 1) 182 | y(y() - 1) 183 |
184 |
188 | x is ...
189 |
191 | y is ...
192 |
194 | sum is ...
195 |
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 | });
208 |