martes, 26 de enero de 2010

Accediendo a los objetos IFRAME con Javascript

Los iframes son muy útiles a la hora de incluir una página dentro de otra. En ocasiones la comunicación entre ellos es indispensable. Para ello contamos con javascript:

- Desde la página contenida en el iframe, con parent accedemos al objeto window de la página que lo contiene. De esta forma podemos hacer cosas como llamar a funciones y usar propiedades:
parent.miFuncion();
parent.document.getElementById('miId');
parent.location.href = 'miWeb.html';
- Desde la página que contiene el iframe también podemos acceder al objeto window de la página del iframe, con la propiedad contentWindow. Así podemos hacer cosas cómo:
document.getElementById('myIframe').contentWindow.miFunction();
document.getElementById('myIframe').contentWindow.document.getElementById('myId');

Una vez tuve que hacer una web que contenía un iframe oculto que, cuando se mostraba, el iframe contenía la misma página que, a su vez, al ser la misma página, contenía un iframe oculto que al mostrarse se mostraba a si misma... así hasta el infinito :) Pues bien, para acceder al objeto window de la página del iframe más "interno", esto es, el último abierto, hice esta sencilla función (usa prototype):
function getInnerMostIframeWindow(){
    var theWindow = window;
    while(theWindow.$('myIframe').visible())
        theWindow = theWindow.$('myIframe').contentWindow;

    return theWindow;
}

lunes, 25 de enero de 2010

GIT: Lo mejorcito en software para control de versiones

En cualquier proyecto de software no debe faltar un buen software de control de versiones.

CVS, SVN han sido dos de los sistemas más populares, pero la aparición de GIT está consiguiendo que muchos proyectos migren su sistema de control de versiones. Puedes buscar información en la red para comprobar si a ti también te merece la pena cambiar.

Dejando de lado las comparaciones, vamos a ver cómo se usa GIT.

Primero hay que instalar git:
apt-get install git-core
Tras instalarlo, hay que configurar nuestro nombre y nuestro email:
git config --global user.name "Tu nombre"
git config --global user.email nombre@dominio.com
Por defecto los colores están deshabilitados, podemos habilitarlos con:
git config --global color.diff auto
git config --global color.status auto
git config --global color.branch auto
En git existen dos niveles de repositorio: el local y el remoto. Cuando se crea un repositorio sólo se puede sincronizar con el local, puesto que no tiene remoto. Los repositorios creados desde el inicial se se sincronizan localmente y con el remoto. Es posible clonar cualquier repositorio, no sólo el inicial. Por tanto los repositorios forman una estructura de árbol.

Para crear un repositorio, en la carpeta del proyecto escribimos:
git init
git add .
git commit
Estas tres líneas, crean el repositorio, añaden todos los ficheros y crean la primera versión en el repositorio local.

Los datos que usa git para manejar la sincronización se guardan en el directorio oculto ".git". El directorio (también oculto) ".gitignore" guarda información relativa a los ficheros que debe ignorar.

Para trabajar con un repositorio hay que clonarlo:
git clone hostname:/var/proyecto proyecto  
Donde "hostname:/var/proyecto" es la ruta del directorio remoto, y "proyecto" es la ruta del repositorio local.
La comunicación con el equipo remoto se hace con ssh, por tanto el usuario debe tener una cuenta en la máquina remota.

Ahora ya podemos trabajar con el proyecto:
Añadir archivos:
git add file
Borrar:
git rm file
Mover:
git mv file
Para "enviar" los cambios realizados en el repositorio local:
git commit -a
Para "borrar" los archivos de la lista de archivos para subir (evitamos subir un archivo modificado):
git rm --cache archivo
Para almacenar los cambios en el repositorio remoto:
git push
GIT obliga a escribir comentarios a la hora de subir archivos, lo cual está muy bien ya que en otros sistemas muchas veces no hay información de por qué se ha subido ciertos ficheros.

A la hora de obtener los cambios, estos son los comandos:
Desde el repositorio local
git fetch
Desde el repositorio remoto:
git pull
Si eres de los que prefieren un entorno gráfico con botones en lugar de escribir comandos, puedes probar git-cola

Si quieres más información puedes ir a:
- Manual de GIT
- Tutorial de introducción a GIT
- "Chuleta" de GIT  
- GIT para usuarios de SVN 
- es.gitready.com

domingo, 24 de enero de 2010

Simular text-overflow:ellipsis en un párrafo con javascript

La propiedad text-overflow:ellipsis todavía no está implementada en todos los navegadores, así que si queremos obtener un resultado parecido en navegadores donde no está implementado (por ejemplo en Firefox) hay que buscar alguna alternativa.

Existe un "plugin" para jQuery que puedes ver haciendo click aquí.

Yo he hecho una simple implementación para prototype que puedes usar para cortar el texto y poner puntos suspensivos si la altura del texto es mayor a la altura del párrafo.

Esta es la función:
Element.addMethods({
    //Pone puntos suspensivos si el texto del elemento si su altura supera "maxHeight"
    ellipsis: function(element, maxHeight){
        element = $(element);
    
        var i=0;
        var words = element.innerHTML.split(' ');
        element.update('');
        
        while(i < words.length && parseInt(element.offsetHeight, 10) < maxHeight)
            element.update(element.innerHTML + (element.innerHTML == '' ? '' : ' ') + words[i++]);
            
        if (i < words.length)
            element.update(element.innerHTML.substring(0, element.innerHTML.lastIndexOf(' ')) + '...');
            
        return element;
    }
});
Puedes usarlo de esta forma tan sencilla:

Teniendo en el html:
Aquí va tu texto
Si quisieras que tu párrafo tuviese 100px de altura máxima, usarías la función así:
$('parrafo').ellipsis(100);

viernes, 22 de enero de 2010

Ubuntu se queda "congelado" si no le conecto un ratón

Desde la versión 8.04 de Ubuntu me ocurre una cosa muy curiosa con mi portátil: si arranco sin ratón USB conectado, Ubuntu se queda "congelado" y no responde, tengo que reiniciar con el botón. En cambio si conecto un ratón USB funciona a la perfección...

En 2008 puse un post en ubuntu forums comentándolo. Me di cuenta de que le pasaba a mucha más gente, pero nadie sabía solucionarlo. Hace unos días se me ocurrió volver a entrar a ese hilo y... ¡ya había una solución! La solución consiste en añadir estas opciones al arranque en GRUB:

highres=off nohz=off irqpoll 

En ubuntu 9.10 ya no hay menu.lst donde hacer esta modificación. Esto hay que hacerlo en /etc/default/grub, añadiendo las opciones anteriores a GRUB_CMDLINE_LINUX_DEFAULT.

Tras modificar el fichero, hay que ejecutar update-grub y... ¡otra cosa solucionada!

miércoles, 20 de enero de 2010

rcconf: Debian Runlevel Configuration Tool

Esta herramienta te permite controlar, gráficamente, qué servicios se ejecutarán cuando el sistema inicie.



Primero debes instalar rcconf:
# apt-get install rcconf
Y luego lo ejecutas con el comando:
# rcconf

rApache: Interfaz Gráfica (GUI) para configurar Apache

Si quieres añadir/editar tus sitios web en GNU/Linux de una forma muy, muy sencilla, puedes usar rApache, un entorno gráfico que facilitará bastante las cosas.

Para instalarlo basta con buscarlo por su nombre en el gestor de paquetes ó en el centro de software de Ubuntu.

Una vez instalado puede que al realizar alguna acción (como crear un sitio web) se quede congelado, colgado. Esto podemos solucionarlo de una forma muy sencilla. Sólo tenemos que cerrar rApache y editar el archivo RapacheGuy.py:

nano -w /usr/share/pyshared/RapacheGtk/RapacheGui.py

Una vez abierto el fichero, vamos a la línea 80 (para saber en qué línea estamos, con el editor nano, pulsamos Ctrl + C) y añadimos estas dos líneas:

# HACK : work around bug
if not Shell.command.ask_password(): sys.exit(1)

Asegúrate que quede bien tabulado, tiene que quedar igual que las líneas anteriores y posteriores (el lenguaje Python tiene en cuenta las tabulaciones).

domingo, 17 de enero de 2010

Ejecutando funciones en un ámbito distinto con setInterval y setTimeout

A veces ocurre que necesitamos ejecutar una función tras un tiempo, o cada cierto intervalo de tiempo. Para la primera situación usamos setTimeout:
setTimeout("tu_funcion();", milisegundos);
y para la segunda setInterval:
setInterval("tu_funcion();", milisegundos);
Pero en ocasiones hay que cambiar el ámbito en el que se debe ejecutar la función, tras el intervalo de tiempo.

Por ejemplo, imaginemos el caso en el que estamos escribiendo el método de una clase y queremos ejecutar otro método de la misma clase (this.otro_metodo) tras ciertos milisegundos. Por tanto necesitamos que "otro_metodo()" se ejecute en el ámbito de "this". Para solucionar este caso, simplemente hay que usar las funciones de esta forma:
setTimeout(
function(thisObj){ 
    thisObj.otro_metodo(); 
}, milisegundos, this
);
La misma sintaxis sirve para setInterval.

Pero hay un pequeño problema, esto no funciona en explorer (vaya, ¡qué extraño!), así que para solucionarlo podemos usar la librería prototype y usarlo así:

setTimeout(
function(){ 
    this.otro_metodo(); 
}.bind(this), milisegundos);