Compartiendo conocimientos… ¡en un hackathon!

Hoy me gustaría quitarnos el estigma con el que nos podéis estar marcando en plan “frikis emprendedores” gracias a las entradas de nuestro blog. ¡Nada más lejos de la realidad! ¡La verdad es que también somos frikis de otras cosas!

Seguir leyendo en GPMESS.

¡Campeones en SIMO!

¡Sí! El pasado 27 de septiembre vencimos en el SIMO, la feria informática española con más reputación. ¿Y qué fue lo que ganamos? Este año entre los eventos del programa se incluía un concurso de proyectos empresariales llamado “15 minutos de gloria”, realizado en colaboración con CSEV, y ¡el que más gustó al jurado fue gpmess!

Seguir leyendo en GPMESS.

Presentamos la versión alpha en la Campus Party Berlín 2012

A estas alturas muchos ya lo sabéis, porque os lo contamos en la primera newsletter que enviamos a nuestra comunidad con varias noticias, pero para despistados, rezagados y para la posteridad queremos dejar constancia en nuestro blog.

Seguir leyendo en GPMESS.

Estrenamos el blog de gpmess

¡Hola a todos! Por si aún no nos conoces, gpmess es una aplicación que permite dejar mensajes geolocalizados (que nosotros llamamos yipis) en cualquier lugar del mundo y que recibirán las personas que pasen por ese sitio. ¿A que es realmente sencillo?

Seguir leyendo en GPMESS.

Java

Estaba comenzando a leer Piensa en java para una asignatura, cuando me he acordado de que hice un curso de java de las aulas mentor hace como un año. Lo hice porque me aburría, pero desde que me matricule en 4 en la UNED, estoy con la cosa de ir por el título por si me dan algún crédito de libre configuración.

Bueno, pues la cosa es que para el curso hice una práctica que nunca llegué a publicar. Es el típico ejemplo de cosas dibujables, a mi parecer bastante didáctico. Se basa en un applet central (lienzo) en el que se pueden realizar acciones mediante otros applets (botones ejecutables). Pretende ser un ejemplo fácilmente ampliable, añadiendo applets de este segundo tipo. En el correo en el que mandé la practica, envié algunas propuestas de ampliación, y aunque ya no se donde anda, recuerdo que una era por ejemplo pasar un objeto dibujable de un lienzo a otro.

He subido todo a un nuevo espacio de google pages, ya que como no se pueden hacer carpetas, no queria guarrear tanto el otro. Os dejo algunos de los enlaces que podeis encontrar ahí que pueden ser mas útiles: documnetación, uno de los ejemplos, y todo comprimido en un zip.

Espero que a alguien le pueda servir de ayuda, apoyo, o para practicar. Ante cualquier problema o duda ya sabeis.

WAMP-Server

Cuando acabe los exámenes, a parte de ponerme con los del 2º cuatrimestre, tengo pensado aprovechar los ratos muertos en los que no esté currando ni de fiesta en enredar un poco con PHP. Ya había tenido algún contacto, pero no me acuerdo de na, y a pesar de que en algunos sitios digan que no es una comunidad muy buena, siempre he pensado que las cosas siempre se pueden hacer bien independientemente de la herramienta que uses. Al fin y al cabo en el trabajo tengo que mantener un programa escrito en VB… Es verdad que algunos lenguajes te lo facilitan, o se aseguran de que no lo puedas hacer tremendamente mal.

Pues la cosa es que después de pasar media hora intentando configurar el php para que acceda al mysql, me ha dado por mirar si existía alguna forma mas fácil (al estilo linux/ubunt) ya que ahora tengo puesto windows, que de momento sólo quiero hacer pruebas, ya llegará el momento si publico algo de meterse en los entresijos de la configuración. El primer resultado de google al respecto ha sido lo que estaba buscando: WampServer. Te instala la última versión de Apache, PHP y MySql. Además puedes ponerle luego la versión que quieras para simular el entorno de producción. Todo controlado desde un tray icon.

Lo único que a primera vista le falta es un configurador de la seguridad. Si quieres poner contraseñas lo tienes que hacer a mano, lo que para hacer unas pruebas y unos ejemplos está bien, pero si quieres montar un entorno de preproducción hay que simular las condiciones en todo lo posible (aunque entonces tendrás también un entorno de producción y sabrás configurarlo sin problemas).

Muy útil para el que quiera empezar a enredar con php en windows, sin pegarse con nadie en 5 minutos.

BlogRollUpdater

Para desestresarme de estudios, trabajo y otros «males», he creado BlogRollUpdater, un script que actualiza un «blog roll» (lista de enlaces a blogs o similares), ordenando sus elementos en función de la fecha de la última publicación. Podría haberlo hecho dentro de los scripts de la página, este en concreto en el que se encarga de cargar los enlaces, pero me pareció que en este caso no era algo tan «personal» y que le podría servir a cualquiera para su blog roll (sois libres de usarlo de ahí mismo, o copiarlo y modificarlo o hacer lo que os salga con ello). Podéis ver un ejemplo(puede que con el tiempo deje de estar ahí, en cuanto enrede con otra cosa), ademas de el propio blog roll de la pagina, si dais a actualizar veréis como los enlaces se cargan primero con la forma estándar que tenían (por orden del blog de enlaces) y luego se recolocan por fecha de actualización. A continuación el código, y alguna explicación de como hay que llamar a la función:

//Creado por lopez para cerocoma.blogspot.com
//puede ser usado por quien quiera para lo que quiera.
//Sería de agradecer que si lo usas, incluyeras en el blogroll el blog "0,",
//ya que das a entender que tiene algún contenido de interes. Sin embargo no tienes ninguna obligación de hacerlo

//BlogRollUpdater:
//Este objeto se encarga de actualizar el orden de los elementos li de un div en función de sus fechas de actualización
//espera que estos elementos tengan como primer enlace el de un blog
//y que el blog tenga algun feed. Si no tuviese feed (o no se encuentra) se considerará su fecha de actualización
//menor al de cualquier otra.
//
//English (soo bad :):
//This object update the li elements of a div element order using the date of the last entries.
//This object requires that the first link of the li elements is a blog link, and the blog has some feed.
//If a blog doesn't has feed or it is not in the google system the update date is less than others.

var elBlogRoll;
var nBlogs;
var nBlogsProcesados;
var blogs;

function BlogRollUpdater(divId,gFACargada,mostrarResumen,zIndex,tamResumen,styResumen){

 this.divId = divId;
 if(this.divId == undefined)
  this.divId = "BlogRoll";

 this.gFACargada = gFACargada;
 if(this.gFACargada == undefined)
  this.gFACargada = false;

 this.mostrarResumen = mostrarResumen;
 if(this.mostrarResumen == undefined)
  this.mostrarResumen = true;

 this.zIndex = zIndex;
 if(this.zIndex == undefined)
  this.zIndex = 1;

 this.tamResumen = tamResumen;
 if(this.tamResumen == undefined)
  this.tamResumen = 150;

 this.styResumen = styResumen;
 if(this.styResumen == undefined)
  this.styResumen = "background:#ccc;border:1px solid #c60;font-size:11px;text-indent:-15px;text-indent:0px;";

 this.actualizar = function (){
  elBlogRoll = this;
  nBlogs = 0;
  nBlogsProcesados = 0;
  blogs = new Array();

  if(this,gFACargada == false){
   this.gFACargada = true;
   google.load("feeds", "1");
   google.setOnLoadCallback(googleFeedApiInicializada(this));
   
  }else{
   googleFeedApiInicializada(this);
  }
 };
}

function googleFeedApiInicializada(){
 if(elBlogRoll.gFACargada == false){
  elBlogRoll.actualizar();
 }else{
  var container = document.getElementById(elBlogRoll.divId);
  sacarElementos(container);
 }
}

function sacarElementos(contenedor){
 var elems = contenedor.getElementsByTagName("li");
 nBlogs = elems.length;

 for each(var e in elems){
  var a = e.getElementsByTagName("a");
  var dir = a[0].getAttribute("href");
  
  //crear objeto Blog
  google.feeds.lookupFeed(dir,new Blog(e.innerHTML).setFeedUri);
 }
}

//Este objeto me demuestra la poca idea que tengo de javascript (persistencia de objetos, this, etc...)
//parece que en el array blogs no se cargan elementos de este tipo, si no elementos que tienen como padre a un Blog
//Seguro que hay alguna manera de hacerlo bien, pasando siempre el mismo objeto sin tener que crear uno cada vez...
//En concreto que los elementos almacenados en blogs son del tipo setEntry y del setFeedUri (donde se hacen lso push)
//seguramente hay alguna palabra reservada para indicar al padre de un objeto que en este caso si sería del tipo Blog

//Blog:
//Este objeto almacena los datos necesarios para el proceso de una entrada del blogroll
//
//This object has the necesary data to process an entry of the blogroll
function Blog(contenido){
 this.contenido = contenido;

 this.setEntry = function (result){
  this.contenido = contenido;
  if(result.feed != undefined)
   this.entry = result.feed.entries[0];
  nBlogsProcesados = nBlogsProcesados + 1;
  blogs.push(this);
  if(nBlogsProcesados == nBlogs){
   blogsProcesados();
  }
 }

 this.setFeedUri = function (result){
  if(result.url == null){
   nBlogsProcesados = nBlogsProcesados + 1;
   this.contenido = contenido;
   blogs.push(this);
  }else{
   var feed = new google.feeds.Feed(result.url);
   feed.setNumEntries(1);
   feed.load(new Blog(contenido).setEntry);
  }
 }

}

function blogsProcesados(){
 for(var i = 0; i < blogs.length; i++){
  for(var j = i+1; j < blogs.length; j++){
   if(blogs[i].entry == undefined){
    //no se ha encontrado la url del feed o no se ha cargado por algún error, se considera la fecha menor que las demás
    var b = blogs[i];
    blogs[i] = blogs[j];
    blogs[j] = b;
   }else{
    if(blogs[j].entry != undefined){
     //hay dos fechas para comparar
     if(0<((new Date(blogs[j].entry.publishedDate).getTime()) - (new Date(blogs[i].entry.publishedDate).getTime()))){
      //j es posterior a i
      var b = blogs[i];
      blogs[i] = blogs[j];
      blogs[j] = b;  
     }
    }//si no j no tiene fecha y se considera menor que i
   }
  }
 }

 var cadenaHTML = "<ul>";
 var indice = 0;

 for each(var b in blogs){

  if(elBlogRoll.mostrarResumen == true && b.entry != undefined){
   cadenaHTML = cadenaHTML + "\n<li><div  onMouseOver='mostrarResumenBlog(" + indice + ")' onMouseOut='ocultarResumenBlog(" + indice + ")'>";
  }else{
   cadenaHTML = cadenaHTML + "\n<li>";
  }

  cadenaHTML = cadenaHTML + b.contenido;

  if(elBlogRoll.mostrarResumen == true && b.entry != undefined){
   cadenaHTML = cadenaHTML + "</div><div id='resumenBlog" + indice + "' style='z-index:" + elBlogRoll.zIndex + ";position:absolute;visibility:hidden;" + elBlogRoll.styResumen + "'><span style='text-indent:15px;font-weight:bold;'>" + b.entry.title + "</span><br /><span style='font-style:italic;'>" + limpiar(b.entry.content, elBlogRoll.tamResumen) + "</span></div></li>";
  }else{
   cadenaHTML = cadenaHTML + "</li>";
  }

  indice = indice + 1;
 }
 cadenaHTML = cadenaHTML + "</ul>";

 var container = document.getElementById(elBlogRoll.divId); 
 container.innerHTML = cadenaHTML;

}


function mostrarResumenBlog(i){
 var container = document.getElementById("resumenBlog" + i);
 container.style.visibility = "visible";
}


function ocultarResumenBlog(i){
 var container = document.getElementById("resumenBlog" + i);
 container.style.visibility = "hidden";
}

function limpiar(cadena, l){
 var c = "";
 var i = 0;
 var f = 0;
 cadena.replace("\n"," ");
 cadena.replace("\t"," ");
 while(i > -1 && i < l){
  i = cadena.indexOf("<");
  f = cadena.indexOf(">");

  if(i > -1 && f > -1)
   cadena = cadena.replace(cadena.substring(i, f + 1), "");  
 }

 c = cadena.substring(0,l);
 if(cadena.length > l)
  c = c + "...";

 return c;
}

Para variar el código es bastante malucho (y mi ingles :P), me he dado cuenta de que se (aun) menos javascript de lo que yo creía.

Para llamar a la función hay que haber añadido la clave del Google Feeds API, la cual se pone en una etiqueta script como veis en el ejemplo que os dan, o como veis aquí. Además hay que incluir el script, y hacer la llamada. Todo junto quedaría así:

<script type="text/javascript" src="http://www.google.com/jsapi?key=VUESTRAAPIKEY"></script>

<script type="text/javascript" src="http://archivos.cerocoma.googlepages.com/BlogRollUpdater.js">
new BlogRollUpdater().actualizar();</script>

Se pueden pasar algunos parametros a la creación del objeto BlogRollUpdater, serían los siguientes en orden:

  1. divId: es el identificador de la etiqueta div que contiene el blog roll. Por defecto busca «BlogRoll».
  2. gFACargada: indica si la Ajax Feeds API ya ha sido cargada, por ejemplo en mi caso como ya la tenía cargada le indico el valor true. Si se indica el valor false (valor por defecto) hay que tener en cuenta que la llamada ha de realizarse durante la carga de la página, esto es debido al modo en que se cargan las apis de google.
  3. mostrarResumen: indica si hay que mostrar un resumen de la primera entrada del blog, al pasar el ratón por encima del enlace. Si se pone a false, los demás valores no importan. Por defecto a true.
  4. zIndex: es el valor del z-index que queremos en el div que se muestra el resumen. En mi caso con un 1 (valor por defecto) es suficiente para que se muestre por encima del sidebar, sin embargo podría ser necesario cambiarlo según el caso.
  5. tamResumen: es el tamaño del contenido de la entrada del resumen. Hay que tener en cuenta que se omiten las etiquetas html. El valor por defecto es 150.
  6. styResumen: es el stilo que se le pondrá al div en el que se muestra el resumen (salvo el z-index y el visibility que no son opcionales). El valor por defecto es de nuevo el que yo necesitaba: «background:#ccc;border:1px solid #c60;font-size:11px;text-indent:-15px;text-indent:0px;»

Con todo esto, mi llamada es (mas o menos) así:

<script type="text/javascript" src="http://www.google.com/jsapi?key=ABQIAAAAm8jjlSilwL_ngAOmGoVVJRTBirHsSigxVb89Gx4cAc1hSJZCexSRlLoIdwdR82Sjtdy_9-cXY0fKwA"></script>

<script type="text/javascript" src="http://archivos.cerocoma.googlepages.com/BlogRollUpdater.js"></script>

[...codigo de carga de los enlaces...]

new BlogRollUpdater('enlaces',true).actualizar();

Mientras lo hacía me he dado cuenta de que necesito algunas cosas, así que si teneis alguna sugerencia de estas (o de cualquier otra cosa) os lo agradecería.

  • Un editor de javascript que al menos compruebe la sintaxis, y si hace sugerencias sobre nombres de variables mejor, que la mayoría de los errores que he tenido me los quitaría.
  • Un texto completo y detallado sobre javascript y el dom, no tengo ni idea de los prototipos ni esas cosas del javascript y deben tener mucha potencia…
  • Algo sobre css, aunque de esto no estoy muy seguro, que no soy muy de mirar lo bonito de las cosas, mientras funcionen me valen, y eso que se que la mitad de lo que vale algo es lo que ves en el primer vistazo, pero es que me puede.

Pues lo dicho, cualquier sugerencia sobre estas cosas o cualquier otra será de agradecer.

PD: Se me olvidaba una apreciación, si el enlace no tiene un feed asociado, o no está en la BBDD de google asociado a esa dirección, se verá relegado al final, como le pasa en mi blog roll a fuckowski, supongo que por el reciente cambio del nombre de dominio.

PPD: Hay que tener en cuenta que la API trabaja con al cache que tiene de los feeds en sus servidores, por lo que feeds poco actualizados podrían no ver afectada su posición en el blog roll hasta unas horas despues de la última publicación. Es el caso del enlace Atom que es del feed de este sitio, y que mientras escribo esto sigue bastante abajo.

PPPD: Al cesar lo que es del cesar, he de decir que la idea la saque de feevy, pero pense que sería mas simple no tener que dar de alta los blogs…

EDITO (12-01-07): Me he dado cuenta de que en IE no rula, parece un problema de crear objetos desde otros scripts al contenedor del tipo. He probado a poner una función para crear el objeto, pero tampoco funciona…. Además en /. me han dicho que en konqueror tampoco rula, y me han aclarado algo que evitará que el código sea tan malo, así que tendré que hacer una nueva versión cuando pueda arreglar estas cosas (si es que soy capaz :P) cuando tenga tiempo, que llevo dos días sin empollar y el lunes se me acaban las vacaciones.

EDITO (13-01-07): El error de konqueror (no lo he probado expresamente, pero también se producía en firefox, solo que continuaba la ejecución) creo que esta solucionado. El problema era que el objeto devuelto por el getElementsByTagName al aplicarle el for each hacia una pasada mas despues de los elementos li con lapropiedad length, lo que provocaba el error, ya que length no tiene funciones…, hay que verlo para entenderlo, he guardado el script viejo (el que esta mal), por si alguien quiere verlo.

Lo de Internet Explorer tambien era por eso, parece que hacia una pasada previa, y como los for each no le gustaban, como que descartaba todo el script, o algo así, no se muy bien, porque me daba distintos errores cada vez. Unas veces «se esperaba ‘(‘» y otras «‘BlogRollUpdater’ no está definido’, la cosa es que quitando los for each se ha solucionado y ya funciona.

Con esto creo (supongo) que el script funciona con todos los navegadores, lo de arreglar el script para que sea mas legible, mas correcto lo dejo para mas adelante.