fadeObj.js actualizado.

November 19, 2009

Pues siguiendo las recomendaciones de mi gran amigo jseros, he actualizado fadeObj.js para implementar la simulación de los eventos onFadeStart y onFadeStep que se activan al iniciar el efecto y en cada una de las vueltas del loop respectivamente.

El código lo puedes obtener en:

http://www.p-freeweb.com/outside/javascript/fadev1.1/fadeObj1.1.js

También puedes ver un ejemplo demostrando el uso de onFadeStart y onFadeStep en:

http://www.p-freeweb.com/outside/javascript/fadev1.1/fade.html

Espero les gusten los cambios.

Espero más criticas y sugerencias.

PD. La implementación del método toggle para no tener que escoger el modo (entrada o salida) requiere un poco más de trabajo y por el momento no tengo el tiempo para implementarlo.Aun falta hacerlo cross browser.

Gracias Jseros y Panino por sus sugerencias y comentarios.

fadeObj.js –Nuevo script.

November 17, 2009

Hoy les traigo un script que estuve desarrollando durante mi tiempo libre estos dos últimos días. Aun me falta cosas por hacerle, como por ejemplo hacerlo cross browser, pero por ahora creo que es un buen ejercicio para quien lo quiera checar e incluso usar. Agradezco a mi gran amigo Panino5001 quien me ayudo a aclarar una duda que me surgió mientras codigueaba.

Checa un ejemplo de fadeObj.js

fadeObj.js

//ObjectName: fade
//Author:     Buzu.
//Varsion:    1.0
//todo:       evitar que se cancele el efecto una vez terminado.
//Bugs?:      Please report any bug to @imbuzu on twitter. use #fade1.0 #Bug

fade = {
 el : null,
 intervalo : null,
 mod : null,
 inAlph : null,
 seg : null,
 fadeF : function(e, m, s){
 //fadeF sig. fadeFunction
 //aceleramos el acceso a fade con una variable local.
 var f = fade;
 f.seg = s || 3;
 !e ? alert('No Elem') : (f.el = e);
 f.mod = m || 's';
 f.mod == 's' ? f.fadeout() : f.mod == 'e' ? f.fadein() : alert('no valid mode');
 },
 fadein : function(){
 var f = fade;
 //si se vuleve a activar el fade sobre el mismo objeto
 //no queremos que el objeto vuelva a alpha 0
 //sino que el efecto comienze con el alpha que el
 //elemento ya tiene.
 f.inAlph = f.inAlph || 0;
 f.intervalo = setInterval(
 function(){
 f.inAlph += 1/(f.seg*10);
 f.el.style.opacity = f.inAlph;
 if(f.inAlph >= 1){clearInterval(f.intervalo); f.onFadeEnd(f.el)};
 }, 100
 );
 },
 fadeout : function(){
 var f = fade;
 f.inAlph = f.inAlph || 1;
 f.intervalo = setInterval(
 function(){
 f.inAlph -= 1/(f.seg*10);
 f.el.style.opacity = f.inAlph;
 if(f.inAlph <= 0){clearInterval(f.intervalo); f.onFadeEnd(f.el);};
 },100
 );
 },
 onFadeEnd : function(){}
}

Ejemplo de uso:

window.onload = function(){
   document.getElementById('fade').onclick = function(){
      fade.onFadeEnd = function(e){
         document.getElementsByTagName('body')[0].removeChild(e);
      }
      fade.fadeF(this, 's', 2)
   }
}   

Para usar el objeto basta con llamar su método fadeF:

fade.fadeF()

Este método recibe tres parametros, el primero es el elemento al cual se le aplicará el fade, el segundo es el modo ’s’ para salida y ‘e’ para entrada y el tercero es el tiempo que durará el efecto (en segundos).

fade.fadeF(elem, 's', 5);

Solo el primer parámetro es obligatorio. Los otros son opcionales y toman como default  s y 3 respectivamente.

Al terminar el efecto, se llama al método onFadeEnd() para simular eventos:

fade.onFadeEnd = function(){
//codigo de la funcion
}

a onFadeEnd se le puede pasar un parametro el cual regresa el nodo al cual se le aplico el fade:

fade.onFadeEnd = function(e){
alert(e);
}

Para entender más el uso de fade, te invito a que revises el código fuente del ejemplo.

Espero que encuentren útil este objeto. En unos días terminare los detalles. Como siempre, estoy abierto a criticas y sugerencias.

NOTA: Este contenido es por motivos educativos e informativos solamente.

Hace un par de días se me ocurrió que posiblemente se puede acceder a las cookies de un sitio web mediante greasemonkey. Al principio pensé que un agujero de seguridad tan grande no debió pasar por enfrente de los ojos de los desarrolladores del plugin sin ser notado, así que hice una pequeña prueba la cual consiste en crear un nuevo script que sea ejecutable en todos los sitios el cual contiene solo la siguiente instrucción:

alert(document.cookie);

Es super sencillo e inofensivo. Sin embargo, al correr un sitio web te das cuenta que en efecto greasemonkey puede acceder a las cookies de cualquier sitio web. Lo que puedes hacer con esas cookies depende mucho de tu creatividad, conocimiento y por supuesto, de la cookie en sí. Por ejemplo una cosa sencilla que hice fue simplemente redireccionar el navegador a una pagina donde la cookie se manda por correo a mi bandeja de entrada. Al probar ese script pude enviarme las cookies de twitter que mi navegador almacena. Un script bien configurado y dirigido para atacar una app especifica podría causar mucho daño, o por lo menos un buen susto. Lo mas obvio que puedes hacer con esto es robar información y ganar acceso a algunas cuentas de sitios web que usan cookies de forma irresponsable.

Redireccionar no es la forma más inteligente de robarte las cookies. Pero recordemos que greasemonkey no está sujeto a las mismas normas de seguridad que javascript corriendo directamente desde un sitio web. Digo esto por que hay que recordar que ajax no está sujeto a un solo dominio, sino que puede interactuar con documentos de distintos dominios al mismo tiempo, por lo que podemos usar el mismo script que yo hice para enviar el correo, pero en lugar de redireccionar y hacer el robo de datos demasiado obvio, podemos usar ajax y hacer la transferencia totalmente transparente al usuario.

Que se puede hacer al respecto?

La verdad es muy poco probable que te pase eso, a menos que alguien esté intencionalmente haciéndolo y ahí es donde está el problema. Por ejemplo alguien puede esconder el script malicioso dentro de algún otro script. Supongamos que quiero robar las cookies de facebook de alguna persona. Solo tendría que escribir un script que fuera útil para los usuarios de facebook y distribuirlo. El script ya tiene dentro la parte que hace el truco. Puedo disfrazarla de alguna u otra manera e incluso ofuscarla. Puedo incluso hacer que el script malicioso se active solo cuando esa persona en particular lo usa y así evitarme un montón de correos en mi bandeja que en realidad no quiero. Entonces que podemos hacer?

Una de las cosas más obvias es simplemente revisar los scripts que usas, aun que claro, eso puede ser un dolor de cabeza. Puedes por ejemplo usar un editor de textos que tenga capacidad para buscar y haces una búsqueda de ‘document.cookie’ para saber cuando un script esté accediendo a las cookies de tu navegador y ver que es lo que está haciendo con ellas. Otra cosa también es usar script confiables y como siempre investigar un poco antes de instalar un script. Pero aun así, recuerda revisarlo aun si nadie reporta nada raro. Esto por que por ejemplo, yo podría descargar un script muy popular, modificarlo y redistribuirlo asegurando que mucha más gente lo va a usar que un script que yo simplemente haya creado ayer por la tarde.

PD. Probablemnte muchos quieran ver los scripts que hice para enviarme cookies a mi correo. No lo comparto por que se que ahí afuera hay muchos script kiddies que probarán todo lo que encuentren para ‘hackear’.  Además, los scripts son tan básicos que cualquiera que tenga conocimientos mínimos los puede desarrollar por si solo.

Hace un par de días comencé a notar una cosa. Primero fue con twitter y su nueva funcionalidad (que al parecer por el momento la han deshabilitado) de actualizar el sitio cada vez que hay twitts nuevos. Me encantaba por que solo dejaba la ventana abierta y en cualquier momento el titulo de la pestaña cambiaba para indicar cuantos twitts nuevos había. Es mucho más fácil estar al tanto de twitter (y esclavizase a él) de esa manera sin tener que tener otra app abierta. Después comencé a notarlo con otros sitios. Por ejemplo, http://scobleizer.com/ actualiza su barra lateral cada cierto tiempo. Llegó el momento que me dije a mi mismo, Gush! este sitio está vivo!. No es la primera vez que veo que un sitio se mueve por si solo. He visto cientos de rolling menus, y sitios que de una u otra forma “se mueven”, pero eso no me impresiona. Después de todo, todo eso que se mueve no es más que un loop, algo que alguien programó antes y que no cambia-un .gif programado. Sin embargo, estos sitios están no solo moviéndose, sino auto actualizándose para mostrarte el nuevo contenido y es eso precisamente lo que causa la sensación de WOW!

Como programador que soy, se que todo lo que hay detrás no es más que ajax, pero la verdad aun así me impresionó. Probablemente sea por que es una de las primeras veces que veo ajax empleado de forma usable, amigable y responsable, o quizá solo me agarró desprevenido y me sorprendió. Cualquiera que sea la razón, la verdad que por un momento me hizo sentir que estaba viendo algo vivo, algo que se movía, y me produjo la sensación que te produce ver cuando un recién nacido mueve una mano-simplemente increíble. Posiblemente esté exagerando, después de todo ajax ya está creciendo barba. Sin embargo, es agradable ver que finalmente los desarrolladores están aprendiendo a usarlo de forma benéfica y no solo para impresionar damiselas. Seguro que la web nos depara muchas sorpresas todavía. Apps como wave se abren paso y cada vez la web deja de ser ese papel lleno de formularios que proveen la única forma de interacción. En lo personal no me emociona las animaciones ni los drag and drop.  Eso lo veo más bien como simples trucos de feria. Los verdaderos avances en la materia son aquellos que no se notan, que han sido tan bien calculados, planeados y desarrollados que se introducen de forma natural de modo que el usuario nunca se da cuenta que lo está usando y por lo tanto nunca tiene que aprender algo nuevo ni adaptarse aun nuevo método de interacción. Way to go, pero la web es cada vez más excitante y nos exige a notros, lo programadores que de cierta manera somos participes en esa evolución web, cada vez mejores y más responsables metodologías para el uso y la aplicación de las nuevas tecnologías. Ahora solo tenemos dos caminos, sentarnos a esperar más avances en la materia, o se nosotros mismos quienes impulsemos eso avances. Tu cual escoges?

Continuando con nuestra serie de trigonometría, hoy voy a hablar sobre las funciones trigonométricas. Es importante que conozcamos estas funciones como la palma de nuestra mano si queremos llegar a algún lugar en trigonometría ya que estas son la base para todo lo que viene. Generalmente oímos hablar de las funciones trigonométricas en función con el triángulo rectángulo. Sin embargo, en mi experiencia he aprendido que es mucho más fácil entender estas funciones en función al plano cartesiano, por lo que empezaré explicando estas funciones desde ese punto de vista y luego veremos como se implementan en el triángulo.

Supongamos que tenemos un plano cartesiano como el siguiente:

fig1

En donde tenemos el eje de las abscisas y el de las ordenadas o como se les conoce más comúnmente el eje de las X y el eje de las Y. Ahora supongamos que desde el el origen (0,0) trazamos una linea a cualquier punto en el plano cartesiano. A la medida de esta linea la llamamos r

fig2

Ahora podemos calcular las funciones trigonométricas de la siguiente manera:

Seno (Sin) = y/r
Coseno (Cos) = x/r
Tangente (Tan) = y/x
Cotangente (Cot) = x/y
Secante (Sec) = r/x
Cosecante (Csc) = r/y

De modo que si la linea que corre del origen (0,0) llega al punto (5,8), le Seno del ángulo formado por dicha linea se representa de la siguiente manera:

Sin a = 8/r

En donde a es el ángulo y r es la distancia del origen (0,0) al punto (5,8)

fig3

Y así para todas las demás funciones.

Hablemos de Ángulos.

Es costumbre que los ángulos en el plano cartesiano empiecen a medirse en el eje de las x. Un ángulo que se abre en sentido contrario a las manecillas del reloj, es  considerado un ángulo positivo. El ángulo que se abre en sentido de las manecillas del reloj, es un ángulo negativo.

fig4

Las funciones trigonométricas en función del triángulo.

Ya vimos las funciones trigonométricas en función del plano cartesiano, pero seguramente tú las has visto de otra manera. Por ejemplo, quizá haz escuchado que el seno es igual a cateto opuesto sobre la hipotenusa. Eso se refiere simplemente a las funciones trigonométricas en función a los lados del triángulo. Seguramente recordarás del artículo anterior que hablamos sobre la hipotenusa y los catetos. Pues hoy llega el día de aplicar ese conocimiento.

Volviendo a nuestro ejemplo del plano cartesiano, si tomas como punto de inicio el punto final de nuestra linea (5,8) y de ahí trazas una linea perpendicular al eje de las x, te darás cuenta que se forma un triángulo. De esta manera podemos traducir nuestras funciones de modo que nos queden en función del triángulo.

 

fig5

Personalmente prefiero usar el plano cartesiano y las funciones trigonométricas en función a este. Me siento más cómodo con x, y, y r que con catetos e hipotenusa. Pero si a ti te gusta más el triángulo, aquí están las funciones trigonométricas traducidas:

Sin = CO/h
Cos = CA/h
Tan = CO/CA
Cot = CA/CO
Sec = h/CA
Csc = h/CO

En donde:
CO = Cateto Opuesto
CA = Cateto Adyacente
h = hipotenusa

Por ahora eso es todo en cuanto a funciones trigonométricas. En la siguiente ocasión hablaremos sobre Identidades y veremos un ejemplo de las muchas aplicaciones de la trigonometría.

Ayer estaba actualizando una aplicación que hice hace un tiempo. La app está basada en php y necesita comunicarse con pay pal. Para lograr comunicación con pay pal uso curl, pero cuando quise correr la app en local me di cuenta que mi php no estaba usando curl. Para poder usar curl solo tuve que hacer dos cosas:

1)instalar curl para php. Para eso basta con correr la siguiente instrucción en terminal:

sudo apt-get install curl libcurl3 libcurl3-dev php5-curl

Tedarás cuenta que estamos instalando más que solo curl para php, pero está bien. Probablemente esos paquetes ya venían por default (como en muchas distribuciones de linux). No cheque antes de instalar.

Una vez tenemos curl, solo basta con recompilar php si lo compilaste manualmente. Solo baja la distribución que quieras compilar, puedes aprovechar para instalar una versión nueva si no has actualizado. Una vez estes listo para correr el ./configure, agrega la –with -curl a las opciones:

./configure –with-curl

Toma en cuenta que tienes que agregar todos los demás –with dependiendo de lo que quieras configurar en tu instalación. No explico mucho en este punto ya que si tienes que hacer esto quiere decir que ya has complilado php anteriormente y sabes de lo que hablo.

Por último, reincica apache o inicialo si no lo has hecho ya.

sudo /usr/local/apache2/bin/apachectl -k start

para iniciar o:

sudo /usr/local/apache2/bin/apachectl restart

Eso asumiendo que tu instalación de apache esta en /usr/local/

Espero que puedan seguir las instrucciones y poner a disponibilidad curl que puede ser muy útil.

Hoy estaba listo para empezar a hacer algunas cosas que tengo pendientes así que inicie mi compu y empecé por hacer lo de siempre  : checar correos, twitter, algunos blogs etc. Después me dispuse a empezar con los pendientes, pero decidi que primero quería limpiar el depa. Puse en modo invernación mi caja ubuntu 9.10 y justo cuando presioné el botón para invernar, recordé que por alguna razón ubuntu 9.10 no reinicia después de estar en modo de ivernación por lo que hay que apagar el sistema y encender de nuevo la compu. Ya me había pasado un par de veces antes así que como siempre, apagué y volví a prender, pero esta vez algo extraño paso y mi compu solo iniciaba en la linea de comandos. Primero que nada, me apaniqué, lo confieso, pero después decidí que resolvería el problema. Lo primero que hice fue intentar correr nautilus, pensando que así se solucionaría todo, pero solo obtuve un error que no recuerdo muy bien pero era algo como:

No displays especified

no recuerdo exactamente el error, pero tenia que ver con dislpay.

Empecé a investigar un poco y encontré algunas sugerencias que no dieron ningún resultado así que mejor regrese a casa (para investigar fui a  un cafe internet, por ahora solo tengo una compu funcionando). Ya en casa seguí intentando cosas hasta que probé con starx y entre todo lo que me salio me decía:

no screens found

Me volví a conectar a internet desde mi PSP y busqué ese error y encontré que era un problema con la configuracion de X11 por lo que lo único que hice fue reemplazar el archivo xorg.conf por el xorg.conf.failsafe

Para hacer eso solo hice lo siguiente (recuerda que en este momento lo único que estoy usando es la linea de comandos)

cd /etc/X11/

sudo cp xorg.conf xorg.confNo
sudo cp xorg.conf.failsafe xorg.conf

Con la primera linea lo que estoy haciendo es una copia de mi xorg.conf por si algo sale mal. Después con la segunda linea copio el archivo xorg.conf.failsafe y lo ‘pego’ en el mismo directorio bajo el nombre xorg.conf para reemplazar el archivo que hasta ahora esta dando problemas. Se puede hacer también con mv en lugar de cp, pero yo quise conservar los archivos originales por eso en lugar de renombrarlos solo los copio.

Después de hacer eso solo presioné ctl+alt+7 para regresar a la interfaz gráfica y eso me soluciono el problema.

Una cosa mas, antes de hacer todo eso, cuando encendía la computadora y la dejaba correr hasta que me apareciera el prompt para poner mi login y mi contraseña en la linea de comandos, la pantalla me salia flasheante y eso hacia que escribir el nombre fuera muy difícil ya que las letras a veces no se imprimían, y ni hablar de la contraseña en la que no vez lo que estas escribiendo. Para solucionar ese problema lo que hice en mi dell latitude d610 fue apagar la computadora, volverla a prender y presionar esc para ver el menu y seleccionar la opción que dice Kernel…no me acuerdo que mas…(recovery mode) y eso me soluciono lo del flasheo.

Espero que les sirva esto, son mas que nada notas mentales que hago por si algún día las necesito nuevamente.

Skype en Ubuntu 9.04

October 17, 2009

Ayer instale (por fin) skype en mi caja ubuntu. Todo estuvo super fácil, es cuestión de bajar el instalador, abrirlo y seguir instrucciones. Pero cuando quise usarlo me dí cuenta que no reconocía el micro (un logitec con conexión usb). Estuve dando vueltas al asunto por un buen rato. Sabia que el problema era que skype no estaba reconociendo el micro por que en las preferencias no me lo marcaba como una opción. Para no hacer largo el asunto, aqui lo que hice para solucionar el asunto:

Al parecer skype tiene problemas con pulseaudio, por lo que lo que tienes que hacer es simplemente remover el paquete. Para hacer eso basta con abrir el terminal y teclear lo siguiente:

killall pulseaudio
sudo aptitude remove pulseaudio

Lo que hacemos es primero detener todos los procesos de pulseaudio que se encuentren corriendo, después removemos el paquete.

Una vez hecho esto, vuelve a abrir skype, ve a las preferencias y luego a sound devices. Ahi selecciona tu mocro de la lista desplegable que dice Microphone.

Screenshot-Options-1

Eso debe solucionar el problema.

UPDATE: 23/oct/2009

Después de desinstalar pulseaudio noté algo extraño. La máquina se saturaba después de un tiempo de uso viendo videos. Al parecer el no tener pulseaduio forza a la computadora a consumir más recursos de los que generalmente consume al procesar el audio. Eso lo noté mas de un par de veces. Llegaba a un punto en el que la computadora simplemente tomaba demasiado tiempo para hacer algo tan sencillo como cerrar una ventana. Para solucionar el problema instalé esound, y desde entonces no me ha dado problema. Si estás experimentando el mismo problema, prueba con lo siuiente:

en terminal escribe:

sudo aptitude install esound
sudo aptitude remove /etc/X11/Xsession.d/70pulseaudio

Eso debe solucionar el problema. De no ser así probablemente no tengas otra opción que volver a instalar pulseaduio. Si por el contrario encuentras otra solución, puedes compartirla en los comentarios.

Update Oct/31/09

Parece ser que con la nueva versión de ubuntu (9.10) ya no es necesario eliminar pulseaduio ni hacer ningún cambio.

Uno de los temas menos tocados en los blogs y foros de programación y desarrollo web es de las matemáticas. Probablemente sea por que en realidad la aplicación de las matemáticas en la programación y el desarrollo web no es ampliamente valorada, o probablemente sea por que dicha aplicación no es un requerimiento. Sin embargo, el correcto uso de la matemática puede y trae grandes beneficios al desarrollo web.

Piensa por un instante en una simple animación como puede ser desplazar un elemento de un lado a otro en la pantalla. Es un efecto relativamente simple; basta con aumentar o disminuir el valor de la posición de dicho elemento en uno o ambos ejes por unos cuantos pixeles y repetir dicha modificación en intervalos. Sin embargo, esta no es la mejor forma de hacerlo. Se puede usar una simple ecuación algebraica para poder calcular el movimiento del elemento y de esta manera poder incluso determinar y establecer el tiempo de duración de la animación así como mantener un intervalo constante y amigable al cpu del usuario (en mi experiencia he encontrado que generalmente 100 milisegundos es un tiempo relativamente amigable que evita esos odiosos saltos en las animaciones). En este post no voy a hablar sobre este efecto, ya que como dije, eso requiere una ecuación algebraica y lo que en este momento nos interesa no es el álgebra, sino la trigonometría.

La trigonometría, aparte de ser la rama de la matemática con el nombre más cool y exótico desde mi punto de vista, es la rama de la matemática (o de la geometría, según la fuente) que “se ocupa la medida de los elementos de los triángulos.”* A decir verdad, desde mi punto de vista, la trigonometría no es otra cosa que el estudio de los triángulos y la razón entre sus ángulos y sus lados, una geometría con un ego exaltado en donde solo existen los triángulos y los círculos. Es una ciencia relativamente sencilla ya que su aplicación en la vida real se puede ver a simple vista y no es tan abstracta como el álgebra o el cálculo. En este artículo veremos una breve introducción al mundo de la trigonometría que nos preparará para artículos posteriores en los que estaré tratando el uso de canvas.

La trigonometría tiene como base el triángulo rectángulo, el teorema de Pitágoras y la seis funciones trigonométricas. En esta introducción hablaremos solo del triángulo rectángulo y del teorema de Pitágoras. Las funciones trigonométricas las dejaremos para la parte dos de la introducción a la trigonometría.

El triángulo rectángulo.

El triángulo rectángulo es aquel que tiene un ángulo recto. Por si no recuerdas lo que es un ángulo recto: un ángulo recto es aquel que mide 90 grados. Justo al otro lado del ángulo de 90 grados, nos encontramos con la hipotenusa, el lado mas grande del triángulo rectángulo. Probablemente recuerdes que los ángulos de un triángulo siempre suman 180 grados, por lo que, al tener un ángulo recto, es fácil deducir que los dos ángulos restantes del triángulo son complementarios, es decir, que juntos suman 90 grados. Este es un aspecto importante de recordar, ya que muchas veces puede resultar extremadamente beneficioso si se sabe aplicar con destreza. Dentro de las muchas posibilidades del triángulo rectángulo, que ya de por si es especial por si mismo, existen triángulos rectángulos con medidas especiales, casi mágicas.

fig-1

Triángulo 90-60-30

Uno de esos triángulos con medidas especiales es el triángulo de 90, 60 y 30 grados. Todos los triángulos mantiene la proporción de sus lados sin importar su tamaño. Es decir que, como dicen algunos hombres para consolarse, el tamaño no importa. Las proporciones del triángulo rectángulo son 2 para la hipotenusa, raíz de 3 para su lado mediano y 1 para su lado mas corto. El siguiente diagrama te ayudará a entender mejor.

En la práctica, esto significa que si un triángulo 90-60-30 tiene como medida 5px para su lado más corto, su hipotenusa mide 10px y su lado mediano tendrá al rededor de 8.66px. Esto es por que para poder obtener la medida de cada uno de los lados hay que mantener la proporción, por lo que si el lado más corto vale 5, podemos decir que que la hipotenusa vale 2X5 y el lado mediano vale 5X(raíz de 3).

fig-2

Triángulo 90-45-45

Otro triángulo que también conviene recordar es el que tiene un ángulo de 90 grados y dos de 45. Las proporciones de este triángulo son raíz de 2 para la hipotenusa y 1 para sus dos catetos (los lados del triángulo que no son la hipotenusa).

El teorema de Pitágoras

Los pitagóricos descubrieron por ahí del 500 a.C. la relación entre los lados de un triángulo. Más concretamente, descubrieron que la suma de los cuadrados de los catetos de un triángulo igualan el cuadrado de la hipotenusa. Me acuerdo que cuando era chico escuchaba hablar del teorema de Pitágoras, y todos esos kiddies (mas grandes que yo por supuesto) hablaban de ese misterioso “teorema” como algo difícil de mascar. Para ese entonces yo no tenía ni idea de lo que era un teorema, pero recuerdo que pensaba que sería algo difícil, tanto que cuando por fin llegue al cursos escolar donde aprendí el teorema de Pitágoras me quedé “Y eso es todo???.” Y es que la verdad el teorema de Pitágoras es uno de los conceptos más sencillos de la matemática:

a2 + b2 = c2

donde a representa uno de los catetos y b representa al otro, mientras que c representa la hipotenusa, de modo que si quieres saber el valor de la hipotenusa y conoces el valor de ambos catetos podemos decir que:

h = raíz de (a2 + b2)

en donde h representa a la hipotenusa. De igual modo la ecuación puede modificarse para obtener cualquier lado de un triángulo mientras se conozcan los otros dos lados.

Por ahora eso es todo en cuanto a trigonometría se refiere. Espero verlos en la siguiente entrega de esta nueva serie donde nos concetraremos en las seis funciones trigonométricas.

*La Biblia de las Matemáticas (p.833)

Continuando con la serie sobre ajax, veamos esta ocasión un ejemplo sencillo de la creación y el uso del objeto XMLHttpRequest, o XHR como se le conoce para abreviar. Quiero hacer notar que debido a la creciente actividad anti IE6 no quiero tratar los métodos de creación del objeto XMLHttpRequest en IE6, que generalmente requiere un try… catch. A partir de IE7, XMLHttpRequest es soportado de forma nativa, por lo que nos vamos a quedar con este método directo de acceso al objeto. Si te interesa brindar soporte para ajax en IE6, puedes buscar en la web sobre el tema.

Como una nota aparte, try… catch debería ser evitado por los problemas de desempeño que trae consigo.

Creando una nueva instancia:

Crear una nueva instancia de XHR es sumamente sencillo:


var miXHR = new XMLHttpRequest();

Con esto has creado una nueva instancia de XHR lista para ser usada, exprimida y explotada. Ahora, veamos la belleza de XHR en acción.

Para poder seguir el ejemplo, primero tienes que tener la siguiente preparación:

1)Un folder llamado ajax
2)Dentro del folder, un archivo de texto llamado texto.txt
3)Dentro del folder, un archivo HTML llamado ajax.html
4)Dentro del folder, un archivo js llamado ajax.js

El archivo de texto puede contener cualquier texto que tu quieras. El mio, por ejemplo contiene:

“Javascript doesn’t suck, you are just doing it wrong” Douglas Crockford.

Mi archivo HTML contiene tan solo el HTML necesario para ser considerado válido:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="es" lang="es">
   <head>
      <meta http-equiv="content-type" content="text/html; charset=utf-8" />
      <title>Ajax! Ah javascript ambiciosamente xtremo!!!</title>
      <script type="text/javascript" src="ajax.js"></script>
   </head>
   <body>
      <p id="ajaxPantalla"></p>
   </body>
</html>

Y mi archivo Javascript esta completamente vacío… por el momento.

Eso es todo lo que necesitas por ahora. Empecemos a trabajar en nuestro javascript:

archivo: ajax.js


window.onload = function(){
   //declaramos un event handler para el evento load de window.
}

Empezamos declarando un event handler para el evento load de window. Este nos va a permitir acceder al DOM cuando ya este totalmente cargado. El DOM, teóricamente, se termina de cargar antes de que el evento load de window sea activado, sin embargo, los métodos para poder detecta cuando el DOM ha sido cargado son, al momento de escribir este articulo, demasiado engorrosos y desde mi punto de vista no vale la pena recurrir a ellos por varias razones.
Nótese que estamos usando event handlres y no event listeners, esto es solo por comodidad, si quiere puedes usar event listeners, aun que en este ejemplo no creo que valga la pena pasar por todo el trabajo extra que eso requiere.

Continuando con nuestro ejemplo, procedamos a crear una instancia del objeto XHR y algunas variables extra que nos serán de utilidad:

archivo: ajax.js
funcion: window.onLoad


var xhr = new XMLHttpRequest();
var pantalla = document.getElementById('ajaxPantalla');
var initTime = new Date().getTime();

Empezamos por definir una nueva instancia de XMLHttpRequest, y la guardamos en una variable (xhr).
También tomamos una referencia a uno de los elementos en nuestro HTML y lo guardamos en otra variable (pantalla)
Por último, guardamos el tiempo actual en otra variable (initTime). Este ultimo paso es solo para poder ir monitorizando el tiempo que toman nuestras llamadas en ser procesadas. Al final capturaremos el tiempo de finalizado de la función y lo compararemos con el tiempo de inicio de la función para ver cuanto tiempo ha tomado el su procesamiento. Para ser mas “exactos” combendría mover la variable initTime justo al inicio, antes de xhr, de modo que el tiempo sea lo primero que se toma al iniciar la función. Sin embargo, yo lo he preferido dejar así.

Continuemos con nuestro ejemplo:

archivo: ajax.js
function: window.onload


if(xhr){
   xhr.onreadystatechange = function(){
   if(xhr.readyState == 4){
      //if(xhr.status == 200 || xhr.state == 304){
         pantalla.innerHTML = xhr.responseText;
      //}
   }else{
      //proveer mensajes para los diferentes codigos http.
   }
}
xhr.open('GET','texto.txt',true);
xhr.send(null);
}else{
   //proveer una alternativa a ajax si no está disponible.
}

Aquí es donde todo esta pasando. Primero chequeamos que efectivamente xhr esté disponible, de no ser así, proveemos un método alternativo:


if(xhr){
   ...
}else{
   //proveer una alternativa a ajax si no esta disponible
}

En este ejemplo no vamos a hablar sobre alternativas, eso lo dejaremos para ejemplos mas adelante.

Si el primer if nos da true, entonces sabemos que xhr esta disponible, por lo que es seguro continuar.


xhr.onreadystatechange = function(){
   if(xhr.readyState == 4){
      //if(xhr.status == 200 || xhr.state == 304){
         pantalla.innerHTML = xhr.responseText;
      //}else{
         //proveer mensajes para los diferentes codigos http.
      //}
   }
}
xhr.open('GET','texto.txt',true);
xhr.send(null);

Lo primero que hacemos una vez determinado que el objeto xhr está disponible, es asignar una función a su evento readystatechange. Este evento se genera cada vez que el estado de la petición cambia. En esta ocasión no hablaremos de los diferentes estados de la petición, eso lo dejaremos para el siguiente artículo. Por ahora basta con que sepas que el cuarto estado es cuando la petición ha sido exitosa y nos ha regresado los resultados.

En un ejemplo real, o si estas corriendo los ejemplos en un localhost, puedes chequear el estado (status) de la respuesta (response). Si sabes algo de los códigos http, sabrás que 200 significa OK y 304 significa no modificado. En nuestro ejemplo chequeamos si el status de la respuesta es 200 o 304, lo que significa que el documento está disponible, de no ser así, enviamos mensajes diferentes dependiendo el código http de la respuesta. En este caso no hemos incluido esos mensajes, pero implementarlos no es difícil.

Una vez determinado que el status de la respuesta es 200 o 304, podemos imprimir el contenido de nuestro archivo txt a nuestra pantalla, para eso usamos innerHTML para asignar a pantalla el texto regresado por xhr.

xhr tiene dos diferentes tipos de respuesta: responseText y responseXML. Dependiendo de lo que estés pidiendo al servidor querrás usar uno u otro. La mayor parte del tiempo estarás usando responseText, por lo que en nuestros ejemplos nos mantendremos especialmente ligados a el.

Las ultimas dos lineas son las que en realidad hacen la petición:

xhr.open() toma mínimo dos parámetros, el método (GET o POST entre otros) y la url del recurso que queremos pedir (en nuestro caso ‘texto.txt’). El tercer parámetro determina si la petición es sincrónica o asíncrona. En nuestro caso, true, le dice al navegador que la petición debe ser asíncrona. En un futuro hablare de las diferencias entre peticiones sincrónicas y asíncronas, por el momento, basta con saber que la mayor parte del tiempo usaras true como tercer parámetro.

Como una nota aparte, el tercer parámetro no debería ser nunca false por problemas de desempeño.

xhr.open() también recibe otros dos parámetros (usuario y clave) para autentificación básica. Estos los usas cuando un sitio te pide una clave y contraseña. Por ejemplo, si vas a:

http://twitter.com/statuses/user_timeline.xml

te darás cuenta que el navegador te pide una clave y contraseña. Si estuvieras haciendo una petición vía ajax a una página similar, usarías los dos últimos parámetros para especificar tu usuario y contraseña. Toma en cuenta que esto no es recomendable ya que ajax es javascript y los archivos javascript pueden ser fácilmente vistos. Su uso puede ser para, por ejemplo, autentificar usuarios usando ajax donde tanto usuario como clave sean provistos por el usuario y no “hard codded” en el javascript.

xhr.send() sirve para enviar datos. En nuestro caso no estamos enviando nada, por lo que usamos null, habrá ocasiones cuando quieras enviar datos, por ejemplo para un sitio que requiere opciones como un índice de temas en un blog. En ejemplos futuros veremos como se usa send() para enviar datos. Por ahora, no es necesario.

Este ha sido un ejemplo sencillo del uso de ajax. En futuros artículos veremos ejemplos mas complejos y útiles. Habrás notado que en este ejemplo todo sucede cuando se carga la pagina, lo cual realmente no tiene sentido. EL objetivo es poder hacer las peticiones como respuesta al input del usuario ya sea hacer click en un enlace, un botón, o simplemente enviar un formulario.

Aquí esta el código completo, notaras que he agregado algunas variables y un par de lineas para medir el tiempo que tarda (en milisegundos) nuestra petición en ejecutarse. Es simplemente para poder ir manteniendo en mente un poco el desempeño de nuestras funciones.

archivo: ajax.js (completo):


window.onload = function(){
   //declaramos un event handler para el evento load de window.
   var xhr = new XMLHttpRequest();
   var pantalla = document.getElementById('ajaxPantalla');
   var initTime = new Date().getTime();
   var finTime = null;
   var totTime = null;

   if(xhr){
      xhr.onreadystatechange = function(){
         if(xhr.readyState == 4){
            //if(xhr.status == 200 || xhr.state == 304){
               pantalla.innerHTML = xhr.responseText;
               finTime = new Date().getTime();
               totTime = finTime - initTime;
               alert(totTime + 'milisegundos');
            //}
         }else{
            //proveer mensajes para los diferentes codigos http.
         }
      }
      xhr.open('GET','texto.txt',true);
      xhr.send(null);
   }else{
      //proveer una alternativa a ajax si no esta disponible.
   }
}

Espero verlos en la siguiente entrega.