Cristalab

Clase que mejora el EventDispatcher de Actionscript 2

Por: JoH + 09.02.2008

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 Sonrisa ).
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 Sonrisa

Etiquetas actionscript

Comentarios | Enviar un comentario
Está bien esa clase, muy útil Thumbs up
Por: Zguillez
este action ejerce una funcion colateral al momento de plantear las paginas web DHTML o de exploraciòn
Por: Luis Miguel _blog
Deja un comentario
IMPORTANTE

Recuerda ser respetuoso, no insultes a otras personas, ni uses palabrotas, hay una persona al otro lado de la pantalla.

Habla bien, NO ESCRIBAS EN MAYUSCULA TODO, no escribas como en un SMS, evita cosas como "ke", "x q" y demás abreviaciones.

Aquí funcionan las etiquetas de los foros, puedes usar [b] para negrita, [img] para las imágenes, [url] para los enlaces, etc.

Si tienes preguntas técnicas, envíalas mejor al foro.