Q: How to create a toggle stream in RxJS? I'd like to create a steam that toggles based on keyup and keydown. The key code is emitted once on a keydown event and emitted again on the keyup event. I used distinctUntilChanged to prevent multiple key codes from being sent while keydown fires. The problem with my code is that I can't do successive keydown and keyup on the same key code because of the distinctUntilChanged.
Currently, pressing and releasing 'a' followed by 'b' works, but not 'a' followed by 'a'.
Requirements
What I want to achieve is:


*

*when the key is down, do some task

*when the key is up, stop doing that task

*multiple keys can be down or up (so can't use the keypress event)

*different actions are associated with different keys (think of 'a' for action-1 and 'b' for action-2)


Code
var getKeyCode = function(e) { return e.which; }
var target = document.querySelector('body');

var keyDownStream = Rx.Observable.fromEvent(target, 'keydown')
    .distinctUntilChanged(getKeyCode);

var keyUpStream = Rx.Observable.fromEvent(target, 'keyup')
    .distinctUntilChanged(getKeyCode);

var toggleStream = Rx.Observable.merge(keyDownStream, keyUpStream);

toggleStream.subscribe(function(e) {
    console.log(e.which);
});


A: I used:
var toggleStream = Rx.Observable.fromEvent(document.body, 'keydown').filter(function ( e, index ) {
  return index < 1;
}).takeUntil(Rx.Observable.fromEvent(document.body, 'keyup')).repeat();

toggleStream.subscribe(function ( e ) {
 // the task should go here 
 console.log("key down :" + e.which);
});

You can find a jsbin here : http://jsbin.com/xuqasawese/edit?html,js,console,output
Currently, pressing and releasing 'a' followed by 'b' works, and also 'a' followed by 'a'. However, you can imagine that you press key 'a' and without releasing that key, press another one 'b' and release 'b'. Then press another key 'c', and your action will be executed. It's kind of an edge case, but do you have any intended behaviour should that happen?

A: Found the solution was to move the distinctUntilChanged to the merged observable and filter by event type and keycode. This would ensure that the subscribers are notified once for the keydown event and once for the keyup event for the same key.
var filterByTypeAndKeyCode = function(e) { return e.type + e.which; }
var target = document.querySelector('body');
var keyUpStream = Rx.Observable.fromEvent(target, 'keyup');
var keyDownStream = Rx.Observable.fromEvent(target, 'keydown');

Rx.Observable.merge(keyDownStream, keyUpStream)
    .distinctUntilChanged(filterByTypeAndKeyCode)
    .subscribe(function(e) {
        console.log(e.which);
    });

