Comunidad de diseño web y desarrollo en internet online

problema con funciones anidadas en una clase as

Citar            
MensajeEscrito el 09 Ene 2011 06:39 am
Hola a todos eh es la primera vez que participo en esta pagina que me parece buenaza!!!
bien comencemos , lo que pasa es que tengo un problema con unas funciones dentro de una clase la
pregunta es :
Como harias para retornar el valor de una funcion supuestamente anidada , por ejemplo , en mi caso tengo un problema de respuesta de una funcion.
este es mi codigo :

Código Javascript :

//----------------------xim-O_o---------------------------------- 
//--------domingo enero 09 del 2011 
import mx.utils.Delegate; 
class conexion{ 
public var msn; 
public var respuesta; 
public var xmlX:XML; 
public var xmlL; 
//--------------------------- 
public var archivo; 
public var indice; 
public var valor; 
public var metodo; 
public var atributos; 
//--------------------------- 
//public static var conex:conexion; 
//--------------------------- 
public function conexion(archivo2,indice2,valor2,metodo2,atributos2){ 
msn = new Array(); 
mensaje(); 
respuesta = new Array(); 
//-----------PARAMETROS---------- 
indice = new Array(); 
valor = new Array(); 
atributos = new Array(); 
///----ASIGNANDO--- 
archivo = archivo2; 
indice = indice2; 
valor = valor2; 
atributos = atributos2; 
if(metodo2 = 1){metodo = "post";}else{metodo = "get";} 
//------------------------------------------- 
xmlX = new XML(); 
xmlX.ignoreWhite = true; 
xmlL = new LoadVars(); 
if(indice.length > 0){ 
for(var i=0;i<indice.length;i++){ 
xmlL.indice[i]= valor[i]; 
} 
} 
//------------------------------------------- 
xmlL.sendAndLoad(archivo,xmlX,metodo); 
xmlX.onLoad= Delegate.create(this, parse);//Es como si estaria llamandose dentro y no devuelve nada 
//newLoad.load("mensajes.php"); 
//------------------------------------------- 

}//fin constructor 

public function mensaje(){ 
msn[0] = "Error al conectar"; 
msn[1] = "Error al tratar de hacer la consulta"; 
msn[2] = "Problemas al tratar de cargar el XML"; 
}//fin mensaje 

public function parse(success:Boolean){ 
if(success){ 
respuesta = respuestaXML();//aqui se pierden los datos cuando le asigno a "respuesta" que es una variable del Scope 
}else{ 
trace(msn[2]); 
} 
//trace(respuesta); 
}//fin parse 

public function respuestaXML(){ 
//------------------------------ 
var respuesta2 = new Array(); 
var code = xmlX.firstChild.childNodes; 
for(var forx=0;forx<code.length;forx++){ 
respuesta2[forx] = new Array(); 
for(var j=0;j<atributos.length;j++){ 
respuesta2[forx][j] = code[forx].attributes[atributos[j]]; 
//trace(respuesta2[forx][j]);//aqui todo esta bien y retorna datos 
} 
} 
return respuesta2; 
}//fin respuestaXML 

public function getResp(){ 
trace(respuesta);//la prueba pasa sin exito 
return respuesta;//NO RETORNA LOS DATOS 
}//fin getResp 
}//fin class 


y asi es como lo llamo :


Código Javascript :

import conexion; 

var xxI = new Array();//las variables en este caso no mando nada 
var xxV = new Array();//valores de envio en este caso no mando nada 
var aaT = new Array();//nodos para el XML 
var resp = new Array(); // aqui capturare la respuesta 

aaT[0]= "nombre"; 
aaT[1]= "descripcion"; 

conec = new conexion("xim.xml",xxI,xxV,0,aaT); 
resp = conec.getResp();// No retorna nada sin existo 


Donde mi XML es :

Código XML :

<?xml version='1.0'?> 
<palaueb> 
<datos nombre="Xim" descripcion="Ok" /> 
<datos nombre="1" descripcion="uno" /> 
<datos nombre="2" descripcion="dos" /> 
<datos nombre="3" descripcion="tres" /> 
<datos nombre="4" descripcion="cuatro" /> 
<datos nombre="5" descripcion="cinco" /> 
<datos nombre="6" descripcion="seis" /> 
<datos nombre="7" descripcion="siete" /> 
</palaueb> 


luego lo generare con php para que sea mas dinamico pero el caso es que mi
clase no me devuelve los datos por el ambito donde se encuentra la funcion alparecer.

si alguien me pudiera ayudar le estaria agradecido .

gracias eso es todo .

Por CLAnonimo

Claber

600 de clabLevel

5 tutoriales
1 articulo

 

Este es un usuario anónimo genérico para las cuentas borradas o perdidas.

opera
Citar            
MensajeEscrito el 10 Ene 2011 04:16 pm
Estás ejecutando sincrónicamente código que es asincrónico. En realidad deberías instanciar tu clase y agregar un listener al evento onLoad, luego tu clase despacha el evento cuando termina de cargar

Jorge

Por solisarg

BOFH

13669 de clabLevel

4 tutoriales
5 articulos

Genero:Masculino   Bastard Operators From Hell Premio_Secretos

Argentina

firefox
Citar            
MensajeEscrito el 11 Ene 2011 03:43 am

solisarg escribió:

Estás ejecutando sincrónicamente código que es asincrónico. En realidad deberías instanciar tu clase y agregar un listener al evento onLoad, luego tu clase despacha el evento cuando termina de cargar

Jorge



Hola Jorge gracias por Tu respuesta ehh!! ...
Esto No se si pudieras darme un pequeño ejemplo para poderme
orientar con ese listener ya que eh tratado varas formas y no lo eh logrado. :zzz:

la forma sincrónicamente y asincrónico que me indicas me imagino que se da como un ajax
la comunicacion , bueno almenos siempre lo eh visto asi desde que programo en flash.

Por CLAnonimo

Claber

600 de clabLevel

5 tutoriales
1 articulo

 

Este es un usuario anónimo genérico para las cuentas borradas o perdidas.

firefox
Citar            
MensajeEscrito el 11 Ene 2011 11:20 am
Seria

Código ActionScript :

conec.addEventListener("complete", getDatos)
function getDatos(evt:Event){
  conec.getResp();
}


En tu clase

Código ActionScript :

import mx.events.EventDispatcher;

(...)
public function conexion(archivo2,indice2,valor2,metodo2,atributos2){  
EventDispatcher.initialize(this)
(....)
public function respuestaXML(){  
(...)
this.dispatchEvent({type:"complete", target: this});
}//fin respuestaXML 


Tengo bastante olvidada la sintaxis de AS2, pero era algo así, pruébalo

Jorge

Por solisarg

BOFH

13669 de clabLevel

4 tutoriales
5 articulos

Genero:Masculino   Bastard Operators From Hell Premio_Secretos

Argentina

firefox
Citar            
MensajeEscrito el 16 Ene 2011 07:52 am

solisarg escribió:

Seria

Código ActionScript :

conec.addEventListener("complete", getDatos)
function getDatos(evt:Event){
  conec.getResp();
}


En tu clase

Código ActionScript :

import mx.events.EventDispatcher;

(...)
public function conexion(archivo2,indice2,valor2,metodo2,atributos2){  
EventDispatcher.initialize(this)
(....)
public function respuestaXML(){  
(...)
this.dispatchEvent({type:"complete", target: this});
}//fin respuestaXML 


Tengo bastante olvidada la sintaxis de AS2, pero era algo así, pruébalo

Jorge



Muchas Gracias por tu Ayuda y si alparecer ya debo migrar a la 3 pero eh llevado siempre la 2 espero que al pasar a la 3 no se me complique todo jajaja xD.

Por CLAnonimo

Claber

600 de clabLevel

5 tutoriales
1 articulo

 

Este es un usuario anónimo genérico para las cuentas borradas o perdidas.

firefox
Citar            
MensajeEscrito el 16 Ene 2011 07:54 am
Bien Volviendo al TEMA. Gracias eh estado leendo soble esa clase :" EventDispatcher" y es muy interesante ...

CLARO ENCONTRAMOS LA SOLUCION xP ! y bien les Dire Todo lo que me pase CHECANDO:

Primero Busque y Busque y me tope con miles de cosas que no tenian resultado:

la primera solucion que me dieron fue la de poner una variable stactic y ponerla en el constructor y asignale su scope y otra hacer uso de otra clase "Delegate": que es una mejora a lo de la instancia seria algo asi :

Código ActionScript :

import mx.utils.Delegate;//usando la clase Delegate
class conexion{
   public static var ins; 
   public function conexion(param){
        ins = this; // asignando el scope para llamar a las funciones. ya no seria necesario porque tenemos la clase "Delegate"
        xmlX = new XML();
   xmlX.ignoreWhite = true;
   xmlL = new LoadVars();
      if(indice.length > 0){
         for(var i=0;i<indice.length;i++){
            xmlL.indice[i]= valor[i];
         }
      }
   //-------------------------------------------
   xmlL.sendAndLoad(archivo,xmlX,metodo);
   xmlX.onLoad= Delegate.create(this, parse);//usando la clase que porcierto si deriamos parametros a la funcion que queremos llamar seria Delegate.create(this, parse,parametro) xP
   }

  public function parse(success:Boolean){//funcion que llama la clase Delegate
   if(success){
      //ins.respuesta = Delegate.create(this, respuestaXML());//no sirvio pero es util fuera de la funcion anidada
               this.respuesta =  Delegate.create(this, respuestaXML());//No sirvio porque tampoco se le asino a la variable de la clase que es respuesta y es publica. Enconces donde esta el problema porque nada de esto Funciona!!!! :(
   }
}//fin parse

public function respuestaXML(){
      //------------------------------
      //this.dispatchEvent({type:"complete", target: this}); 
      var respuesta2 = new Array();
      var code = xmlX.firstChild.childNodes;
         for(var forx=0;forx<code.length;forx++){
            respuesta2[forx] = new Array();
            for(var j=0;j<atributos.length;j++){
               respuesta2[forx][j] = code[forx].attributes[atributos[j]];
               //trace(respuesta2[forx][j]);
            }
         }
         return  respuesta2;
      }//fin respuestaXML
      
public function getResp(){
   trace(ins.respuesta);
   return    ins.respuesta;//NO RETORNA LOS DATOS
}//fin getResp
}


Pues BIEN estuve a punto de rendirme cuando me dijeron que use la clase " EventDispatcher" y bien denuevo a investigar ok y esto es lo que encontre :

----------------------------------------------------------------------------------------------------------------------------------
Una de las partes más importantes y que más confusión y problemas ha generado de AS2 es la comunicación entre clases. Foros y listas de correo están llenos de problemas y dudas sobre "ámbitos", "eventdispatchers" y "delegates".

Como regla general yo diría:

* Si necesitas comunicación dentro de la misma clase, siempre Delegate.
* Si necesitas que más de una clase escuche lo que hace otra, siempre EventDispatcher.
* Si la comunicación es 1:1, depende.
Vamos a ver el funcionamiento de los 2 métodos.
------------------------------------------------------------------------------------------------------------------------
"Delegate"
------------------------------------------------------------------------------------------------------------------------
NOTA: Lo que voy a contar aquí es prácticamente un copy&paste de un tuto que publiqué hace tiempo y que está enlazado al final. Si lo leíste en su día, te puedes saltar lo que sigue sin problemas.

Los foros de Flash están llenos de preguntas que tienen que ver con el "scope" o ámbito dentro de los famosos "callbacks" de objetos como XML, LoadVars, XMLSocket, etc. Flash necesita estas funciones porque las llamadas al servidor en Flash son asíncronas, es decir, el player no detiene la ejecución del código cuando se hace, por ejemplo, una petición de un fichero xml:

Código ActionScript :

class A{
    private var oneVar:String="Helloworld";
    functionA(){
        var myXML:XML = newXML();
        myXML.ignoreWhite = true;
        myXML.onLoad=function():Void{
            trace(oneVar); //undefined ¬¬
        }
    myXML.load("myXML.xml");
    }
}


Esto pasa porque el ámbito "dentro" del onLoad es el propio objeto myXML, NO la clase. Puedes hacer la prueba haciendo trace(this) dentro del onLoad. Una de las primeras soluciones que se utilizó para esto fue crear dentro de la función principal una

variable que hacía referencia a la propia clase. Algo como esto:


Código ActionScript :

class A{
    private var oneVar:String="Helloworld";
    functionA(){
        var owner=this;
        var myXML:XML = newXML();
        myXML.ignoreWhite = true;
        myXML.onLoad = function():Void{
            trace(owner.oneVar); //yeah!
        }
        myXML.load("myXML.xml");
    }
}


Y esto funciona. Este comportamiento "peculiar" de Flash (de los ECMAScript, vamos) se llama closure.

ámbito en las llamadas asíncronas. Pues a todo esto llegó la versión 7.2 del Flash IDE y el señor Mike Chambers introdujo la clase Delegate. Utilizando esa clase dejaríamos el código anterior en algo como esto:

Código ActionScript :

importmx.utils.Delegate;
class A{
    private var oneVar:String = "Hello world 2";
    function A(){
        var myXML:XML = new XML();
        myXML.ignoreWhite = true;
        myXML.onLoad = Delegate.create(this,xmlLoaded);
            myXML.load("myXML.xml");
        }
    private function xmlLoaded(success:Boolean):Void{
        trace(oneVar);
    }
}


Estamos "delegando" el onLoad en la función xmlLoaded, pero, lo más importante, el ámbito de la función xmlLoaded es la clase original, por lo que "encontramos" la variable sin problemas.

Esto definitivamente NO es lo mismo que hacer: myXML.onLoad = xmlLoaded. Si lo probáis, estaréis con el mismo problema que antes, el ámbito de la función xmlLoaded será el objeto myXML, por lo que el trace volverá a ser undefined.

El mayor problema de la clase de Macromedia (aún era Macromedia) es que NO permite el paso de parámetros a la función delegada, pero pronto llegaron los frikis para solucionarlo haciendo sus propias clases para delegar. La que yo utilizo es una copia con alguna modificación de una que encontré en la lista de MTASC. Con estas nuevas clases se pueden pasar parámetros de la siguiente forma:

Código ActionScript :

myXML.onLoad=Delegate.create(this,xmlLoaded,"val1",val2);


OJO, nuestros parámetros llegarán después de los "oficiales", en este caso el típico success que llega a los onLoad del objeto XML.
------------------------------------------------------------------------------------------------------------------------------------------------
"EvenDispatcher"
------------------------------------------------------------------------------------------------------------------------------------------------
La misión básica de EvenDispatcher es permitir que varios objetos estén "escuchando" los eventos que lanza otro. EvenDispatcher siempre trata de comunicación entre clases, ya sea 1:1 (un emisor y un receptor) o 1:n (un emisor y varios receptores).

Técnicamente es una implementación del patrón Observer (ver enlaces al final) y fue introducida en su día por Macromedia. Pero como casi siempre apareció una versión libre, GDispatcher, en esta ocasión a cargo de Grant Skinner (gskinner.com).

Las clases que emiten eventos con EvenDispatcher son completamente independientes de quien esté escuchando, nunca saben si los escuchan 1 o 10, ellos sólo se limitan a emitir. Son como una radio o televisión con audiencia.

Sólo el objeto emisor necesita importar GDispatcher. Algo como lo siguiente:

Código ActionScript :

importcom.gskinner.GDispatcher;
class broadcaster{
    public var addEventListener:Function;
    public var removeEventListener:Function;
    private var dispatchEvent:Function;
    public function broadcaster(){
        GDispatcher.initialize(this);
        send();
    }
    private function send():Void{
        var ev:Object = new Object();
        ev.type = "myEvent";
        ev.variable = "wadus";
        dispatchEvent(ev);
    }
}


import  broadcaster;
class receiver{
    public function receiver(){
        varbr:broadcaster = newbroadcaster();
        br.addEventListener("myEvent",this,"callback");
    }
    private function callback(ev:Object):Void{
        trace(ev.type+""+
        ev.variable);
    }
}


Lo primero que llama la atención es que hayamos definido en la clase emisora unas variables del tipo Function. Si alguien se molesta en abrir GDispatcher puede ver que lo que hace en el método initialize es crear en tiempo de ejecución funciones a la clase que se le pasa como parámetro. Así que tenemos que definir esas mismas funciones como propiedades de nuestra clase para que el compilador no se queje de que el método al que el receptor trata de acceder (addEventListener) no existe.

La clase receptora es bastante simple. Simplemente importa a la emisora y se añade como listener para un evento concreto. Para hacerlo utiliza el método addEventListener pasando como parámetros el evento que quiere escuchar, el objeto que está escuchando (la propia clase (this) en este caso, pero se puede hacer que escuche otra) y la función que va a recibir la llamada. OJO que la función está pasada como cadena.

La implementación que hemos visto es perfectamente válida y funcional pero se puede mejorar. El primer problema es que el literal del nombre del evento ("myEvent") lo estamos repitiendo dos veces, una en el emisor y otra en el receptor. Malo. Otra es que el tipo del parámetro que llega a la función receptora es del tipo genérico Object, lo que no nos permite ninguna validación de tipos al compilar. Malo también. Bueno, pues las 2 cosas las vamos a solucionar en la misma jugada. Vamos a crear un objeto específico para el evento y será ese objeto "conocido" el que se envíe.

Código ActionScript :

class myEvent{
    public static var EVENT_LITERAL:String = "eventOne";
    public var type:String = "";
    public var variable:Number;
    public function myEvent(_variable:Number){
        type = EVENT_LITERAL;
        variable = _variable;
    }
}


Código ActionScript :

importcom.gskinner.GDispatcher;
import myEvent;
class broadcaster{
    public var addEventListener:Function;
    public var removeEventListener:Function;
    private var dispatchEvent:Function;
    public function broadcaster(){
        GDispatcher.initialize(this);
        send();
    }
    private function send():Void{
        var ev:myEvent = new myEvent(5);
        dispatchEvent(ev);
    }
}

Código ActionScript :

import  broadcaster;
import myEvent;
class receiver{
    public function receiver(){
        var br:broadcaster = new broadcaster();
        br.addEventListener(preventivamente_LITERAL,this, "callback");
    }
    private function callback(ev:myEvent):Void{
        trace(ev.type + " "
        + ev.variable);
    }
}


Mucho mejor. El literal con el nombre del evento sólo se define una vez en la clase myEvent. Se define como variable estática para que la clase receptora pueda utilizarlo sin tener que crear una instancia. La propiedad type se define para ser compatibles con EventDispatcher y GDispatcher.

Además con la nueva implementación el tipo del evento que llega al receptor es myEvent y no Object, por lo que tendremos validación de tipos al compilar.

Si sustituyes myEvent, por videoStarted, applicationReady, menuButtonPressed y similares, es cuando se empieza a ver la utilidad de EvenDispatcher (vamos, de un patrón Observer).


-----------------------------------------------------------------------------------------------
EvenDispatcher ¿vs? Delegate
-----------------------------------------------------------------------------------------------

Una vez vistos EventDispatcher y Delegate, ¿hay situaciones en las que se pueda elegir entre usar una opción o la otra? Ya hemos visto que la comunicación dentro de la misma clase siempre es con Delegate, así la decisión viene cuando hay que comunicar 2 clases. Vamos a ver cómo.


Código ActionScript :

importBroadcaster;
importtv.zarate.utils.Delegate;
class Receiver{
    public function Receiver(){
        var buttonCallback:Function = Delegate.create(this, buttonPressed);
        var broadcaster:Broadcaster = newBroadcaster(buttonCallback);
    }
    private function buttonPressed():Void{
        //este método se ejecuta cuando se presione el botón
        //en la clase emisora
    }
}


Código ActionScript :

class Broadcaster{
    public function Broadcaster(buttonPressedCallback:Function){
        var button:MovieClip = base_mc.createEmptyMovieClip("button", 100);
        button.onPress = buttonPressedCallback;
    }
}


Atención a la jugada. La clase receptora crea una función delegada y la pasa como parámetro a la emisora que simplemente se lo asigna al evento onPress de su botón. Así que cuando el botón es presionado, la clase emisora recibe sin problemas el evento.

Ahora, ¿qué hacemos si hay que pasar parámetros en la llamada? Esto es algo que NO podríamos hacer:

Código ActionScript :

button.onPress = buttonPressedCallback("parametro");


Ya que al añadir "()" estaríamos ejecutando la función. Si necesitamos pasar parámetros con este método, habría que pasar por una función intermedia. Repito sólo la clase emisora:

Código ActionScript :

importtv.zarate.utils.Delegate;
class Broadcaster{
    public function Broadcaster(externalCallback:Function){
        var button:MovieClip = base_mc.createEmptyMovieClip("button", 100);
        button.onPress = Delegate.create(this, butPressed, externalCallback);
    }
    private function butPressed(externalCallback:Function):Void{
        externalCallback("parametro");
    }
}

Al utilizar la clase emisora internamente una función para recibir el evento onPress del botón, ya puede pasar los parámetros que quiera al callback externo.

LUEGO DE ESO ENCONTRE UNA CLASE MEJORADA DE "EvenDispatcher" QUE ESTA EN ESTA MISMA PAGINA AQUI EL LINK:
[url=http://www.cristalab.com/tips/clase-que-mejora-el-eventdispatcher-de-actionscript-2-c52269l/][/url]

A TODO ESTO AHORA MI CODIGO SE VE ASI CON LA CLASE DEL ENLACE:

Código ActionScript :

/*********CLASS CONEXION XML CREADO POR XIM*******/
//import mx.events.EventDispatcher; 
import com.npi.events.EventDispatcher;
import mx.utils.Delegate;
class conexion{
   public var msn;
   public var respuesta;
   public var xmlX:XML;
   public var xmlL;
   //---------------------------
   public var archivo;
   public var indice;
   public var valor;
   public var metodo;
   public var atributos;
   //---------------------------
   public static var ins;//
   //---------------------------
public function conexion(archivo2,indice2,valor2,metodo2,atributos2){
      EventDispatcher.initialize(this);
      ins = this;msn = new Array();respuesta = new Array();indice = new Array();valor = new Array();atributos = new Array();
      mensaje();
      ///----ASIGNANDO---
      archivo = archivo2;indice = indice2;valor = valor2;atributos = atributos2;
      if(metodo2 = 1){metodo = "post";}else{metodo = "get";}
      //-------------------------------------------
      xmlX = new XML();
      xmlX.ignoreWhite = true;
      xmlL = new LoadVars();
      if(indice.length > 0){
         for(var i=0;i<indice.length;i++){
            xmlL.indice[i]= valor[i];
         }
      }
      //-------------------------------------------
      xmlL.sendAndLoad(archivo,xmlX,metodo);
      xmlX.onLoad= Delegate.create(this, parse);
      //newLoad.load("mensajes.php");
      //-------------------------------------------
      
}//fin constructor
   
public function mensaje(){
      msn[0] = "Error al conectar";
      msn[1] = "Error al tratar de hacer la consulta";
      msn[2] = "Problemas al tratar de cargar el XML";
}//fin mensaje
   
public function parse(success:Boolean){
   if(success){
      Delegate.create(this, respuestaXML());
   }else{
      trace(msn[2]);
   }
}//fin parse

public function respuestaXML(){
      //------------------------------
      //this.dispatchEvent({type:"complete", target: this}); //NO FUNCIONA EL THIS
      var respuesta2 = new Array();
      var code = xmlX.firstChild.childNodes;
         for(var forx=0;forx<code.length;forx++){
            respuesta2[forx] = new Array();
            for(var j=0;j<atributos.length;j++){
               respuesta2[forx][j] = code[forx].attributes[atributos[j]];
               //trace(respuesta2[forx][j]);
            }
         }
         ins.respuesta = respuesta2;//ASIGNADO
         ins.dispatchEvent({type:"complete", target:this}, true);//TUVE QUE COLOCAR LA INSTANCIA "INS" ES UTIL
      }//fin respuestaXML
      
public function getResp(){
   trace(ins.respuesta);//COMPRUEBO
   return    ins.respuesta;//AHORA SI RETORNA LOS DATOS
}//fin getResp
}//fin class


Y LO LLAMO DE ESTA FORMA :

Código ActionScript :

import conexion;
var xxI = new Array();
var xxV = new Array();
var aaT = new Array();
var resp = new Array();
aaT[0]= "nombre";
aaT[1]= "descripcion";
conec = new conexion("descripcion2.xml",xxI,xxV,0,aaT);//INSTANCIO PARA QUE ESCUCHE EL addEventListener
conec.addEventListener("complete", getDatos,true) //ESCUCHA SE SE COMPLETO Y LLAMA A LA FUNCION getDatos
function getDatos(){ 
  conec.getResp(); //AHORA SI RETORNA
}


BIEN ACABE ESO SERIA TODO SI AYUDE EN ALGO ESPERO QUE SI :lol: SALUDOS DESDE LIMA - PERU GRACIAS!!!

Por CLAnonimo

Claber

600 de clabLevel

5 tutoriales
1 articulo

 

Este es un usuario anónimo genérico para las cuentas borradas o perdidas.

firefox

 

Cristalab BabyBlue v4 + V4 © 2011 Cristalab
Powered by ClabEngines v4, HTML5, love and ponies.