Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating events with google closure

I would like to use events to communicate between my objects in a google closure (GC) environment.

Suppose I have two classes foobar.Boss and foobar.Employee. The Boss wants to know when the Employee has made coffee, and whether or not that coffee is decaf (he's laying off the caffeine this week).

GC has made classes available that seem to provide the means to do this, goog.events.Event and goog.events.EventTarget.

Without knowing better, I'd think it would work like this:

foobar.Employee.prototype.makeCoffee = function(isDecaf)
{        
    this.coffeeMaker.putCoffeeInMachine(isDecaf);
    this.coffeeMaker.start();
    var event = new goog.event.Event('COFFEE_ON', { isDecaf: isDecaf });
    goog.events.dispatchEvent(event);
}

foobar.Boss.prototype.addEmployee = function(employee)
{
    ...
    goog.events.listen(employee, 'COFFEE_ON', function(e)
    {
        if (e.target.isDecaf)
        {
            this.refillMug();
        }
    }, false, this);
    ...
}

Is this a correct pattern? I am confused by the class goog.events.EventTarget -- how does a target dispatch events? Doesn't a target have things happen to it?

This question is helpful, but a more direct answer would be appreciated.

like image 789
Ben Flynn Avatar asked Jan 31 '12 22:01

Ben Flynn


People also ask

What is the closure library used for?

Closure Library is a powerful, low-level JavaScript library designed for building complex and scalable web applications. It is used by many Google web applications, such as Google Search, Gmail, Google Docs, Google+, Google Maps, and others. For more information, visit the Google Developers or GitHub sites.

What is an event listener?

An event listener is a procedure in JavaScript that waits for an event to occur. The simple example of an event is a user clicking the mouse or pressing a key on the keyboard.

What is GOOG JavaScript?

The Google Closure library is a powerful JavaScript framework and includes features which are also interesting outside of a browser environment, e.g. implementations of common algorithms (encryption, geometry, time and date handling, ...), data structures (tries, pools, priority queues, ...) and support for functional ...


2 Answers

Having looked at this for a while, my understanding is now that the EventTarget in fact plays a dual roll of being the entity that dispatches events and the entity that is listened to. So one option would be to have Employee inherit goog.events.EventTarget but I have gone a different route.

First I created a new event type that would let the Boss know if the coffee was decaf.

/**
 * @constructor
 * @extends {goog.events.Event}
 */
foobar.CoffeeEvent = function(isDecaf)
{
  goog.events.Event.call(this, 'COFFEE_ON');
  this.isDecaf = isDecaf;
};
goog.inherits(foobar.CoffeeEvent, goog.events.Event);

Next I created an event listener type to dispatch these events.

/**
 * @constructor
 * @extends {goog.events.EventTarget} 
 */
foobar.CoffeeEventTarget = function()
{
  goog.events.EventTarget.call(this);
};
goog.inherits(foobar.CoffeeEventTarget, goog.events.EventTarget);

I added an object of this type to my Employee.

foobar.Employee = function()
{
  ...
  this.coffeeEvents = new foobar.CoffeeEventTarget();
  ...
}

When the employee refills the coffee:

foobar.Employee.prototype.makeCoffee = function(isDecaf)
{        
    this.coffeeMaker.putCoffeeInMachine(isDecaf);
    this.coffeeMaker.start();
    var event = new foobar.CoffeeEvent(isDecaf);
    this.coffeeEvents.dispatchEvent(event);
}

Mr. Bossman listens for this.

foobar.Boss.prototype.addEmployee = function(employee)
{
    ...
    goog.events.listen(employee.coffeeEvents, 'COFFEE_ON', function(e)
    {
        if (e.isDecaf)
        {
            this.refillMug();
        }
    }, false, this);
    ...
}

Note that this won't tell me which employee refilled the coffee, because the event target will an instance of CoffeeEventTarget. If you wanted all of Employee in there I suppose you could add it as a member field. If you were OK with inheriting to Employee from goog.events.EventTarget then you get Employee for free as the target.

like image 151
Ben Flynn Avatar answered Sep 30 '22 11:09

Ben Flynn


The way I think of EventTarget is this:

A button is a target, which you can register to be notified about its click event whenever one takes place. Thus, the "target" of a click is the button (you aim at the button, then click on it). But when the button gets clicked, it's not the mouse that tells everyone that the button was clicked - the button itself dispatches that message.

To touch on the question brought up by @ben-flynn about why would someone need/want to subclass EventTarget:

If you want to listen for key down events, you probably care about what key was pressed. The way you'd know what key was pressed is by looking up the keyCode field on the event object that is dispatched by the KeyDownEventTarget. On the other hand, a ButtonEventTarget dispatches a different event object, namely a ClickEvent, which does not have a keyCode field in it. So to summarize, the reason you'd subclass EventTarget is so whoever is listening for events that will be dispatched by that target know what event object will be dispatched when the event is triggered.

like image 33
rodrigo-silveira Avatar answered Sep 30 '22 13:09

rodrigo-silveira