RxJS Playground

Simple place for me to mess around with RxJS

by Josh Carroll

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.0.1/Rx.js"></script>
<div class="container">
  <div class="event" id="click-event">Click</div>
  <div class="event" id="doubleclick-event">Double Click</div>
  <div class="event" id="keydown-doubleclick-event">Key Down Double Click</div>
</div>

CSS

.container {
  margin: 20px;
}

.event {
  margin: 10px;
  border: 1px solid black;
  border-radius: 5px;
  padding: 10px;
}

.animate-event {
  animation: animationFrames ease-in-out 0.25s;
  animation-iteration-count: 1;
  transform-origin: 50% 50%;
  -webkit-animation: animationFrames ease-in-out 0.25s;
  -webkit-animation-iteration-count: 1;
  -webkit-transform-origin: 50% 50%;
  -moz-animation: animationFrames ease-in-out 0.25s;
  -moz-animation-iteration-count: 1;
  -moz-transform-origin: 50% 50%;
  -o-animation: animationFrames ease-in-out 0.25s;
  -o-animation-iteration-count: 1;
  -o-transform-origin: 50% 50%;
  -ms-animation: animationFrames ease-in-out 0.25s;
  -ms-animation-iteration-count: 1;
  -ms-transform-origin: 50% 50%;
}

@keyframes animationFrames {
  0% {
    transform: scaleX(1.00) scaleY(1.00);
  }
  50% {
    transform: scaleX(1.10) scaleY(1.10);
  }
  100% {
    transform: scaleX(1.00) scaleY(1.00);
  }
}

@-moz-keyframes animationFrames {
  0% {
    -moz-transform: scaleX(1.00) scaleY(1.00);
  }
  50% {
    -moz-transform: scaleX(1.10) scaleY(1.10);
  }
  100% {
    -moz-transform: scaleX(1.00) scaleY(1.00);
  }
}

@-webkit-keyframes animationFrames {
  0% {
    -webkit-transform: scaleX(1.00) scaleY(1.00);
  }
  50% {
    -webkit-transform: scaleX(1.10) scaleY(1.10);
  }
  100% {
    -webkit-transform: scaleX(1.00) scaleY(1.00);
  }
}

@-o-keyframes animationFrames {
  0% {
    -o-transform: scaleX(1.00) scaleY(1.00);
  }
  50% {
    -o-transform: scaleX(1.10) scaleY(1.10);
  }
  100% {
    -o-transform: scaleX(1.00) scaleY(1.00);
  }
}

@-ms-keyframes animationFrames {
  0% {
    -ms-transform: scaleX(1.00) scaleY(1.00);
  }
  50% {
    -ms-transform: scaleX(1.10) scaleY(1.10);
  }
  100% {
    -ms-transform: scaleX(1.00) scaleY(1.00);
  }
}

TypeScript

const Observable = Rx.Observable;

class EventElement {

  private elem: any;
  private animation = 'animate-event';

  constructor(selector: string) {
    this.elem = document.querySelector(selector);
  }

  animate(){				this.addAnimationEndEvent('webkitAnimationEnd','mozAnimationEnd','MSAnimationEnd','oanimationend','animationend');
    
    this.elem.classList.add(this.animation);
  }
  
  private addAnimationEndEvent(...events:string[]){
  	const _this = this;
    
  	events.forEach(e => {
    	_this.elem.addEventListener(e, function handler(){
    	
        _this.elem.classList.remove(_this.animation);

        _this.elem.removeEventListener(e, handler);
      });
    });
  }
}

const noop = () => {};

const click$ = Observable.fromEvent(document, 'click');
const keydown$ = Observable.fromEvent(document, 'keydown');

const clickEventTarget = new EventElement('#click-event');
const doubleClickEventTarget = new EventElement('#doubleclick-event');
const keydownDoubleClickEventTarget = new EventElement('#keydown-doubleclick-event');

click$.do(() => { clickEventTarget.animate(); })
.subscribe(noop);

const doubleClicks$ = click$
	.map(e => { 
  	return { e, ticks: Date.now() };
   })
	.pairwise()
  .map(pairs => {
  	const previous = pairs[0];
    const latest = pairs[1];
    const elapsedMilliseconds = latest.ticks - previous.ticks;
    
    return { e:latest, elapsedMilliseconds };
  })
  .filter(event => { return event.elapsedMilliseconds <= 250; });

const keydownWithDoubleClick$ = keydown$
	.skipUntil(doubleClicks$)
  .do(() => { keydownDoubleClickEventTarget.animate(); })
  .subscribe(noop);

doubleClicks$
	.do(() => {
  	console.log('double click');
  	doubleClickEventTarget.animate(); 
   })
  .subscribe(noop);