moribvndvs / ng2-idle

Responding to idle users in Angular (not AngularJS) applications.
https://moribvndvs.github.io/ng2-idle
Apache License 2.0
315 stars 128 forks source link

Documentation on InterruptSource #51

Closed arloduff closed 6 years ago

arloduff commented 7 years ago

Is it possible to get more documentation on how to implement our own custom interrupt source? I haven't seen this anywhere in the documentation.

In my case, I want the user to no longer be considered idle whenever he moves his mouse or presses a key on the keyboard, not just within the tab, but anywhere on the computer, or at least in the browser.

I'm seeing InterruptSource as an abstract class, but am not sure which properties it wants me to define when I extend from it It also looks like attachFn and detachFn are parameters passed to the constructor when instantiated, but I don't understand what should happen in these functions or what the purpose of them is. I assume attachFn attaches the event it wants to listen to to this somehow but is detachFn called during destruction?

alex-ponce commented 6 years ago

Please respond to this request. It is the minimum you could do to help us implement custom interrupt sources

moribvndvs commented 6 years ago

Have you looked at the source code for any of the interrupts? It's intentionally pretty vague, because I don't want to create too much of an opinion about what your custom source needs to do. However, EventTargetInterruptSource is the most used source and is a good example of implementing a custom interrupt source.

In its simplest form, an interrupt source simply needs to emit from the onInterrupt event emitter whenever your custom code decides the user (or some code on behalf of the user) has done something that should interrupt the idle timeout.

Your actual implementation, however, may be more sophisticated than that. Here's what happens:

  1. You specify interrupt sources using idle.setInterrupts() and provide it an array of sources (anything that derives from InterruptSource).
  2. For each source, it is wrapped in an instance of Interrupt, which is used to manage the event emitter subscription between Idle and the interrupt source. This part is not particularly important, and is mainly used internally for book keeping and clean up.
  3. Each wrapped interrupt is subscribed to a function in idle that calls self.interrupt() and passes any arguments from the interrupt source.
  4. When you call idle.watch, idle enumerates all interrupts and calls resume(), which in turn will call the attach() function on the source. This is where your source should, if necessary, begin listening for whatever your user activity is that can cause an interrupt.
  5. When your interrupt source needs to cause an interrupt, it should emit via onInterrupt.emit and pass any relevant args. This will in turn cause the function I mentioned in item #3 above, which will cause idle to reset the idle count down.
  6. When idle.stop is called, the idle service is destroyed, or the user goes into the timeout state, interrupt.pause is called, which will in turn call the detach() function on the source. This is where your source should (again, if necessary) stop listening for user activity because we are in a state we no longer want to let them cause interrupts.

So using EventTargetInterruptSource as an example, here's what it does.

In the constructor, you provide a target (which is anything that can be made Observable) a space-delimited list of event names on the target that should trigger an interrupt, and optionally time in milliseconds that will throttle incoming events (so we don't swarm your app with user input). We split the events list and enumerate for each event, creating an observable event source, and adding it to a list of event sources that we need to keep track of so we can properly dispose them later. It then creates a handler for the attach and detach methods. Attach simply enumerates through each event source and creates a subscription that emits onInterrupt, and detach enumerates through each subscription we created and unsubscribes.

So now that we've constructed an instance, when a user causes one of the specified events on target, it'll cause an interrupt while the source is attached. When the source is detached, it removes all event handlers and stops listening for user activity.

Attaching and detaching is important in the context of browser events to prevent memory leaks and avoid performance problems. However, that implementation detail is up to your custom handler. I do provide it in the base class so you can receive notification when idle is or isn't requesting interrupts, but if you don't need to attach or detach, you can simply ignore attach/detach and focus on working with onInterrupt.

alex-ponce commented 6 years ago

Thank you very much for such detailed response. This will certainly put me on the right path.

pjyoti1235 commented 6 years ago

i actually wanted the idle.setInterrupts for only mouse click events not for hover or any other event...don't know how to go about it

rahul2270 commented 6 years ago

@alex-ponce Can you or someone provide a sample code for setting a list of interrupts. For example, I specifically want the system to remain idle during mouse hovers. Is there a link or doc for exact values of interrupts?

Peroucho8 commented 5 years ago

@rahul2270 did you find any example for setting a list of interrupts. I specifically just want to interrupt only on mouse click

vhdinh commented 4 years ago

@Peroucho8 @pjyoti1235 @rahul2270
I was able to get my custom interruption source. Here is an example of how I did it:

this.idle.setInterrupts(
      [
        new EventTargetInterruptSource(document, 'mousemove'),
        new EventTargetInterruptSource(document, 'mousedown'),
        new EventTargetInterruptSource(document, 'mouseup'),
        new EventTargetInterruptSource(document, 'click')
      ]
    );

Hope this helps