Events (library & classes)

Categories:Flash

Overview

Summary

An object-oriented event system allowing the AS3 developer a more familiar way to use events in JSFL.

Contents

Concept

Flash's standard event mechanism is a simple callback-based event model, which allows the developer to add events via string, and have a callback (event handler) called when the event fires:

var eventId = fl.addEventListener("documentClosed", onDocumentClosed);

However, there are a few problems with the standard Flash event handler implementation:

  • It's impossible to keep track of (and therefore remove) listener ids between external script executions (i.e. in development)
  • No information about the event is passed to the event handler function
  • There's no overall management of registered event handlers

xJSFL's Event library and classes attempt to answer these shortcomings with a standard Event model and Event classes similar to AS3's, as well as the ability to add, remove and get events by event and type - and all between external calls.

Usage

Adding an event handler to fire on an event

The main difference with registering an event handle function between JSFL and xJSFL is that with xJSFL you supply the eventId you want to keep track of:

function onDocumentChanged(event)
{
    trace(event.document.name);
}

xjsfl.events.add(DocumentEvent.CHANGED, onDocumentChanged, 'onDocumentChanged');

Note that the function name and the eventId name are not related, nor do they have to be the same. It is the string name that is used to add and remove the callback - the callback itself is merely stored as a reference.

What to do within the event handler

Once the handler is added, and when an appropriate event is fired within Flash, the handler is called and from within you have access to the properties at the time of the event, via the event object.

Bear in mind though that due to some inherent limitations of the Flash event model, these cannot always be relied on to return a true state of the Flash environment at the time of the event.

Updating and removing the event handler

When it comes to updating the event handler you can simply add it again with the same name, or if at any point you want to remove the event handler, you simply call the remove() method with the type and name of the previously-added handler:

xjsfl.events.remove(DocumentEvent.CHANGED, 'onDocumentChanged');

Event types

Rather than simply calling an event handler function with no information about the event that took place, the xJSFL Event model defines specific Event classes, instances of which are passed to event handler functions in a manner already familiar to AS3 developer.

Event Type Description CS Version Event Constant
Document publish A document is about to be published 5.5 DocumentEvent.PUBLISH
Document published A document was published 5.5 DocumentEvent.PUBLISHED
Document saved A document was saved 5.5 DocumentEvent.SAVED
Document new A new document was created 4 DocumentEvent.NEW
Document opened A document was opened 4 DocumentEvent.OPENED
Document closed A document was closed 4 DocumentEvent.CLOSED
Document changed A new document was opened or tabbed to 4 DocumentEvent.CHANGED
Layer changed A new layer selection was made 4 LayerEvent.CHANGED
Frame changed A new frame selection was made 4 FrameEvent.CHANGED
Mouse move The mouse was moved 4 MouseEvent.MOVE

These event instances have both a specific type, as well as a common name property that maps directly to the standard eventType strings as accepted by the standard fl.addEventlistener() function. Note however that the xJSFL Event constant names are slightly differently to the Flash event strings.

Additional properties are specific to each event class.

Native JSFL event model limitations

Unfortunately, due to the way Flash seems to order Frame event handlers, there are some severe limitations to Flash's native event model.

The JSAPI appears to fire a frameChanged event before it has updated the document / timeline properties, which results in frame Events reporting the previous document and timeline.

At the moment, I don't know how to solve this. I've experimented with lastParam properties, comparing the Date of the callback, firing events in order with pre and post handlers, attempting to force a document update by calling flash or document methods first, but so far every route has been a dead end. It may just be that it's not possible.

Other limitations include:

  • Although "frameChanged" fires when you edit a new symbol, the document properties do not update in time, so again, you end up with the wrong document/timeline data fed into the Event.
  • timeline.getSelectedframes() often returns nothing from within an event handler, so is effectively useless for interactive tools relying on the current frame selection.
  • Multiple events can be fired for what seem like single events to the user - for example, selecting the same layer fires a layer event once, but selecting a new layer fires a layer event twice, with timeline.currentLayer reporting the same layer for both events.

If you can live with these fairly annoying limitations, you may be able to get some mileage out of at least the Document, Layer & Mouse events.

Event API

The event API is the central place to add and remove event handler functions.

add(type, callback, name, scope)

Add an event handler function for a particular event type

Parameters:

  • type String A String Event constant
  • callback Function A callback function to be fired when the event happens
  • name String A named id with which to get, delete or overwrite the callback
  • scope Object An optional scope in which to call the callback function

The following example traces the name of the current document when the user creates or changes the document in the Flash IDE, and also overwrites any current DocumentEvent.CHANGED handlers:

function onDocumentChanged(event)
{
    trace(event.document.name);
}
xjsfl.events.add(DocumentEvent.CHANGED, onDocumentChanged, 'onDocumentChanged');
// On changing the current document
Untitled-2

If you need to register a method on an object that needs to self-reference, be user to pass in the scope:

xjsfl.events.add(DocumentEvent.CHANGED, handlers.onDocumentChanged, 'onDocumentChanged', handlers);

Note that as event handler names could be overwritten by any running JSFL code, you should take the trouble to namespace them if making tools for collaborative environments.

The following example sets a namespaced event handler name from within a module (and necessarily sets the scope as well):

xjsfl.events.add(DocumentEvent.CHANGED, this.onDocumentChanged, 'myModule.onDocumentChanged', this);

remove(type, name)

Remove an event handler function for a single or all event types

Parameters:

  • type String A String Event constant
  • name String The name of a previously-registered callback

The following example removes an existing named handler:

xjsfl.events.remove(DocumentEvent.CHANGED, 'onDocumentChanged');

You can also remove handlers of the same name from multiple event types by passing the name of a single event handler.

The following example removes handlers registered using the name documentHandler from all event types:

xjsfl.events.remove('documentHandler');

removeAll(type)

Remove all event handler functions for a single, or all event types

Parameters:

  • type String An optional String Event constant

The following example removes all existing DocumentEvent.CHANGED handlers:

xjsfl.events.removeAll(DocumentEvent.CHANGED);

The following example removes all existing handlers, for all event types:

xjsfl.events.removeAll();

Note that you should never remove event handlers by type in final production code as other modules may be reliant on handlers they previously added.

get(type, name)

Get a reference to an event handler function for an event type

Parameters:

  • type String A String Event constant
  • name String A name of a previously-registered callback

Returns:

  •   Function An event handler function or null if it doesn't exist

The following example retrieves the function assigned as 'onMouseMove' for the MouseEvent.MOVE event:

var callback = xjsfl.events.get(MouseEvent.MOVE, 'onMouseMove');
trace(callback);
function onMouseMove(event)
{
    trace(event);
}

Event classes

This section describes the Event classes that will be dispatched from the main xjsfl.event library.

DocumentEvent(type)

An object representing a the JSFL Event that fires when a user interacts with a document

Properties:

  • type String The type of event
  • document Document The Document object the event occurred in

Event types

  • CS4:
    • NEW A new document was created
    • OPENED A document was opened
    • CLOSED A document was closed
    • CHANGED A new document was opened or tabbed to
  • CS5:
    • PUBLISH A document is about to be published
    • PUBLISHED A document was published
    • SAVED A document was saved

The following example traces the name of a new document, when created:

function onDocumentNew(event)
{
    trace(event.document.name);
}
xjsfl.events.add(DocumentEvent.NEW, onDocumentNew);
// On creating a new document
Untitled-1

LayerEvent()

An object representing a the JSFL Event that fires when a user changes a layer

Properties:

  • type String The type of event, which is always 'changed'
  • document Document The Document object the event occurred in
  • timeline Timeline The Timeline object the event occurred on
  • layer Layer The Layer object the event occurred on

Event types:

  • CHANGED A new layer selection was made

The following example adds an event handler to be called every time a different layer is selected (this includes changing documents and timelines), or a new layer is created:

function onLayerChanged(event)
{
    trace(event);
}
xjsfl.events.add(LayerEvent.CHANGED, onLayerChanged);
// On changing layer, or creating a new layer
[object LayerEvent timeline="Scene 1" layer="Layer 2"]

FrameEvent()

An object representing a the JSFL Event that fires when a user changes a frame

Properties:

  • type String The type of event, which is always 'changed'
  • document Document The Document object the event occurred in
  • timeline Timeline The Timeline object the event occurred on
  • layer Layer The Layer object the event occurred on
  • frame Frame The Frame object the event occurred on

Event types:

  • CHANGED A new frame selection was made

The following example adds an event handler to be called every time a different frame is selected (this includes changing documents, timelines and layers), or a new frame is created:

function onFrameChanged(event)
{
    trace(event);
}
xjsfl.events.add(FrameEvent.CHANGED, onFrameChanged);
// On changing frame, or creating a new frame
[object FrameEvent timeline="Scene 1" layer="Layer 2" frame="11"]

MouseEvent()

An object representing a the JSFL Event that fires when a user move the mouse

Properties:

  • type String The type of event, which is always 'move'
  • shift Boolean A flag indicating if the SHIFT key is down
  • ctrl Boolean A flag indicating if the CTRL key is down
  • alt Boolean A flag indicating if the ALT key is down
  • x Number The x location in pixels of the mouse on the Flash stage
  • y Number The y location in pixels of the mouse on the Flash stage

Event types:

  • MOVE The mouse was moved

The following example adds an event handler to be called every time the mouse is moved:

function onMouseMove(event)
{
    trace(event);
}
xjsfl.events.add(MouseEvent.MOVE, onMouseMove);
// On moving the mouse
[object MouseEvent x="424.95" y="7" shift="false" ctrl="false" alt="false"]

Comments are closed.