Implementation

OK, let's start by creating the 3 main observables we need for our solution that will produce the corresponding mouse event values:

Composing mouse_hold$

OK, now we need to compose mouse_hold$ according to this algorithm:

When mouse_Down$ emits a value we should start a 2000ms timer If the timer emits value in 2000ms— we should emit a string: HOLD If mouse_Up$ or mouse_Move$ emit a value before the 2000ms timer emission — we should complete mouse_hold$

For step 1 we will use the RxJS timer function. Usually, it is used for periodic value emissions, but if it is provided with one argument (inactivity duration) — then it emits value (zero) one time only.

const timer$ = timer(2000);

So for step 2 we should use the switchMap operator to return an Observable that will emit a string: HOLD

Here we make a switch two times: when mouse_Down$ emits — we switch to the timer$ Observable. In 2000ms timer$ will emit and we will switch to an of('HOLD') Observable. So at the end, the mouse_Hold$ subscribers will get a HOLD string on a 2000ms period.

Now we will implement step 3 — if one of mouse_Up$ or mouse_Move$ emits a value — we should complete the observable. We can reach this by using the merge function (to combine values from both mouse_Up$ or mouse_Move$ ) and the takeUntil operator — to complete mouse_Hold$ if any of them emits.

Composing mouse_drags$

OK, now we need to compose mouse_drags$ according to the following algorithm:

When mouse_Down$ emits a value, we start waiting for both the mouse_hold$ and mouse_move$ observables. If mouse_move$ emits (before mouse_hold$ emits)— we should continue re-emitting the mousemove event object (our main goal actually). If mouse_Up$ or mouse_hold$ emit a value — we should complete mouse_drags$.

As in the previous example for step 1 we will use switchMap.

For step 2 we will use switchMap as in a previous example.

mouse_drags$ = mouse_Down$.pipe(

switchMap((time) => mouse_Move$)

)

For step 4 we will use takeUntil and merge as we did in a previous example:

mouse_drags$ = mouse_Down$.pipe(

switchMap((time) => mouse_Move$,

takeUntil(merge(mouse_Up$, mouse_Hold$)),

)

Seems like it is done, isn’t it?