Just toying around with RxJS stuff.
A Pen by Michael Russell on CodePen.
| <div class="wrapper"> | |
| <!-- buttons generated by js --> | |
| </div> | |
| <script> | |
| console.log('from html') | |
| </script> |
Just toying around with RxJS stuff.
A Pen by Michael Russell on CodePen.
| console.clear() // clear out the console on each save/update in codepen | |
| var percussion = new Percussion(); | |
| percussion.setAutoScroll(false); | |
| percussion.stop(); | |
| // ------------ | |
| // DOM Helpers | |
| // ------------ | |
| function childIndexOf(element){ | |
| return [].indexOf.call(element.parentNode.children, element); | |
| } | |
| const createAndAddButton = (function(){ | |
| let wrapper = $('.wrapper'); | |
| return () => { | |
| let btn = $('<button/>'); | |
| let indx = wrapper.children().length; | |
| btn.attr('data-indx', indx); | |
| btn.css({opacity: 0}); | |
| btn.html(indx); | |
| wrapper.append(btn); | |
| return btn; | |
| }; | |
| }()); | |
| // ------------ | |
| // RxJS Helpers | |
| // ------------ | |
| function delegate(wrapper, selector, eventName){ | |
| return Rx.Observable.fromEvent( | |
| $(wrapper), | |
| eventName, | |
| e => ({ event:e, delegate:e.target.closest(selector) }) | |
| ).filter(x => x.delegate !== null); | |
| } | |
| // Generate a stream of numbers from an array and then randomize them. | |
| const correctSequence$ = Rx.Observable | |
| .fromArray(_.shuffle(_.range(0, 6))); | |
| percussion.addStream(correctSequence$); | |
| // Hold streams within array to retrieve length later on | |
| const correctSequenceArray$ = correctSequence$.toArray(); | |
| // log sequence as array to console (to get answer...) | |
| correctSequenceArray$ | |
| .subscribe(n => console.log(n)); | |
| // build out button UI | |
| correctSequence$.forEach(createAndAddButton); | |
| const animation$ = correctSequence$ | |
| .flatMap( (itemIndx, indx) => { | |
| let elm = $('.wrapper').children().eq(itemIndx); | |
| return Rx.Observable.fromPromise( | |
| $.when(elm.delay(indx * 750).fadeTo(500, 1)) | |
| ); | |
| }).share(); | |
| percussion.addStream(animation$); | |
| // On the last animation trigger the done. | |
| animation$.last() | |
| .subscribe(()=>console.log('Animation Stream Completed')); | |
| // create a stream of button clicks | |
| const buttonClicks$ = delegate('.wrapper', 'button', 'click'); | |
| buttonClicks$.subscribe(e => e.delegate.disabled = true); | |
| percussion.addStream(buttonClicks$); | |
| // map the stream of button clicks to their child index | |
| const buttonClicksIndex$ = buttonClicks$ | |
| .map(e => childIndexOf(e.delegate)); | |
| // buffer the clicks into sets of the array length | |
| // then check if the sequence of clicks match the | |
| // sequence from array (mapping to a list of true/false values) | |
| const buttonSequence$ = correctSequenceArray$.flatMap(arr => { | |
| return buttonClicksIndex$ | |
| .windowWithCount(arr.length) | |
| .flatMap(btnClick => btnClick.sequenceEqual(correctSequence$)) | |
| }); | |
| percussion.addStream(buttonSequence$); | |
| // Track the number of clicks the user has made and group | |
| // them into a set based on length of sequence | |
| const buttonsClickCount$ = correctSequenceArray$ | |
| .flatMap(arr => buttonClicks$.bufferWithCount(arr.length)); | |
| percussion.addStream(buttonsClickCount$); | |
| // filter the buffered squence of clicks based on | |
| // whether the sequece was successfully entered (filter for 'true') | |
| const buttonSequenceCorrect$ = buttonSequence$ | |
| .takeUntil(buttonsClickCount$) | |
| .filter(equal => equal); | |
| percussion.addStream(buttonSequenceCorrect$); | |
| // Naming is hard... | |
| const sequenceCorrectAndClicks$ = | |
| // ZIP!!!! | |
| Rx.Observable.zip(buttonSequence$, buttonsClickCount$); | |
| percussion.addStream(sequenceCorrectAndClicks$); | |
| // array of results | |
| // 0: is boolean if squence was correct | |
| // 1: is list of the clicks made | |
| sequenceCorrectAndClicks$ | |
| .subscribe( (results) => { | |
| alert(`Sequence correct: ${results[0]}`); | |
| results[1].forEach(e => e.delegate.disabled = false); | |
| }); |
| <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.7/rx.all.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.min.js"></script> | |
| <script src="https://rawgit.com/grisendo/Percussion/master/dist/Percussion.min.js"></script> |
| *{ | |
| box-sizing: border-box; | |
| } | |
| html,body{ | |
| width: 100%; | |
| height: 100%; | |
| } | |
| body{ | |
| padding: 20px; | |
| } | |
| .wrapper{ | |
| height: 100%; | |
| display: flex; | |
| align-items: center; | |
| flex-wrap: wrap; | |
| justify-content: center; | |
| flex-flow: row wrap; | |
| align-content: center; | |
| button{ | |
| width: 33.333333333%; | |
| box-sizing: border-box; | |
| padding: 20px 0; | |
| display: inline-block; | |
| } | |
| } |