i'm pretty new rxjs , haven't read solution this. more detailed explanation in comments, want process key combination (i think buffer this) when specific key pressed (like pressing "o" wait short time other keys pressed), process key input otherwise (anything other "o" if "o" hasn't been pressed, or 'timeout' "o" has passed).
observable.fromevent(document, 'keydown') // want continue processing event if user pressed "o99" in series, // in pressed "o", followed "9" , "9" // think can buffer .buffer(() => observable.timer(1000)) .map((e) => 'option-99') // need pass keys through unbuffered if it's "o" (unless following "o") // in other words, "o99" buffered or something, "9" not, , processed .map((e) => e.keycode)
thanks
you have common case deal with, of event associated action depends on control state (i.e. have basic state machine). basically, if consider 2 control states : simple_key
, combo
, , 2 events : keyup
, , keyuptimer
, :
- in
simple_key
state- if key pressed
o
, switchcombo
state - if not
o
, remain in same state, , pass key downstream - if timer event, pass null value filtered out downstream
- if key pressed
- in
combo
state- we accumulate key pressed
- if timer events, revert
simple_key
state
so, map event action, need know control state in. operator scan
allows decide how process event depending on accumulated state.
it (https://jsfiddle.net/cbhmxaas/):
function getkeyfromevent(ev) {return ev.key} function iskeypressediso(ev) {return getkeyfromevent(ev) === 'o'} const key = 'key'; const timer = 'timer'; const combo = 'combo'; const simple_key = 'whatever'; const timespaninms = 1000; const keyup$ = rx.observable.fromevent(document, 'keyup') .map(ev => ({event: key, data: getkeyfromevent(ev)})); const keyuptimer$ = keyup$.flatmaplatest(eventstruct => rx.observable.of(eventstruct) // .tap(console.warn.bind(console, 'timer event')) .delay(timespaninms) .map(() => ({event : timer, data: null})) ); rx.observable.merge(keyup$, keyuptimer$) // .tap(console.warn.bind(console)) .scan((acc, eventstruct) => { if (acc.control === simple_key) { if (eventstruct.event === key) { if (eventstruct.data === `o`) { return {control: combo, keyorkeys : []} } else { return {control: simple_key, keyorkeys : eventstruct.data} } } else { // timer event return {control: simple_key, keyorkeys : null} } } else { // have 2 states, combo state here if (eventstruct.event === key) { return {control: combo, keyorkeys : acc.keyorkeys.concat([eventstruct.data])} } else { // timer event, have 2 events return {control: simple_key, keyorkeys : acc.keyorkeys} } } }, {control: simple_key, keyorkeys : null}) // .tap(console.warn.bind(console)) .filter(state => state.keyorkeys) // timer event in simple_key state .map (({control, keyorkeys}) => { // here associate action // if keyorkeys array, have combo // else have single key console.log('key(s) pressed', keyorkeys) return keyorkeys }) .subscribe (console.log.bind(console))
Comments
Post a Comment