Foros del Web » Programando para Internet » Javascript »

Manejador de evento como parte de una clase

Estas en el tema de Manejador de evento como parte de una clase en el foro de Javascript en Foros del Web. Hola! Esto es un poco rallada, pero con los expertos en JavaScript que hay por aquí seguro que quedamos todos más contentos. Estoy haciendo una ...
  #1 (permalink)  
Antiguo 08/09/2010, 17:45
isra00
Invitado
 
Mensajes: n/a
Puntos:
Pregunta Manejador de evento como parte de una clase

Hola! Esto es un poco rallada, pero con los expertos en JavaScript que hay por aquí seguro que quedamos todos más contentos.

Estoy haciendo una aplicación con controles autocompletados y cosas así... llamémosle "widget". Un widget es un control de formulario (input text, botón...) sobre el que opero con JavaScript para darle al usuario una funcionalidad más rica.

Me gustaría tener la funcionalidad de cada widget encapsulada en una clase u objeto. Básicamente esta información es el id del objeto y algunas funciones. Por ejemplo, imaginemos un "widget" para seleccionar localidad a través de un option select. Al principio, el select muestra una lista de países. Cuando seleccionas un país, entonces aparecen en ese mismo select todas las ciudades de ese país (en realidad es un poco más complejo, pero dejémoslo así de momento).

Por ejemplo (estoy usando jQuery):

Código:
function WidgetSeleccionarLocalidad(id) {
    this.widget = $("#" + id);
    widget.addClass("widgetizado");

    this.modoSeleccionPais = function () {
        //Carga los países por AJAX y los mete en el select
        this.widget.operacionesParaMeterOpciones();
    }

    this.modoSeleccionLocalidad = function() {
        //Carga por AJAX las localidades del país seleccionado y los mete en el select
        this.widget.operacionesParaMeterOpciones();
    }
}
Bien, se supone que con esto puedo tener varios widgets a la vez, creando diferentes instancias de la clase WidgetSeleccionarLocalidad().

Algunas de estas funciones se asociarán a los manejadores de eventos de los controles. Y aquí está el problema: no puedo poner el siguiente código dentro de modoSeleccionPais():

Código:
this.widget.bind("click", this.modoSeleccionLocalidad);
¿Por qué no puedo hacer esto? Porque al pasar por valor el método this.modoSeleccionLocalidad no le estoy pasando la "copia" del método correspondiente a la clase instanciada, sino una función "aislada" del resto de la clase, que no podrá acceder a this.widget, ni a otros atributos que pusiera, ni a otros métodos de la clase.

Llegados a este punto, ¿se os ocurren soluciones? A mí solo se me ocurre dejar las clases y utilizar funciones "planas", aunque no me parece tan elegante como la forma orientada a objetos porque habría que pasar a cada función el widget en concreto, para poder trabajar con él.

Espero haberme explicado, estoy ansioso por leer vuestras ideas al respecto. ¡Gracias!
  #2 (permalink)  
Antiguo 09/09/2010, 03:46
 
Fecha de Ingreso: septiembre-2010
Ubicación: Malaga
Mensajes: 47
Antigüedad: 9 años, 3 meses
Puntos: 1
Respuesta: Manejador de evento como parte de una clase

Hola

Yo he planteado un problema parecido en el hilo
Crear link a metodo del mismo objeto
[URL="http://http://www.forosdelweb.com/f13/crear-link-metodo-del-mismo-objeto-840310/"]http://http://www.forosdelweb.com/f13/crear-link-metodo-del-mismo-objeto-840310/[/URL]

De las posibles opciones que creia posible, lo he solucionado de momento, pasandole al objeto el nombre de la instancia, algo chapucero, pero hasta que vea si son posibles las otras soluciones o alguna otra, al menos me sirve.
Es decir, he sustituido la llamada a
this.miMetodo()
por
this.nombreInstancia+".miMetodo()"

Este link tambien te puede servir
[URL="http://jibbering.com/faq/notes/closures/#clObjI"]Associating Functions with Object Instance Methods[/URL]

Espero que esto te ayude algo

Saludos
  #3 (permalink)  
Antiguo 09/09/2010, 06:34
 
Fecha de Ingreso: septiembre-2010
Mensajes: 2
Antigüedad: 9 años, 2 meses
Puntos: 0
Respuesta: Manejador de evento como parte de una clase

No sé si te he entendido bien, pero intentaré darte mi punto de vista.

Creo que intentas crear controles propios, como podría ser por ejemplo un calendario o un desplegable que se autocompleta o modifica al producirse eventos sobre el mismo.

Lo más simple a mi entender es que encapsules objetos y eventos dentro de una instancia propia, en vez de intentar dar un significado a un objeto:

Código:
var calendario=new Calendar();
lugarDeCalendario.appendChild(calendario);
Donde calendar tiene dentro el código de eventos que pueden producir asociado a el contenido html que pueda tener.

Siguiendo con el ejemplo del calendar, y suponiendo que lo hacemos con una tabla, el propio objeto calendar genera un div cuyo contenido para el dia 13 puede ser estilo:
Código:
<td id="d13" onclick="alter(\"dia 13\");">13<td>
Con esto tienes un componente cerrado con su comportamiento, como lo haría extJS.

Lo único que te queda ahora es que el comportamiento sea modificable, para lo que yo utilizaría elprincipio de simplicidad: Javascript es tipado débil y en cualquier momento puedes redefinir cualquier cosa (pública), asi que si quieres que el día 13 tenga otra alerta, podrias hacer un:
Código:
calendario.getElementById("d13").onclick= function(){...
Hay que tener en cuenta que los id son globales, asi que puede utilizarse otro mecanismo, o generar los ids para el contenedor: id="calendario1_d13"

Si quieres un comportamiento común a los objetos, no solo modificar dicha instancia, deberías tocar el prototype de la clase Calendar.

Si no me he explicado, o no he entendido que es lo que pretendes, o estoy hablando tonterías... o si todo esto es una patada a los estándares y demás, cosa en lo que eres más experto que yo, espero que lluevan las críticas, porque solo así aprenderé. :P


PD: Sobre el tema del this (una vez hayas decidido como quieres hacer tu widget, si a "mi estilo" o al tuyo), el problema es simple si manejas variables públicas, privadas, etc...si no me equivoco demasiado (corríjanme los expertos), creo que va asi:

Código:
	function Demo()
	{
		var privateProperty=0;					//read-write from privileged
		var privateMethod=function(){};			//read-write from privileged
		this.privilegedProperty=1;
		this.privilegedMethod=function(){};
	}
	Demo.staticProperty=2;						//only 1 instance
	Demo.staticMethod=function(){};				//only 1 instance
	Demo.prototype.publicProperty=3;			//read-write class-level
	Demo.prototype.publicMethod=function(){};	//read-write class-level

Última edición por murciano; 09/09/2010 a las 06:48
  #4 (permalink)  
Antiguo 09/09/2010, 14:11
isra00
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: Manejador de evento como parte de una clase

Gracias Oasis8! Creo que haré lo que propones, tener controladas las instancias y especificarlas en el handler.

@murciano El problema está en que al "bindear" una función a un evento esta función se copia ya que se pasa por valor, y la función "bindeada" está aislada del resto de la clase.
  #5 (permalink)  
Antiguo 10/09/2010, 06:23
 
Fecha de Ingreso: septiembre-2010
Mensajes: 2
Antigüedad: 9 años, 2 meses
Puntos: 0
Respuesta: Manejador de evento como parte de una clase

Cita:
Iniciado por isra00 Ver Mensaje
@murciano El problema está en que al "bindear" una función a un evento esta función se copia ya que se pasa por valor, y la función "bindeada" está aislada del resto de la clase.
Por eso digo, en ese caso llama a una funcion de la clase...algo como:

Código:
this.widget.bind("click", Widget.funcion.call(this.widget,[args]));
  #6 (permalink)  
Antiguo 10/09/2010, 10:38
isra00
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: Manejador de evento como parte de una clase

@murciano Si has probado eso, verás que cuando el método es lanzado, por alguna "extraña razón" this es undefined. La extraña razón es que, al bindear el evento, en lugar de enlazar el evento con el método se crea una copia del método (función) aislada del resto de la clase. Así es como funciona JavaScript

Etiquetas: clases, objetos, poo
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 14:34.