On Github eamodeorubio / reactive-baconjs
By Enrique Amodeo / @eamodeorubio
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.0 Generic License(I know, my web design skills suck !)
var keyUpStream = $('input.search-text') .asEventStream('keyup');
var queryTextStream = $('input.search-text') .asEventStream('keyup') .map(function extractValue(ev) { return ev.target.value; });
var queryTextStream = $('input.search-text') .asEventStream('keyup') .map('.target.value');
var queryTextStream = $('input.search-text') .asEventStream('keyup') .map('.target.value') .skipDuplicates();
var $inputSearch = $('input.search-text'); var queryTextStream = $inputSearch .asEventStream('keyup') .map('.target.value') .skipDuplicates() .toProperty($inputSearch.get(0).value);
function valueFrom(selector, event) { event = event || "change"; var $el = $(selector); var prop = $el .asEventStream(event) .map('.target.value') .skipDuplicates() .toProperty($el.get(0).value); return prop; } var queryTextStream = valueFrom('input.search-text', 'keyup');
var dataSource = new EventSource(url); // Listen for any message dataSource.addEventListener('message', function (event) { console.log(event.data); }); dataSource.addEventListener('open', function(event) { // Connection is open ! }); dataSource.addEventListener('error', function(event) { if (e.readyState == EventSource.CLOSED) { // Connection is closed! } }); // Listen for messages of custom type "some-msg-type" dataSource.addEventListener('some-msg-type', function (event) { console.log(event.data); });
function eventStreamForQuery(queryString) { var dataSource = new EventSource("books?" + queryString); function close() { if (dataSource) { dataSource.close(); dataSource = null; } } return Bacon.fromBinder(function (output) { // Add code here to emit Bacon events return close; // Return "cleaning" function }); }
function eventStreamForQuery(queryString) { // ... Omitted for brevity ... return Bacon.fromBinder(function(output) { dataSource.addEventListener('end', function () { output(new Bacon.End()); close(); }); dataSource.addEventListener('data', function (event) { output(new Bacon.Next(JSON.parse(event.data))); }); return close; }); }
function eventStreamForQuery(queryString) { if (!queryString) return Bacon.never(); // Only "end" no data var dataSource = new EventSource("books?" + queryString); function close() { // ... Omitted for brevity ... } return Bacon.fromBinder(function(output) { // ... Omitted for brevity ... }); }
var streamsOfStreams = queryTextStream .map(queryToQueryString) .map(eventStreamForQuery) .doAction(function(resultStream) { // Mmm, inception or what?? return resultStream .map(toSomethingMeaningful) .doAction(doSomethingElse) .doAction(renderResult); });
var streamsOfItems = queryTextStream .map(queryToQueryString) .flatMap(eventStreamForQuery) .map(toSomethingMeaningful) .doAction(doSomethingElse) .doAction(renderResult);
var streamsOfItems = queryTextStream .map(queryToQueryString) .flatMapLatest(eventStreamForQuery) .map(toSomethingMeaningful) .doAction(doSomethingElse) .doAction(renderResult);
function toStreamWithMarks(stream) { return Bacon.once("NEW-QUERY") .concat(stream .mapEnd("END-QUERY") ); } var streamsOfItems = queryTextStream .map(queryToQueryString) .map(eventStreamForQuery) .flatMapLatest(toStreamWithMarks) .doAction(doSomethingElse) .doAction(renderResult);
function toStreamWithMarks(stream) { return Bacon.once(StartQuery) .concat(stream .map(ResultItem) .mapEnd(EndQuery) ); } var streamsOfItems = queryTextStream .map(queryToQueryString) .map(eventStreamForQuery) .flatMapLatest(toStreamWithMarks) .doAction(".render");
function StartQuery() { var $inProgressIndicator = $('.waiting-msg'), $itemsFoundCounter = $('.item-count'), $resultContainer = $('.result-container'); return { render: function () { $inProgressIndicator.show(); $itemsFoundCounter.text('0'); $resultContainer.html(''); } }; }
function ResultItem(book) { var $template = $('.templates .book'), $resultContainer = $('.result-container'); return { render: function () { var $bookView = $template.clone(false); var $titleLink = $bookView.find('.title a'); $titleLink.attr('href', book.link); $titleLink.text(book.title); $bookView.find('.description img').attr('src', book.cover); $bookView.find('.price span').text(book.price); $bookView.find('.authors ul') .html(book.authors.map(htmlForAuthor).join('')); $resultContainer.append($bookView); } }; }
function EndQuery() { var $inProgressIndicator = $('.waiting-msg'); return { render: function () { $inProgressIndicator.hide(); } }; }
// Reactive Property for description criteria var queryByDescription = valueFrom('input.search-text', 'keyup'); // Reactive Property for minimum price criteria var queryByMinPrice = valueFrom('input.min-price') .map(Number) .doAction(renderPriceInto('.min-price-output')); // Reactive Property for maximum price criteria var queryByMaxPrice = valueFrom('input.max-price') .map(Number) .doAction(renderPriceInto('.max-price-output'));
// Whole query criteria var queryStream = shakedNotStirred( queryByDescription, queryByMinPrice, queryByMaxPrice ); var streamsOfItems = queryStream .map(queryToQueryString) .map(eventStreamForQuery) .flatMapLatest(toStreamWithMarks) .doAction(".render");
// Note: this does not work with properties var queryStream = queryByDescription .merge(queryByMaxPrice) .merge(queryByMinPrice);Original by BaconJS: https://raw.github.com/wiki/baconjs/bacon.js/baconjs-merge.png
var queryStream = Bacon.zipWith( function(desc, minPrice, maxPrice) { return { q: desc, minPrice: minPrice, maxPrice: maxPrice }; }, queryByDescription, queryByMinPrice, queryByMaxPrice );
var queryStream = Bacon.combineWith( function(desc, minPrice, maxPrice) { return { q: desc, minPrice: minPrice, maxPrice: maxPrice }; }, queryByDescription, queryByMinPrice, queryByMaxPrice);Original by BaconJS: https://raw.github.com/wiki/baconjs/bacon.js/baconjs-combine.png
var queryStream = Bacon.combineTemplate({ q: queryByDescription, minPrice: queryByMinPrice, maxPrice: queryByMaxPrice });
var streamsOfItems = queryStream .debounce(200) .map(queryToQueryString) .map(eventStreamForQuery) .flatMapLatest(toStreamWithMarks) .doAction(".render");
var queryStream = Bacon.combineTemplate({ q: queryByDescription, minPrice: queryByMinPrice, maxPrice: queryByMaxPrice }).doAction(function (query) { if (query.minPrice > query.maxPrice) $('input.max-price').val(query.minPrice).trigger('change'); });
function StartQuery() { return { // ... Omitted code countItems: function () { return -1; } }; } function ResultItem(book) { return { // ... Omitted code countItems: function () { return 1; } }; } function EndQuery() { return { // ... Omitted code countItems: function () { return 0; } }; }
var foundItemCount = streamsOfItems .map(".countItems") .scan(0, function(currentTotalItems, itemCount) { return itemCount >= 0 ? currentTotalItems + itemCount : 0; });Original by BaconJS: https://raw.github.com/wiki/baconjs/bacon.js/baconjs-scan.png
foundItemCount .map(String) .assign($('.total-count'), "text");