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="https://www.google.com/jsapi?key=VUESTRAAPIKEY"></script>

<script type="text/javascript" src="https://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="https://www.google.com/jsapi?key=ABQIAAAAm8jjlSilwL_ngAOmGoVVJRTBirHsSigxVb89Gx4cAc1hSJZCexSRlLoIdwdR82Sjtdy_9-cXY0fKwA"></script>

<script type="text/javascript" src="https://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.

Siempre hay un modo mas simple…

Hoy va la cosa de como hay que pararse a pensar antes de actuar, es algo que no siempre hago.

A través de fresqui, me encontré una página en la que puedes ver mapas de la tierra en «tiempo real». Esta, en realidad «roba» su funcionalidad a otra, en cuyo dominio se pueden encontrar varias cosas interesantes.

Cuando lo vi me dije que estaría bien tenerlo de fondo de escritorio a pesar de la resolución, y ya me estaba preparando para hacer algún programa/script que la descargara periódicamente. En linux sería fácil, ya que el wget suele estar por defecto. Sin embargo en windows lo único, que yo sepa, con lo que se podría hacer eso por linea de comandos es telnet (seguro que hay alguna cosilla, pero no la conoceré). La cosa es que ya cuando estaba poniéndome a ello, me acordé de que en el escritorio de windows se pueden incrustar trozos de paginas, creo que desde el 95. Echando un vistazo, vi que también se podían establecer como fondo de escritorio paginas html, así que eso hice (está ajustado a mi escritorio 1280×800 con la barra de windows con la altura por defecto):

<html><head></head><body bgcolor="black" alink="black" link="black"><a href="javascript:location.reload(true);"><img src="https://www.fourmilab.ch/cgi-bin/uncgi/Earth?img=learth.evif&dynimg=y&opt=-p" width="1250" height="740" /></a></body></html>

Esto es mucho mas simple que lo que me proponía en un principio, pero realmente tiene la suficiente funcionalidad, y el resultado es similar al que esperaba. Además seguro que en unos días me he aburrido de ello.

Pequeñas actualizaciones

Como veréis he realizado algunos cambios en la pagina, siguiendo con lo que empecé algún tiempo atrás. Para que veáis que no dejo todo sin acabar, sólo lo pospongo hasta que me vuelva a apetecer enredarme con ello (y si no me vuelve a apetecer, pos que le voy a hacer yo :P).

Modifiqué lo de las frases, para poder ir cambiando de una a otra, y los enlaces que tenía estáticos en la pagina, los he modificado para que también se carguen de un blog aparte, para no tener que modificar, cada vez que añada o quite uno, la plantilla. Lo último ha sido un bloque de sugerencias donde mostrar enlaces curiosos, pero que no son para tanto como para ponerles un enlace permanente (estas sugerencias también se pueden ir cambiando con el botón). Si pasáis por encima del enlace que os aparezca, podéis ver una descripción de lo que es en un globo, que he hecho con mis limitados conocimientos de css y javascript.

Ya sé que esta barra lateral se ve bastante mal en IE, pero es que no me apetece nada pegarme con él para que funcione. Además, hay cosas que se que no funcionarán nunca, como lo de las imágenes embebidas en el código.

Bueno, pos lo dicho, ahora hay 3 blogs relacionados con este, que le aportan pequeños contenidos que van mas allá de las entradas: frases, enlaces, enlaces curiosos. Además si se accede a alguno de estos blogs sin poner «?noredir» en la url, se redirige automáticamente a cerocoma, indicándole de donde viene, para que así esta pagina pueda mostrar lo que se quería ver en dichos blogs. Por ejemplo, si se accede a esta pagina añadiendo «?frase=0&enlace=0&enlacecurioso=0» se mostrarán la última frase, la última sugerencia, y el último de los enlaces se verá resaltado.

Aquí dejo el código, por si a alguien le puede aportar ideas, o como ejemplo de uso de la AJAX feeds api de google (el código podría ser mejor, pero solo lo toco hasta que funciona ;):

     var propiedades;var cargandoImg = '<img alt="Cargando" src="data:image/gif;base64,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" width="66" height="66" />';var cambiarImg = '<img title="Cambiar" src="data:image/gif;base64,R0lGODlhHgAeANUzAObm5uLi4uPj4+fn593d3eXl5eHh4dzc3ODg4PHx8dPT09DQ0Ojo6PT09NLS0t7e3vLy8t/f3/f39+rq6tra2vDw8PPz89XV1dbW1u3t7evr69vb29nZ2dfX1/X19e7u7tjY2Onp6fb29uzs7Pj4+Pn5+fr6+u/v7/v7+/39/fz8/OTk5NTU1NHR0c/Pz8HBwX9/f////5ubm////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAADMALAAAAAAeAB4AAAb/wJlsSCwaj0hhLKVCmUokicjTsEASlU9mpJkwBoCVIGB4wWQxmBMqpVqxWq4XLCbDzOh1dFq9ZrddXwAFYwYID3gxT3tufnGBYIRkhwSJbHxvFSeAc4MrkxEEB4lREo1YRJCeoKIbiRKmfQlGEyGRn4ahBxsUryKyR7arQ7q8HIm/b0i3AUW7FBwgiQ0NV8vDRtAgHdN+RsIFYkgy2xiJ3kXg4uMyGBeJWCdGDJ4C7EQsiZofRfThArkeECjSwR2LfGdinNBSpF5AUUUMslCQSIsGI2IeHjBy4aACB4kydDEyBkEEgQcoGPHooEWiEbUYGDGJUmURli1cJow5AAnEcSMTW7ZYkCjEl3D3bn7MucBFoqN1ksoIytSF04R0CkW4R3Wo1atowmhFeaTjUq9fE9UxhNJYObNCFzRNm7AQpWfRCsJlOpcumklttentKver3zR33Q4+W9iwizsJX0ieTLmyZcswZsDYzLmz58+gZwQBADs=" width="12" height="12" />';function procesarQueryString(){ if(propiedades==undefined){  propiedades = new Array();  var cadena = document.URL;  if(cadena.indexOf("?")>-1){   cadena = cadena.substring(cadena.indexOf("?")+1,cadena.length);   var pares = cadena.split("&");   for(var i=0;i<pares.length;i++){    var par = pares[i].split("=");    propiedades[par[0]] = par[1];   }  } }}function separarCampos(valor){ var campos = valor.split('|-|'); return campos;}//Fusilada de http://www.desarrolloweb.com/articulos/763.php function aleatorio(inferior,superior){  numPosibilidades = superior  - inferior;  aleat = Math.random() * numPosibilidades;  aleat = Math.round(aleat);  return parseInt(inferior) + aleat; }var feedFrases;var feedSugerencias;function eliminarElemento(vector, indice){ var auxiliar = new Array(); var i; var j=0; for(i=0;i<vector.length;i++){  if(indice!=i){   auxiliar[j++] = vector[i];  } } return auxiliar;}function mostrarFrase(){ var texto = "Todo conocer depende de la estructura que conoce."; var container = document.getElementById("citaAleatoria"); var boton = ' <div align="right"><a href="JavaScript:modificarFrase();">' + cambiarImg + '</a></div> '; procesarQueryString(); var i = 0; if(propiedades["frase"] != undefined){  i = propiedades["frase"];  if(i<0){   i = 0;  }  if(i>feedFrases.length){   i = feedFrases.length-1;  }   }else{  i = aleatorio(0,feedFrases.length-1); } container.innerHTML = boton + feedFrases[i]; feedFrases = eliminarElemento(feedFrases,i); if(feedFrases.length==0){  feedFrases = undefined; }}function mostrarDescSugerencia(){ var container = document.getElementById("descSugerencia"); container.style.visibility = "visible";}function ocultarDescSugerencia(){ var container = document.getElementById("descSugerencia"); container.style.visibility = "hidden";}function mostrarSugerencia(){ var texto = "Hoy no tengo sugerencias ;)"; var container = document.getElementById("sugerencia"); var boton = ' <div align="right"><a href="JavaScript:modificarSugerencia();">' + cambiarImg + '</a></div> '; procesarQueryString(); var i = 0; if(propiedades["enlacecurioso"] != undefined){  i = propiedades["enlacecurioso"];  if(i<0){   i = 0;  }  if(i>feedSugerencias.length){   i = feedSugerencias.length-1;  }   }else{  i = aleatorio(0,feedSugerencias.length-1); } var campos = separarCampos(feedSugerencias[i].content); container.innerHTML = boton + '<div onmouseover="mostrarDescSugerencia()" onmouseout="ocultarDescSugerencia()"><a href="' + campos[0] + '">' + feedSugerencias[i].title + '</a><div id="descSugerencia" style="z-index:1;position:absolute;background:#ccc;border:1px solid #c60;font-size:11px;visibility:hidden;">' + campos[1] + '</div></div>'; feedSugerencias = eliminarElemento(feedSugerencias,i); if(feedSugerencias.length==0){  feedSugerencias = undefined; }}function cargaFraseAleatoria(result) { //Valor por defecto por si ocurre un error que no se quede en blanco if (!result.error) {  feedFrases= new Array();  for(i=0;i<result.feed.entries.length;i++){   feedFrases[i] = result.feed.entries[i].content;  } } mostrarFrase();}function cargaSugerencias(result) { //Valor por defecto por si ocurre un error que no se quede en blanco if (!result.error) {  feedSugerencias =result.feed.entries; } mostrarSugerencia();}function inicializarFrase(){ var container = document.getElementById("citaAleatoria"); container.innerHTML = '<div align="center">' + cargandoImg + '</div>'; var feed = new google.feeds.Feed("http://frases-cerocoma.blogspot.com/feeds/posts/default?start-index=1&max-results=100000"); feed.setNumEntries(10000); feed.load(cargaFraseAleatoria);}function cargaEnlaces(result) { if (!result.error) {  var container = document.getElementById("enlaces");  procesarQueryString();  var i = -1;  if(propiedades["enlace"] != undefined){   i = propiedades["enlace"];  }  var j = 0;  var cadena = "</ul>";  for(j=0;j<result.feed.entries.length;j++){   if(i==j){    cadena = '<li><a href = "' + result.feed.entries[j].content + '"><span style="color:#c60;"><b><u>' + result.feed.entries[j].title +'</u></b></span></a></li>' + cadena;   }else{    cadena = '<li><a href = "' + result.feed.entries[j].content + '">' + result.feed.entries[j].title +'</a></li>' + cadena;   }  }  cadena = "<ul>" + cadena;  container.innerHTML = cadena; }}function inicializarEnlaces(){ var container = document.getElementById("enlaces"); container.innerHTML = '<div align="left">' + cargandoImg + '</div>'; var feed = new google.feeds.Feed("http://enlaces-cerocoma.blogspot.com/feeds/posts/default?start-index=1&max-results=100000"); feed.setNumEntries(10000); feed.load(cargaEnlaces);}function inicializarSugerencias(){ var container = document.getElementById("sugerencia"); container.innerHTML = '<div align="left">' + cargandoImg + '</div>'; var feed = new google.feeds.Feed("http://enlacescuriosos-cerocoma.blogspot.com/feeds/posts/default?start-index=1&max-results=100000"); feed.setNumEntries(10000); feed.load(cargaSugerencias);}function initialize() { inicializarFrase(); inicializarEnlaces(); inicializarSugerencias();}function modificarFrase(){ propiedades["frase"]=undefined; if(feedFrases == undefined){  inicializarFrase(); }else{  mostrarFrase(feedFrases); }}function modificarSugerencia(){ propiedades["enlacecurioso"]=undefined; if(feedSugerencias == undefined){  inicializarSugerencias(); }else{  mostrarSugerencia(feedSugerencias); }} google.load("feeds", "1"); google.setOnLoadCallback(initialize);

Calculadora en Visual Basic 6

Como (supongo que debido a la entrada sobre VB) bastantes venis buscando una calculadora en Visual Basic y me he encontrado un video de W0Lf099 en el que hace una calculadora, os la dejo para que encontreis lo que buscais. No es que sea muy funcional (no es como una calculadora de mano, ni como la de windows), y alguna de las cosas que dice no es de lo mas exacta (que facil es criticar sin hacer nada ;), pero enseña el uso de controles básicos, y puede ser un buen ejemplo para empezar.

Dura algo menos de 10 minutos:

Canales de usuarios de Youtube en Miro

Para añadir un canal en Miro con los videos de un usuario de youtube, solo hay que ñadir un canal con una url del tipo:

http://www.youtube.com/rss/user/nombreDeUsuario/videos.rss

Por ejemplo, podeis añadir estos en español: muchachadanui, rtve. O este en el que no importa el idioma.

Si sabeis de algun otro canal bueno en castellano no dudeis en dejarlo en un comentario, o enviarme un email.