Comunidad de diseño web y desarrollo en internet online

Clase que mejora el EventDispatcher de Actionscript 2

Aunque el manejo de eventos en ActionScript 2 no es tan refinado como el de su sucesor, AS 3, la clase EventDispatcher sí puede usarse en muchas situaciones, sobre todo cuando se trabaja con componentes, logrando un código más robusto y orientado a la Programación orientada a objetos. En algunas ocasiones los listeners de nuestra aplicación se quedan vivos aún cuando ya no los necesitamos y eso nos acarrea que la aplicación tenga unos resultados poco esperados (esto sucede sobre todo si usamos interfaces o programamos de afán :) ).
Por esa razón he modificado ligeramente la clase EventDispatcher de Macromedia añadiéndole algunas funcionalidades interesantes que listaremos a continuación:

1. A la función addEventListener se le añadió un nuevo argumento llamado "tagName":
Es un String con el cual podemos agrupar listeners de la misma funcionalidad. Se ve mejor con un ejemplo:

Código :

this.addEventListener("clic", onClic, "botones");
this.addEventListener("focus", onFocus, "botones");
this.addEventListener("exit", onExit, "botones");


Como ven todos tienen el mismo tagName ("botones" en este ejemplo).

2. Se añadió una nueva función estática "removeEventListenersForTagName":
Con esta podemos eliminar todos los listeners que tengan cierto tagName.

Código :

EventDispatcher.removeEventListenersForTagName("botones");
EventDispatcher.removeEventListenersForTagName("registro");
EventDispatcher.removeEventListenersForTagName("juego1");


3. Se añadió una nueva función estática "removeEventListenersForEvent":
Con esta podemos eliminar todos los listeners que tengan cierto evento y fueron registrados por nuestro EventDispatcher.

Código :

EventDispatcher.removeEventListenersForEvent("clic");
EventDispatcher.removeEventListenersForEvent("focus");
EventDispatcher.removeEventListenersForEvent("exit");


Hay que tener cuidado con esta función ya que se busca ese nombre de evento en toda la aplicación.

4. Se añadió una nueva función estática "removeEventListenersForScope":
Con esta podemos eliminar todos los listeners de cierta clase u objeto.

Código :

EventDispatcher.removeEventListenersForScope(this);
EventDispatcher.removeEventListenersForScope(this.oMain);
EventDispatcher.removeEventListenersForScope(RegisterManger);


5. Se añadió una nueva función estática "removeAllEventListeners":
Con esta eliminamos todos (repito, TODOS) los listeners que fueron registradas por nuestro EventDispatcher.

Código :

EventDispatcher.removeAllEventListeners();


6. A la función dispatchEvent se le añadió un nuevo argumento llamado "deleteListener": Es un Boolean que le indica a la función si debe eliminar el listener después de ejecutarlo. Si es True entonces despacha el evento y lo borra inmediatamente, si el False o undefined o null lo despacha pero no lo borra.

Código :

this.dispatchEvent({type:"clic", target:this}, true);
this.dispatchEvent({type:"clic", target:this}, false);
this.dispatchEvent({type:"clic", target:this});



Como ven no tenemos que ponernos a eliminar uno por uno los listeners que creamos, solo los agrupamos por un tagName o los encapsulamos en cierta clase y los matamos todos de un solo golpe.

Otra ventaja es que es 100% compatible con el EventDispatcher de Macromedia entonces podemos cambiar tranquilamente el import de mx.events.EventDispatcher por el de nuestro EventDispatcher.
Las demás funciones siguen igualitas y se utilizan de la misma manera (incluido el "initialize").

EventDispatcher.as

Código :

/**
 * Clase modificada de EventDispatcher de Macromedia
 * @author      JoH
 * @version     20071210
 */
//****************************************************************************
//Copyright (C) 2003 Macromedia, Inc. All Rights Reserved.
//The following is Sample Code and is subject to all restrictions on
//such code as contained in the End User License Agreement accompanying
//this product.
//****************************************************************************

/**
* base class for event listening and dispatching
*
* @helpid 3295
* @tiptext
*/
class com.npi.events.EventDispatcher
{
        // make a instance of ourself so we can add methods to other objects
        static var _fEventDispatcher:EventDispatcher = undefined;

        // these events do not get called via backdoor because of name collisions with other methods
        static var exceptions:Object = {move: 1, draw: 1, load:1};
        /**
        * object with all listeners
        */
        static var _queues:Object;
        static var _queuesCount:Number;
        // internal function for removing listeners
        static function _removeEventListener(queue:Object, event:String, handler):Void
        {
                if (queue != undefined)
                {
                        var l:Number = queue.length;
                        var i:Number;
                        for (i = 0; i < l; i++)
                        {
                                var o = queue[i].handler;
                                if (o == handler) {
                                        queue.splice(i, 1);
                                        return;
                                }
                        }
                }
        }

/**
* add listening and dispatching methods to an object
* @param object the object to receive the methods
*/
        static function initialize(object:Object):Void
        {
                if (_fEventDispatcher == undefined)
                {
                        _fEventDispatcher = new EventDispatcher;
                        EventDispatcher._queues = new Object();
                        EventDispatcher._queuesCount = 0;
                }
                object.addEventListener = _fEventDispatcher.addEventListener;
                object.removeEventListener = _fEventDispatcher.removeEventListener;
                object.dispatchEvent = _fEventDispatcher.dispatchEvent;
                object.dispatchQueue = _fEventDispatcher.dispatchQueue;
                //---
                object["__qc_"] = EventDispatcher._queuesCount;
                EventDispatcher._queuesCount++;
        }

        // internal function for dispatching events
        function dispatchQueue(queueObj:Object, eventObj:Object, deleteListener:Boolean):Void
        {
                var queueName:String = "__q_" + eventObj.type;
                var queue:Array = queueObj[queueName];
                if (queue != undefined)
                {
                        var i:String;
                        // loop it as an object so it resists people removing listeners during dispatching
                        for (i in queue)
                        {
                                var o = queue[i].handler;
                                var oType:String = typeof(o);

                                // a handler can be a function, object, or movieclip
                                if (oType == "object" || oType == "movieclip")
                                {
                                        // this is a backdoor implementation that
                                        // is not compliant with the standard
                                        if (o.handleEvent != undefined)
                                        {
                                                // this is the DOM3 way
                                                o.handleEvent(eventObj);
                                        }
                                        if (o[eventObj.type] != undefined)
                                        {
                                                if (EventDispatcher.exceptions[eventObj.type] == undefined)
                                                {       
                                                        // this is a backdoor implementation that
                                                        // is not compliant with the standard
                                                        o[eventObj.type](eventObj);
                                                }
                                        }
                                }
                                else // it is a function
                                {
                                        o.apply(queueObj, [eventObj]);
                                }
                                //---
                                if (deleteListener) 
                                {
                                        EventDispatcher._removeEventListener(queueObj[queueName], eventObj.type, o);
                                }
                        }
                }
        }

/**
* dispatch the event to all listeners
* @param eventObj an Event or one of its subclasses describing the event
*/
        function dispatchEvent(eventObj:Object, deleteListener:Boolean):Void
        {
                if (eventObj.target == undefined)
                        eventObj.target = this;

                this[eventObj.type + "Handler"](eventObj);

                // Dispatch to objects that are registered as listeners for
                // this object.
                this.dispatchQueue(this, eventObj, deleteListener);
        }

/**
* add a listener for a particular event
* @param event the name of the event ("click", "change", etc)
* @param the function or object that should be called
*/
        function addEventListener(event:String, handler, tagName:String):Void
        {
                var queueName:String = "__q_" + event;
                var oQueue:Object = new Object();
                if (this[queueName] == undefined)
                {
                        this[queueName] = new Array();
                }
                if (EventDispatcher._queues[queueName] == undefined)
                {
                        EventDispatcher._queues[queueName] = new Object();
                }
                _global.ASSetPropFlags(this, queueName,1);

                EventDispatcher._removeEventListener(this[queueName], event, handler);
                //---
                oQueue.tagName = tagName;
                oQueue.handler = handler;
                //---
                this[queueName].push(oQueue);
                EventDispatcher._queues[queueName][this["__qc_"]] = this[queueName];
        }

/**
* remove a listener for a particular event
* @param event the name of the event ("click", "change", etc)
* @param the function or object that should be called
*/
        function removeEventListener(event:String, handler):Void
        {
                var queueName:String = "__q_" + event;
                EventDispatcher._removeEventListener(this[queueName], event, handler);
        }
        
/**
 * Elimina todos las escuchas que tengan ese tag
 * @param       tagname Tag a eliminar
 */
        public static function removeEventListenersForTagName(tagName:String):Void
        {
                if (tagName != undefined)
                {
                        var i:String;
                        var j:String;
                        var k:String;
                        var queues:Object;
                        var queue:Object;
                        //---
                        for (i in EventDispatcher._queues)
                        {
                                queues = EventDispatcher._queues[i];
                                //---
                                for (j in  queues) 
                                {
                                        queue = queues[j];
                                        //---
                                        for (k in queue)
                                        {
                                                var o = queue[k].tagName;
                                                if (o == tagName)
                                                {
                                                        queue.splice(k, 1);
                                                }
                                        }
                                }
                        }
                }
        }
        
/**
 * Remueve todas las escuchas que tengan ese nombre de evento
 * @param       event Nombre del evento a eliminar
 */
        public static function removeEventListenersForEvent(event:String):Void
        {
                if (event != undefined)
                {
                        var j:String;
                        var k:String;
                        var queues:Object;
                        var queue:Object;
                        //---
                        queues = EventDispatcher._queues["__q_" + event];
                        //---
                        for (j in  queues) 
                        {
                                queue = queues[j];
                                //---
                                for (k in queue)
                                {
                                        queue.splice(k, 1);
                                }
                        }
                        //---
                        delete EventDispatcher._queues["__q_" + event];
                }
        }
        
/**
 * Remueve todas las escuchas de la Clase / Objeto
 * @param       scope Ruta de la Clase / Objeto a eliminar
 */
        public static function removeEventListenersForScope(scope):Void
        {
                if (scope != undefined)
                {
                        if (scope["__qc_"] != undefined)
                        {
                                var scopeNumber:Number = scope["__qc_"];
                                var i:String;
                                var j:String;
                                var k:String;
                                var queues:Object;
                                var queue:Object;
                                //---
                                for (i in EventDispatcher._queues)
                                {
                                        queues = EventDispatcher._queues[i];
                                        //---
                                        for (j in  queues) 
                                        {
                                                if (j == scope["__qc_"])
                                                {
                                                        queue = queues[j];
                                                        //---
                                                        for (k in queue)
                                                        {
                                                                queue.splice(k, 1);
                                                        }
                                                        //---
                                                        delete EventDispatcher._queues[i][j];
                                                        //---
                                                        break;
                                                }
                                        }
                                }
                        }
                }
        }
        
/**
 * Remueve todas las escuchas que fueron registradas por esta clase
 */
        public static function removeAllEventListeners():Void
        {
                var i:String;
                var j:String;
                var k:String;
                var queues:Object;
                var queue:Object;
                //---
                for (i in EventDispatcher._queues)
                {
                        queues = EventDispatcher._queues[i];
                        //---
                        for (j in  queues) 
                        {
                                queue = queues[j];
                                //---
                                for (k in queue)
                                {
                                        queue.splice(k, 1);
                                }
                        }
                }
                //---
                EventDispatcher._queues = new Object();
        }
}

Espero les sirva :)

¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.

Publica tu comentario

El autor de este artículo ha cerrado los comentarios. Si tienes preguntas o comentarios, puedes hacerlos en el foro

Entra al foro y participa en la discusión

o puedes...

¿Estás registrado en Cristalab y quieres
publicar tu URL y avatar?

¿No estás registrado aún pero quieres hacerlo antes de publicar tu comentario?

Registrate