Entradas etiquetadas ‘ javascript ’

Evitar el uso de eval() en Javascript

Jueves, Noviembre 6, 2008

Hoy en el trabajo he descubierto que la función eval() de Javascript y Firebug se llevan muy mal. Tan mal que no conseguía depurar una clase que estoy desarrollando. Googleando un poco he conseguido encontrar varias formas de evitar eval() y algunos motivos por lo que es recomendable evitar su uso.

El funcionamiento de eval() es el siguiente:

  1. Se convierte el argumento en un String.
  2. Se parsea el String y se convierte en código Javascript.
  3. Se ejecuta el código Javascript resultante.

Evidentemente saltarse los pasos 1 y 2 mejora el rendimiento. Además evita esos problemas “raros” que he comentado antes con Firebug.

En concreto los problemas con los que me he encontrado incluían los siguientes usos de eval:

  • Asignar una propiedad a un objeto cuyo nombre está almacenado en un String.
  • Llamar a una función cuyo nombre está almacenado en un String.
  • Crear un objeto de una clase cuyo nombre está almacenado en un String.

Es decir, tres casos muy parecidos que se reducen a uno solo, acceder a variables cuyo nombre conocemos a posteriori. Para solucionar esto basta con saber que hay varias formas de acceder a una propiedad de un objeto en Javascript. La típica:

  1. objeto.atributo = valor

y la no tan típica:

  1. var nombreDelAtributo="atributo";
  2. objeto[nombreDelAtributo] = valor;

Ahora solo falta saber otra cosa. Cualquier variable se puede acceder también como un atributo del objeto window, un ejemplo:

  1. var cadena = "Hola mundo!";
  2. alert(window.cadena); //mostrará un alert con "Hola mundo!"
  3. alert(window[‘cadena’]); //también mostrara un alert con "Hola mundo!"

Ahora veamos algunos ejemplos de usos de eval() y otras formas de avordar el mismo problema.

  1. /*
  2. *asignar un valor a un atributo cuyo nombre no conocemos a priori
  3. */
  4. eval(‘objecto.’ + nombreDelAtributo + ‘=valorDelAtributo’);
  5. //se podría cambiar por
  6. objeto[nombreDelAtributo] = valorDelAtributo;
  7.  
  8. /*
  9. * Llamar a un metodo de un objeto estando el nombre del metodo almacenado en una variable
  10. */
  11.  
  12. eval(‘objeto.’ + nombreDelMetodo + ‘(argumento)’);
  13. //podría ser
  14. objeto[nombreDelMetodo](argumento);
  15.  
  16. /*
  17. * Crear un objeto de una clase teniendo el nombre de la clase en una variable
  18. */
  19.  
  20. eval(‘var objeto = new ‘ + nombreDeLaClase + ‘()’);
  21. //sería
  22. var objeto = new window[nombreDeLaClase]();

En el último ejemplo podemos hacer esto por que una clase es también una variable del programa, y como tal se almacena como un atributo del objeto window.

Y vosotros, ¿usáis eval() en vuestro código? ¿conocíais estas soluciones?

Event.stop() en Prototype

Domingo, Octubre 19, 2008

Mi última pelea con Prototype ha estado protagonizada por los eventos. Tenía que conseguir capturar el evento de scroll sobre un div y después de hacer algunas cosas cancelar el comportamiento por defecto del evento y evitar la propagación al scroll general de la página.

Al final descubrí la función Event.stop() de Prototype. En la documentación dice lo siguiente:

Llamándola en un evento, para la propagación y previene el comportamiento por defecto.

Su uso es simple. Veamos un ejemplo.

  1. $(‘elemento’).observe(‘evento’, function(e){
  2.   otroComportamiento();
  3.   //esto detiene el comportamiento por defecto y evita la propagacion
  4.   e.stop();
  5. });

Aquí tenéis una página con un par de ejemplos. Podéis ver el ejemplo viendo el código fuente de la página.

  • El primer formulario mostrará un alert() con el valor
  • El segundo formulario hará una petición GET (evidentemente sin ningún efecto) sobre la misma página
  • El primer párrafo con scroll ignora el uso de la rueda del ratón
  • El segundo párrafo funciona igual que siempre :)

bind() y bindAsEventListener() en Prototype, como utilizarlos

Lunes, Octubre 13, 2008

Desde que empecé a trabajar mi función principal es la de desarrollador web. Básicamente me peleo todo el día con Prototype y con AJAX. Después de unas cuantas semana Prototype se ha convertido en parte en un gran aliado, pero también en un enemigo a batir. Conocer el framework con profundidad es esencial para trabajar con él y a veces no es fácil. Una de las cosas que mas trabajo me costó entender fue la utilidad de las funciones bind() y bindAsEventListener(). Ambas son muy potentes y muy útiles cuando se utilizan bien, pero comprender su uso puede ser difícil y a veces nos pueden dar quebraderos de cabeza.

Voy a intentar explicar de forma clara y simple como se usan estas dos funciones y para qué sirven. Vayamos por partes.

  1. bind(): Es una de las estrellas en Prototype y también es una de las más trabajo suele costar entender. Imaginemos un objeto que tiene métodos para acceder a sus datos miembro. Usando bind() podemos hacer que esos objetos accedan a datos miembro de otros objetos en lugar de a los del objeto original. Veamos un ejemplo:
    1.  
    2. var Clase1 = Class.create({
    3.   initialize: function(msg){
    4.     this.mensaje = msg;
    5.   },
    6.   log: function(){
    7.     console.log(this.mensaje);
    8.   }
    9. });
    10. var objeto1 = new Clase1("Mensaje, Objeto1");
    11. var objeto2 = new Clase1("Mensaje, Objeto2");
    12.  
    13. objeto1.log(); //Genera -> Mensaje, Objeto1
    14. objeto2.log(); //Genera -> Mensaje, Objeto2
    15. //Creamos el bind de alerta para que se ejecute en el
    16. //contexto del objeto2.
    17. var log_bind = objeto1.log.bind(objeto2);
    18. log_bind(); //Genera -> Mensaje, Objeto2

    Como vemos, la llamada a log_bind() realiza la llamada a objeto1.bind() usando el contexto del objeto2, lo cual en terminos prácticos equivale a hacer objeto2.bind()

    También podemos usar bind() para añadir argumentos a la llamada a una función. Veamos un ejemplo de esto.

    1. var Clase2 = Class.create({
    2.   initialize: function(msg){
    3.     this.mensaje = msg;
    4.   },
    5.   log: function(){
    6.     console.log(this.mensaje + ‘ ‘ + $A(arguments).join(‘, ‘));
    7.   }
    8. });
    9.  
    10. var objeto3 = new Clase2("Mensaje, Objeto3");
    11. objeto3.log();
    12. var log_bind_mas_argumentos = objeto3.log.bind(objeto3,1,2,3,4,‘ lo que sea’);
    13. log_bind_mas_argumentos();

    Esta vez no cambiamos el contexto de la función, pero añadimos varios argumentos extra que luego se extraen usando $A(arguments), convirtiéndolos así en un Array de Prototype.

  2. bindAsEventListener(): Una vez hemos comprendido el uso que tiene bind() es fácil entender la dinámica de bindAsEventListener(). Su funcionamiento es el mismo que el de la función bind() pero con adaptaciones específicas para un contexto concreto, el de la captura de eventos.Este es el mismo ejemplo que hay en el API de Prototype pero un poco retocado:
    1. var obj = {
    2.   name: ‘Un bonito ejemplo’
    3. };
    4.  
    5. function handler(evento){
    6.   var tag = Event.element(evento).tagName.toLowerCase();
    7.   var data = $A(arguments);
    8.   data.shift();
    9.   console.log(this.name + \nHas clickado en ‘ + tag + \nOtros argumentos: ‘ + data.join(‘, ‘));
    10. }
    11. $(‘elemento’).observe(‘click’, handler.bindAsEventListener(obj, 1, 2, 3));

    Por partes, el objeto obj tiene una propiedad name y la función handler(evento) se encarga de manejar el evento una vez se ha disparado. Esta función extrae el nombre del elemento de la página que ha disparado el evento, los argumentos extra pasados a la función y los muestra todos por la consola de facebook. La clave de todo el ejemplo es la línea:

    1. $(‘elemento’).observe(‘click’, handler.bindAsEventListener(obj, 1, 2, 3));

    Esta línea asigna la función handler(evento) como manejadora del evento onclick del elemento y además cambia su contexto al del objeto obj y le pasa 3 números como argumento. Pero echando un segundo vistazo a la función vemos que en ningún momento le pasamos el argumento evento. Esa es precisamente la función especial de bindAsEventListener() pasar como primer argumento el objeto de la clase Event que representa al evento que se ha disparado.

    Usando bindAsEventListener() siempre recibiremos el objeto Event como primer argumento, sin necesidad de pasar ese evento de forma manual.

Espero que después de este par de ejemplo quede todo un poco más claro, como siempre se aceptan preguntas, dudas y sugerencias :) y para todo el código que necesitéis pegar podéis usar Pastie

mooSmartForms: Dando un toque de estilo a tus formularios

Sábado, Noviembre 17, 2007

¿Por qué otra librería que hace lo mismo?

Hace poco tuve que terminar de darle forma a un proyecto con Joomla! una de las cosas que más trabajo cuesta es darle estilo a un formulario usando CSS. Probé un par de soluciones como FancyForm y CRIR pero ninguna se adaptaba al código generado por Joomla, así que no me quedó más remedio que escribir mi propio script que hiciera lo propio.

Como funciona.

mooSmartForms está inspirado en otras librerías como CRIR y FancyForm, por lo tanto usa el mismo mecanismo. Mediante Javascript oculta los controles del formulario y añade un estilo para el control desactivado y otro para el control activado a la etiqueta asociada al control.

La librería permite aplicar una clase CSS a los elementos. Hace uso de mootools, de ahí el “moo” del nombre. Para que nuestro código sea “estilizable” tiene que tener las siguientes características.

  • Cada checkbox o radio input necesita tener un elemento label asociado a su id.

Listo :D no hay más requisitos. A continuación un ejemplo de como sería ese código “estilizable”.

  1. <label for="check">Checkbox
  2. <input id="check" type="checkbox" />
  3. </label><label for="radio1">Radio1</label>
  4. <input id="radio1" name="sample" type="radio" />
  5. <label for="radio2">Radio2</label>
  6. <input id="radio2" name="sample" type="radio" />

Para que el script haga su trabajo hay que insertarlo en la página y además necesitamos mootools.

  1. <script src="mootools.js" type="text/javascript"><!–mce:0–></script>
  2. <script src="moosmartforms.js" type="text/javascript"><!–mce:1–></script>

Un pequeño ejemplo del aspecto que podemos conseguir con la librería. Ejemplo de mooSmartForms

Aquí tenéis mooSmartForms para descargarlo y usarlo como queráis. Tiene una licencia MIT, así que podéis hacerle todas las “perrerías” que os apetezca. Si queréis personalizar el estilo solo tenéis que editar el fichero mooSmartForms.css

Soporte.

He probado mooSmartForms con los siguiente navegadores:

  • Internet Explorer 6 y 7
  • Firefox 2
  • Konqueror
  • Safari 3 ( gracias a Álvaro por el testeo )
  • Opera

Si conseguís que funcione en otro navegador agradecería que me lo hicierais saber :D . Aunque también se agradece un aviso con cualquier error que encontréis o con problemas que se me hayan pasado.

Para futuras versiones.

  • Estilos para el resto de elementos de los formularios.
  • Posibilidad para discriminar los elementos que queremos “estilizar”.
  • Capacidad para añadir efectos a las transicciones entre los estados de los elementos.
  • Posibilidad de elegir el nombre que queremos darle a las clases CSS de los elementos.

Para terminar.

Si encontráis algún error o algún problema podéis dejar un comentario en el post. Sin necesitáis añadir código al post, por favor, utilizad esta web.

Créditos.

Las imágenes que se usan para el estilo de ejemplo pertenecen al tema de iconos silk icons que tiene licencia Creative Commons.

Realizar Busquedas con Google Maps en tu web

Sábado, Octubre 20, 2007

Estos días me he tenido que pelear bastante en serio con Google Maps y Google Local Search. Necesitaba un mapa que permitiese buscar una dirección y que pudiera, una vez encontrada la dirección, guardarla en una base de datos.

Por suerte Google Maps permite hacer cosas así con poco código aunque de todas maneras me tocó pelearme durante un par de días con su API hasta que conseguí encontrar lo que quería. Casi todo lo necesario se encuentra en la documentación de su API, el único problema es que necesitas saber exactamente lo que buscas antes de poder encontrar algo. En este enlace está la ayuda de Local Search, que aunque no es demasiado extensa tiene algunos ejemplos interesantes.

Mis requsitos exactos eran los siguientes:

  • Un mapa con un cuadro de búsqueda
  • Un sistema para poder moverse por los resultados de la búsqueda de forma sencilla para el usuario

En este caso particular solo necesitaba las coordenadas del centro del mapa una vez que el usuario ha encontrado lo que buscaba. Este dato se copiará en un campo oculto de un formulario para poder guardarlo en una base de datos. En el ejemplo se mostrarán las coordenadas en un DIV junto al mapa.

Una vez que sabemos lo que necesitamos nos ponemos manos a la obra. Vamos a repasar las herramientas que vamos a usar:

  • Lo primero que necesitamos es una key para acceder al API. Para ello visitamos esta dirección. Lo único necesario para conseguirla es una cuenta en Google, sirve la que se usa para acceder a GMail.
  • Como vamos a hacer un uso intensivo de Javascript es una buena idea buscarse un ayudante. En mi caso he echado mano a la librería mootools 1.11 por que es con la que mejor me llevo, pero imagino que sirven otras librerías del mismo estilo como jQuery o prototype. El motivo para usar este tipo de librerías es que permiten moverse libremente por el árbol DOM del documento HTML y capturar eventos que ocurren en él de forma sencilla. Dos tareas que vamos a necesitar para nuestro ejemplo.
  • Por último no nos puede faltar nuestra navaja suiza para el desarrollo web: Firebug ya que nos permitirá depurar y testear nuestro Javascript de forma sencilla.

Aquí podéis encontrar el ejemplo terminado y aquí os lo podéis descargar. Tiene una licencia MIT, así que podéis hacer lo que queráis con él, aunque agradecería un aviso si lo usáis para cualquier cosa, simple curiosidad :)

Por último unas cuantas aclaraciones. He intentado comentar el código lo más claramente posible, si tenéis cualquier duda podéis preguntar en los comentarios e intentaré responder. Si tenéis que añadir el código al post, por favor, hacedlo aquí (aquí tenéis una ayuda por si no sabéis usarlo) y añadid un enlace en el post.

He comentado el codigo linea por linea para los que, como yo, no tengan ni idea de Javascript, mootools o Google Maps. Espero que a ellos les pueda servir como ejemplo de lo que se puede hacer con estas 3 tecnologías juntas.

TinyMCE: Editor WYSIWYG HTML integrable en páginas web

Jueves, Julio 19, 2007

Hoy me ha surgido un problema bastante tonto con una página web que estaba terminando de diseñar para un cliente. Uno de los requisitos es que el cliente necesitaba un cuadro de texto en el que insertar una descripción en texto con formato. Hasta ahí todo bien, hasta que me he dado cuenta de que el cliente no sabe ni tiene por qué saber formatear un texto en HTML. Buscando un poco en Google he encontrado TinyMCE ( DEMO ).

TinyMCE es un editor HTML WYSIGYG ( What You See Is What You Get ) programado en Javascript que se integra en páginas web de forma rápida y sencilla. Convierte los <textarea> en editores completamente funcionales y muy configurables. Una lista de algunas de sus características:

  • Soporte para varios navegadores.
  • Extensible mediante temas y plugins.
  • Soporte para diferentes lenguajes.

Al final parece que el cliente no se va a tener que pelear con HTML… menos mal.

Por cierto, ¿ he dicho ya que tiene licencia LGPL ?

Ejemplo de jQuery ( ahora jugando con los efectos )

Jueves, Mayo 17, 2007

Llevo unos días jugando con jQuery. Ya he dicho en algún post anterior lo mucho que me ha sorprendido la facilidad de uso y la potencia de esta librería. Por ahora solo he podido jugar un poco con los selectores y los efectos, aún no he tenido oportunidad de usar las herramientas de las que dispone, tanto para facilitar el uso de AJAX como para muchas otras cosas. De todas formas aquí va un ejemplo, un poco tonto, eso sí… de lo que se puede hacer con jQuery de forma muy sencilla.

Ejemplo de jQuery

jQuery: AJAX hecho fácil

Lunes, Mayo 14, 2007

En un post anterior ya hablé de jQuery, lo usé para que los enlaces de OBG incluyan un icono a la izquierda que indique cuando salen del blog.

  1. jQuery.noConflict();
  2. jQuery(document).ready(function(){
  3.                 jQuery("a").not("[@href*='otrobloggeek.com']").css("background", "transparent url(/blog/wp-includes/images/link-externo.png) no-repeat");
  4.                 jQuery("a").not("[@href*='otrobloggeek.com']").css("padding", "0 0 2px 18px");
  5. });

Este es el código en cuestión. Es una pequeña demostración de la potencia que nos brinda esta librería. Uno de los puntos fuertes de jQuery son los selectores, que nos permiten recorrer el árbol DOM del documento XML en cuestión; en nuestro ejemplo es HTML. jQuery nos permite mezclar selectores CSS con XPATH, con lo que podemos seleccionar cualquier elemento de la página de forma sencilla. Además, la documentación es bastante completa.

Yo he tenido algún quebradero de cabeza al intentar usarla por que uno de los plugins de OBG usa Prototype, otra librería similar a jQuery y ambas usan el mismo atajo para los selectores: $. Por suerte la documentación de JQuery explica qué hacer en estos casos.

Por cierto, el código de ejemplo, traducido a lenguaje natural sería algo así como: “Selecciona todos los enlaces cuyo destino no contenga ‘otrobloggeek.com’ y ‘ponlos guapos’”.

Algunos cambios

Domingo, Mayo 13, 2007

He introducido algunos cambios light en el estilo del blog y ya de paso le he echado un ojito a jQuery; una librería Javascript que nos hace la vida más fácil.

  • Un blockquote algo más “bonito” ( al menos para mi gusto ). Aquí os dejo el archivo .xcf de Gimp por si os gusta :D . Para incluirlo en la página hay que añadir algo parecido a esto en el estilo de la web:
  1. blockquote {
  2.     background: transparent url(_img/quote.jpg) no-repeat;
  3.     font-size: 1.1em;
  4.     font-style: italic;
  5.     padding: 10px 0 20px 50px;
  6.     width: 420px;
  7.     margin: 0 auto 1em;
  8. }

con lo que conseguimos que se vea más o menos así

esto es una cita de ejemplo para ver como se ve el estilo nuevo de OBG. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi et ante. Donec ullamcorper dolor non metus. Curabitur eget sem. Suspendisse pede. Aenean non dolor. Donec mattis fermentum est. Duis purus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aenean rutrum pretium risus. Etiam adipiscing congue nulla.

  • Un icono a la izquierda de los enlaces externos, como este . Aquí es donde entra en juegojQuery. Usando este script se añade el icono que queramos a la izquierda de los enlaces:
  1. jQuery.noConflict();
  2. jQuery(document).ready(function(){
  3.                 jQuery("a").not("[@href*='otrobloggeek.com']").css("background", "transparent url(/blog/wp-includes/images/link-externo.png) no-repeat");
  4.                 jQuery("a").not("[@href*='otrobloggeek.com']").css("padding", "0 0 2px 18px");
  5. });

Para usarlo hay que añadir antes jQuery a nuestra web. En la web de jQuery tenéis ejemplos de como hacerlo.

Por supuesto podeéis usar el código como queráis y donde queráis. :)

Edito: El icono para los enlaces externos lo he sacado de la galería de iconos Tango que tienen una licencia Creative Commons 2.5 Attribution-ShareAlike

Edito 2: En este post explico qué hace el código Javascript que pone guapos los enlaces.

Edito 3: La medicación de la alergia me deja un poco atolondrado (sí, eso es posible) por eso acabo de subir el archivo Gimp con la imagen que aparece a la izquierda de las citas.

Redirigir las visitas de tu antiguo weblog

Miércoles, Abril 18, 2007

Una de las cosas que mas me ha fastidiado el cambio a wordpress es que he perdido un puñado de visitas que llegaban a mi antiguo weblog (poquitas en realidad) y supongo que también habré perdido algún permalink. Trasteando un poquito con javascript he conseguido un pequeño script que redirije las entradas del weblog viejo al nuevo mediante la etiqueta meta.

El script analiza la dirección por la que se ha llegado al a página, la parsea y formatea el permalink con el formato que yo he elegido en wordpress. Me ha costado sacrificar el día en el permalink, pero no creo que haya sido una gran pérdida.

  1. var string = (location.href);
  2. var getit = new Array();
  3. var getit = string.split(‘/’);
  4. var result = getit[ getit.length-1 ];
  5. var filename = result.split(‘.’);
  6.  
  7. document.write("<meta http-equiv=’refresh’");
  8. document.write("content=’0; url=http://otrobloggeek.com/");
  9.  
  10. if(filename[1]=="html"){
  11.  
  12.   document.write(getit[getit.length-3] + "/");
  13.   document.write(getit[getit.length-2] + "/");
  14.   document.write(filename[0] + "/");
  15.  
  16. }
  17.  
  18. document.write("’/>");

Hay que insertar el script anterior en el head de la plantilla de blogger para que genere una etiqueta meta que lo rediriga. Por supuesto soys libres de cambiarlo, modificarlo y adaptarlo a vuestras necesidades. Seguramente también funcionará en otros motores además de blogger y wordpress.