Comunidad de diseño web y desarrollo en internet

Asignar eventos a botones de una película Flash desde un XML

Este tip se me ocurrió mientras desarrollaba una aplicación que contendría una gran cantidad de botones con distintos diseños, cada uno diferente, así que era imposible hacer un patrón y reutilizarlos. Además, cada uno de estos dispararía un enlace distinto que el cliente aun no sabía cual, así que el "editaría" después el FLA con la información final.

Cansado de convertir cada vector en botón y luego colocarle un nombre de instancia, pensaba en como haría el cliente para editar las url. Se me ocurrió crear un XML con los nombres de instancia de los botones y las URL, y así poder evitar que el cliente meta la mano al FLA.

La idea es simple y haremos un ejemplo inicial con 5 botones, para eso ya tengo un XML con los nombres de instancia y las URL de cada botón, algo así:

Código :

<data>
   <d btn='botonZguillez' url='zguillez.html'/>
   <d btn='botonZah' url='zah.html'/>
   <d btn='botonElecash' url='elecash.html'/>
   <d btn='botonXklibur' url='xklibur.html'/>
   <d btn='botonOtaku' url='otaku.html'/>
</data>


Por otro lado, tenemos nuestro FLA con los 5 botones y sus respectivos nombre de instancia(notemos que los nombres de instancia no llevan un patrón o son consecutivos).

Lo primero que haremos es cargar el XML mediante una clase

Código :

package cristalab.utils{
   
   import flash.events.*;
   import flash.net.*;
   
   public class LoaderXML extends EventDispatcher{
      
      public static var ACTION:String = "action";
      public var _data:XML;
      
      public function LoaderXML (){}

      //metodo para cargar el XML, recibe como paremetro la url del archivo
      public function loadXML(url:String):void{
         var urlLoader:URLLoader = new URLLoader(new URLRequest(url));
         urlLoader.addEventListener(Event.COMPLETE, complete);
      }
      
      private function complete(e:Event):void{
         _data = new XML(e.target.data);
         dispatchEvent(new Event(LoaderXML.ACTION));
         
      }
   }   
}


Ahora desde nuestra clase principal llamamos a la clase LoaderXML

Código :

package {
   
   import flash.events.*;
   import flash.display.*;
   import flash.ui.*;
   import cristalab.utils.*;

   public class Main extends MovieClip{
      
      private var t:LoaderXML;
      
      public function Main(){
         t = new LoaderXML();          
         t.loadXML("data/data.xml");
         //cuando cague el XML llamamos al metodo compare
         t.addEventListener(LoaderXML.ACTION, compare);
      }
      
      private function compare(e:Event):void{
         trace("aqui pondremos el código para hacer la magia");      
      }
   }   
}


Ahora si podemos empezar a hacer código en el método compare, para eso crearemos un for que nos permita recorrer el XML, sacando el nombre de instancia y verificando su existencia en el mcContenedor (gracias Otaku)

Código :

var tmpBTN:SimpleButton;
var name:String;
var miXML:XML = e.target._data;

for(var i:int=0; i< miXML.d.length() ; i++){
   name = miXML.d.@btn[i];
   if( mcContenedor.getChildByName( name ) != null )
   {
      //AQUI EXISTE EL BOTON
   } 
}


Ya casi tenemos todo listo, ahora solo nos queda agregar el evento al boton. También guardo el valor de i en tabIndex para saber la ubicación que tiene en el XML. El método queda así:

Código :

      private function compare(e:Event):void{
         var tmpBTN:SimpleButton;
         var name:String;
         var miXML:XML = e.target._data;
         
         for(var i:int=0; i< miXML.d.length() ; i++){
            name = miXML.d.@btn[i];
            if( mcContenedor.getChildByName( name ) != null )
            {
               tmpBTN = mcContenedor.getChildByName( name ) as SimpleButton; 
               tmpBTN.tabIndex = i; 
               tmpBTN.addEventListener(MouseEvent.CLICK, sayName); 
            } 
         }
      }


Ahora creamos nuestro método sayName y listo, tenemos nuestro FLA funcionando, aquí el código completo

Código :

package {

   import flash.events.*;
   import flash.display.*;
   import flash.ui.*;
   import cristalab.utils.*;

   public class Main extends MovieClip {

      private var t:LoaderXML;
      public function Main() {
         t = new LoaderXML();
         t.loadXML("data/data.xml");
         t.addEventListener(LoaderXML.ACTION, compare);
      }

      private function compare(e:Event):void{
         var tmpBTN:SimpleButton;
         var name:String;
         var miXML:XML = e.target._data;
         
         for(var i:int=0; i< miXML.d.length() ; i++){
            name = miXML.d.@btn[i];
            if( mcContenedor.getChildByName( name ) != null )
            {
               tmpBTN = mcContenedor.getChildByName( name ) as SimpleButton; 
               tmpBTN.tabIndex = i; 
               tmpBTN.addEventListener(MouseEvent.CLICK, sayName); 
            } 
         }
      }

      private function sayName(e:MouseEvent):void {
         trace(t._data.d.@url[e.target.tabIndex]);
      }
   }
}


Esto es simple, ahora imagina que si tienes que cambiar la url de algun btn, sólo lo harías en el XML ^^

Es más, ahora agrega 10, 20, 50 botones en el FLA, le pones nombre de instancia y todas las url en el XML :P solo editas ahi las url y listo, funciona ^^.

Pruébalo, esto salió como jugando y pensando en que uno aveces es flojo :P ya que con 36 líneas de código, puedes tener N cantidad de botones.

Aquí el ejemplo del tip





Ahora si no quieres usar tabIndex, podemos utilizar el código de Zguillez donde quedaría así:

Clase Main.as

Código :

package 
{
   import flash.display.MovieClip;
   import flash.display.SimpleButton;
   import flash.events.Event;
   import flash.events.MouseEvent;
   import cristalab.utils.LoaderXML;
   import cristalab.display.SimpleButtonURL;

   public class Main extends MovieClip
   {
      private var t:LoaderXML;

      public function Main()
      {
         t = new LoaderXML();
         t.loadXML("datos.xml");
         t.addEventListener(LoaderXML.ACTION, compare);
      }
      private function compare(e:Event):void
      {
         var total:uint = e.target._data.d.length();
         var i:uint;
         var name:String;
         var url:String;
         for (i=0; i<total; i++)
         {
            name = e.target._data.d.@btn[i];
            url = e.target._data.d.@url[i];
            if (this.getChildByName(name) != null)
            {
               var boton:SimpleButtonURL;
               boton = new SimpleButtonURL(this.getChildByName(name) as SimpleButton);
               boton.url = url;
            }
         }
      }
   }
}

Clase SimpleButtonURL.as

Código :

package cristalab.display
{
   import flash.display.SimpleButton;
   import flash.events.Event;
   import flash.events.MouseEvent;
   import flash.net.URLRequest;
   import flash.net.navigateToURL;

   public class SimpleButtonURL
   {
      private var _url:URLRequest;

      public function SimpleButtonURL(boton:SimpleButton):void
      {
         boton.addEventListener(MouseEvent.CLICK, _navigateToURL);
      }
      public function set url(u:String):void
      {
         _url = new URLRequest(u);
      }
      private function _navigateToURL(e:Event):void
      {
         if (_url!=null)
         {
            navigateToURL(_url);
         }
      }
   }
}


:) listo, espero les sea útil.

¿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

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