tillda
tillda

Reputation: 18690

Distinguishing user-triggered and code-triggered events

I have a component that encloses a video: <div class="component"><video src="..." /></div>.

Now I want to manage the state of of the playback in two ways:

  1. listen for the playback state that can be changed by clicking on the native play/pause button and do stuff with it (change component layout, notify other components...)

  2. manually trigger the playback from outside via lets say myComponent.playContent()

I don't know how to manage this correctly. For example when a user clicks on the native video control a play event is dispatched. When i manually call myComponent.playContent() which calls domVideo.play() the play event is also dispatched, so if I just listen for the play event it gets mixed up or called twice etc.

The problem is that two different things are mixed here.

First, a playback start can be triggered by user clicking on the native control, in which case I want to catch the event as and do all sort of stuff with it. This is the typical "bubbling", buttom-up flow.

Second, the program - usually the component - wants to trigger the playback in a "top down" way and here I want to differentiate the fired event to avoid treating it as user-created play event.

I had this problem many times, for example with tab-changing events in ExtJS's tab panels (tabchange event) and I don't know how to adress this in an event-based programming paradigm.

I'm looking for a general solution or a correct approach. It is not only about the native DOM events. I have a YT.Player (a YouTube player) object with its own events that has the same model and I'm suffering the same problem.

EDIT: Some trick with setTimeout and cancelling is possible, but I want to avoid that.

Upvotes: 1

Views: 353

Answers (1)

Borek Bernard
Borek Bernard

Reputation: 53352

I'm not sure about DOM specifics but let me tell you how it would work in Flex / Flash Player which is also client-side, event-based runtime / programming model.

So let's have a component C (for example, the video player from your example) and an application A - simply something that contains your component (could be a sub-application, application module etc.; let's just call it application).

Public API of the component is something like this:

component VideoPlayer
    function play()
    event playStateChange

I'll describe two situation, one without an MVC framework ("bare-bone" solution) and one with an MVC framework in place.

1) Without any MVC framework

The application needs to have a reference to the component and call something like this somewhere:

videoPlayer.addEventListener("playStateChange", function() {...})

If it needs to start the playback on the VideoPlayer, it would just call

videoPlayer.play();

Simple.

(I don't understand the problem you describe at the bottom of the question, i.e. why calling play() should dispatch the same event again - in Flex, programmer would need to explicitly do that and it would possibly be a mistake; of course it might make sense to dispatch differently named event if necessary but that is another thing.)

2) With an MVC framework

Flex applications are usually quite large with deeply nested hierarchies of separate screens, content panes, containers, components etc. so it might not be practical for the application to have direct reference to all components in the application.

Therefore, MVC frameworks (not named correctly but let's leave that aside...) usually provide a central event bus through which different parts of the application can communicate together. So with this framework in place, any code anywhere in the application could do something like this:

eventBus.dispatchEvent("globalPlayEvent")

and the component (VideoPlayer) would do something like this during its instantiation:

eventBus.addEventListener("globalPlayEvent", function() {
    play();
}

The communication in opposite direction would be similar - the component would just dispatch a "playStateChange" on some global event dispatched / event bus and anyone interested could handle it. In this model, you don't depend on event bubbling which I take as good.

Does this answer your question?

Upvotes: 0

Related Questions