Search code examples
javascriptreactive-programmingkefir.js

Capture all key inputs until ENTER is hit in a reactive programming way


In Javascript and using Kefir, I'd like to capture all key inputs until ENTER is hit. So far, I've managed to do this using bufferWhile like

var inputValues = Kefir
  .fromEvents(document.querySelector('body'), 'keydown')
  .bufferWhile(event => event.keyCode!=13);

var result = inputValues.toProperty(() => "");
result
.onValue(x => elm.innerHTML = x.slice(0,-1).map(y => String.fromCharCode(y.keyCode)).join(''))
.onError(() => elm.innerHTML = "?");

but initially I wanted to use a regular scan as in

var inputValues = Kefir
  .fromEvents(document.querySelector('body'), 'keydown')
  .scan((acc, y) => acc.concat(y), "");

but then how do I:

  1. Output the accumulator when ENTER is hit?
  2. Restart the accumulator to start a new keystroke sequence?

essentially, how do you compose bufferWhile using scan and a single stream? The answer doesn't have to be specifically about Kefir though, any FRP pseudo-code will do.


Solution

  • I'm not sure this is what you want. In general, idea is to separate stream of confirmation and fulfilling. And combine it in some way:

    const input$ = ...;
    const key$ = input$.filter(isNotEnter).map(toChar);
    const enter$ = input$.filter(isEnter);
    
    const confirm$ = Kefir.merge([
        enter$,
        key$.debounce(1000)
    ]);
    
    key$.bufferBy(confirm$);