Cargar scripts JavaScript una sola vez + llamar función cuando la carga termina
Programando interfaces con JavaScript me topé con un problema al que no encontré una solución concreta. Cuando tenemos una página dinámica que carga scripts JS usando AJAX a medida que los va necesitando, podemos caer en el problema de cargar el mismo script más de una vez. Esto se debe a que de antemano no sabemos si el script se cargó o no y lo necesitamos para cumplir alguna función. Un ejemplo rápido de ver es el caso de asignar un evento a un componente. Supongamos que tenemos una página con el siguiente componente: <DIV ID="contenedor">contenido</DIV> y tenemos una sección que cambia según el accionar del usuario, pero carga un script jQuery de la siguiente forma:
$.getScript('/js/bind.js');
cuyo contenido es el siguiente:
$('#contenedor').click(function(event){ $("#contenedor").append("hola"); });
Si llamamos la misma sección más de una vez, lo que sucederá es que el evento click se enlaza más de una vez al componente "contenedor", haciendo que la palabra "hola" se agregue varias veces, en lugar de una sola vez como se esperaría. Van entendiendo por dónde va el problema? De alguna forma, la sección que carga el script debería saber que el script ya se cargó y no debería cargarlo de nuevo. El tema es cómo saber esto... En internet encontré algunas alternativas (sobre todo en StackOverflow) que explican cómo escapar este problema, pero al parecer ni JavaScript, ni jQuery implementan una solución directa, el programador debe encargarse de diseñar una función a tal fin. Otro problema con el que me topé relacionado a esto es cómo saber en qué momento se terminaron de cargar varios scripts. Si usas jQuery, ellos recomiendan usar la función $(document).ready() para esperar a que la página se cargue. La realidad es que cuando se cargan scripts con $.getScript, el evento ready no espera a que estos scripts se carguen. No obstante $.getScript permite definir una función como parámetro que será llamada cuando el script se termine de cargar... pero y si queremos esperar a que un conjunto de scripts se carguen? Para matar dos pájaros de un tiro (los problemas citados), diseñé una función jQuery denominada load_script, la cual decidí compartir con el mundo porque ninguna de las soluciones que encontré me pareció completa. Esta función está basada en distintas propuestas de distintos usuarios de StackOverflow. La función utiliza dos variables globales: loaded_scripts y loading_scripts. loaded_scripts mantiene la lista de scripts que ya se cargaron, así no se los vuelve a cargar nuevamente, mientras que loading_scripts mantiene la lista de scripts que se están cargando actualmente, para saber en qué momento se terminó de cargar todo. Los parámetros de la función son: script_list y callback. script_list es un arreglo con la lista de scripts que se deben cargar y por los cuales debe esperarse a que carguen, mientras que callback es una función definida por el programador que se llamará cuando todos los scripts se terminen de cargar.
/**
 * Load the given JavaScript scripts and call the callback function when all of them are fully loaded.
 * Each script is loaded only once, meanning that if this function is called two times with the same script name
 * it will be loaded the first time. This avoids problems like redeclared functions or variables, event binded more than
 * once, and every other error produced by a script loaded multiple times.
 * The function uses two global array variables:
 *  loaded_scripts: scripts that has been already loaded. Used to know which scripts should not be loaded again.
 *  loaded_scripts: scripts that are in loading process. Used to know when the loading process is done.
 * 
 * @param script_list array containing the scripts links to load. Ex: ['/js/load_this.js', '/js/binder.js']
 * @param callback the function to call when loading of the scripts is done.
 */
var loaded_scripts = Array();
var loading_scripts = Array();
jQuery.fn.load_scripts = function(script_list, callback)
{
  var script;
  
  //check for already loaded scripts and so they're not loaded again
  for(s in script_list)
  {
    if(loaded_scripts.indexOf(script_list[s]) == -1)
      loading_scripts.push(script_list[s]);
  }
  
  //if all the requested scripts are already loaded, callback and return
  if(loading_scripts.length == 0)
  {
    callback();
    return;
  }
  
  for(s in loading_scripts)
  {
    script = loading_scripts[s];
    $.getScript(script,  function() {
      //when script is loaded, remove it from the loading scripts array.
      //if it's the last script on the array, it means we're done loading, so call the callback function.
      loading_scripts.splice(loading_scripts.indexOf(script), 1);
      loaded_scripts.push(script);
      if((loading_scripts.length == 0) && (callback !== undefined))
 callback();
    });
  }
}
Un ejemplo de uso es el siguiente:
$(window).load_scripts(['/js/load_this.js', '/js/binder.js'], function() {
    $('#contenedor').click(function(event){
        $("#contenedor").append("hola");
    });
});
Espero que la función les sirva, al menos como ejemplo, ya que por lo que vi es un problema recurrente en los foros. Si encuentran algún error en el código, me avisan en los comentarios ;)
Obtener información de Wikipedia a través de su API
Desde hace un tiempo me venía planteando la posibilidad de tomar información de Wikipedia para completar la información de ciertos ítems. Pensé, para qué reescribir información que ya existe de forma libre? mejor sería aportar y mejorar los artículos de Wikipedia.

Por programas como Amarok o Clementine (que uso a diario), sabía que Wikipedia tenía alguna especie de web service para tomar información. Buscando encontré que MediaWiki, el software detrás de Wikipedia, provee una API que permite realizar consultas de diversos tipos. Esta web service viene habilitado por defecto cuando instalan el software, y Wikipedia permite su uso de forma gratuita. La API no sólo permite consultar información, sino también modificar el contenido de los artículos en sus bases de datos.

Como la información provista en la descripción de la API me resultó algo escasa o muy desparramada, me pareció interesante explicar brevemente como realizar request de artículos.

Para empezar, necesitamos saber que la URL del web service es la siguiente:
  http://@lc.wikipedia.org/w/api.php
donde @lc debe reemplazarse por el código del lenguaje del artículo que se desea obtener. Por ejemplo, si queremos el artículo de la Wikipedia en inglés, el código será 'en' (http://en.wikipedia.org/w/api.php), mientras que para el español, el código será 'es' (http://es.wikipedia.org/w/api.php).
A esta URL deben pasarse dos parámetros obligatorios, y estos parámetros fuerzan el uso de otros para especificar lo que se desea obtener. Existen muchos posibles parámetros y estos se encuentran documentados en MediaWiki - API:Properties.

Los parámetros obligatorios para obtener contenido son los siguientes:
  - format: especifica en qué formato retornar el contenido. Los formatos disponibles actualmente son:
    - json: formato JSON. Soporta la opción callback que permite especificar una función javascript a llamar cuando la carga del contenido esté completa.
    - php: formato serialized de PHP.
    - wddx: formato WDDX.
    - xml
    - yaml
    - rawfm: formato JSON con elementos de debugging (HTML) y callback.
    - txt: PHP print_r().
    - dbg: PHP var_export().
    - dump: PHP var_dump().
    Si bien la API soporta múltiples formatos, tienen pensado removerlos y dejar sólo JSON. En el artículo me centraré sólo en el uso de JSON.
  - action: especifica qué acción realizar. MediaWiki soporta más de 15 acciones, las cuales están descriptas aquí. La acción que nos ocupa en nuestro caso es 'query'. query es una de las acciones más importantes y está documentada aquí.

Hasta ahora contamos con la siguiente URL para obtener contenido, a la cual iremos agregando parámetros según lo que necesitemos:
  http://en.wikipedia.org/w/api.php?format=json&action=query

Ahora bien, la acción 'query' requiere los siguientes parámetros adicionales para obtener contenido:
  - titles, pageids, revids: es necesario utilizar uno de estos tres parámetros para especificar la página que deseamos, ya sea por el título de la misma (titles), su ID (pageids) o el ID de la revisión (revids). Cabe aclarar aca que cada página tiene múltiples revisiones, siendo la más actual la que se está mostrando. Estos parámetros soportan requests de múltiples páginas a la vez, separando el título/ID/revID de cada una utilizando el símbolo | (ejemplo: titles=PáginaA|PáginaB|PáginaC). MediaWiki aconseja solicitar múltiples páginas a la vez para ahorrar procesamiento y ancho de banda.
  En caso de utilizar el título para obtener la página, es necesario normalizarlo antes. La normalización del título implica poner en mayúsculas la primer letra, reemplazar todos los espacios con underscore '_', y ajustar el nombre al lenguaje que se está solicitando.
  - prop: se utiliza para obtener diversos datos acerca de la/s página/s especificadas con titles/pageids/revids. Cada propiedad conlleva el uso de otro parámetro para especificar información adicional sobre lo que se desea. Las propiedades se encuentran documentadas aquí, siendo las que más nos interesan en nuestro caso, las siguientes:
    - info: recupera información básica acerca de una página. Este valor de prop requiere un parámetro adicional, que puede ser inprop (propiedades a obtener, separadas con el símbolo '|'), intoken o incontinue.
    - revisions: retorna las revisiones de la página solicitada, o bien la última revisión de cada una de las páginas listadas (en caso de solicitar más de una página). Revisions cuenta con varios posibles parámetros, de los cuales los que más nos interesan en este artículo son:
      - rvprop: indica qué propiedad obtener de cada revisión. Existen diversas propiedades que se pueden obtener, siendo 'content' la que nos interesa, dado que es la que indica que deseamos obtener el contenido de la revisión. Si no se especifica otro parámetro, se retornará sólo la revisión actual de la página.
      - rvparse: indica que el contenido retornado debe ser parseado y convertido a HTML. Si no se especifica este comando, el contenido será retornado en formato wikitext.
    - imageinfo/ii: obtiene información de imágenes. Esta propiedad también cuenta con varios posibles parámetros, de los cuales nos interesa iiprop. iiprop permite obtener distintos atributos de una imagen, y de estos nos resultan interesantes 'url' y 'size', que permiten obtener la URL donde se encuentra la imágen y el tamaño de la misma.
   
Además de los listados, los siguientes dos parámetros también son de mucha utilidad:
  - redirects: se puede utilizar en conjunto con titles, para que MediaWiki resuelva los redirects necesarios para llegar al contenido, en caso que el título solicitado realice un redirect.
  - continue: en muchos casos, no se retorna todo el contenido en un sólo request. Cuando esto sucede, MediaWiki incluye la variable continue en su respuesta para indicar que hay más contenido por retornar. Para estos casos, se puede utilizar el parámetro continue (sin ningún valor) y así obtener la continuación del último request.

Ya con la teoría, ahora podemos ver como todo esto funciona en la práctica. Como comenté anteriormente, las URLs que armaremos buscan obtener información en formato json, por lo que los parámetros format=json y action=query estarán en ellas.

Como caso de ejemplo tomemos la wiki en español de Mahatma Gandhi. Como no sabemos el ID de la página, podemos buscar usar el título. Para empezar, debemos normalizar el título antes de poder utilizarlo en la query. En este caso, debemos reemplazar el espacio por el underscore, es decir, queda Mahatma_Gandhi.
La información que deseamos traer es la última revisión del artículo, así que elegimos la propiedad "revisions" y el parámetro rvprop=content, para que traiga el contenido:
  http://es.wikipedia.org/w/api.php?format=json&action=query&titles=Mahatma_Gandhi&prop=revisions&rvprop=content

El formato del contenido retornado es el siguiente:
  {
    "query": información y resultado de la consulta. Es un objeto compuesto por:
    {
      "normalized": título normalizado
      "pages": lista de páginas retornadas por la consulta. Es un arreglo asociativo cuyos índices son los IDs de las páginas. Cada elemento del arreglo está compuesto por:
      {
         "ns":
         "pageid": el ID de la página.
         "revisions": arreglo que contiene todas las revisiones de la página. Está ordenado de revisión más nueva a más antigua, siendo 0 la versión actual. Cada uno de estos arreglos. Este arreglo contiene un arreglo con un solo ítem cuyo índice es el símbolo '*', y es éste el que contiene el contenido de la revisión.
         "title": el título de la página.
      }
    }
    "warnings": contiene warnings que arroja el servidor. Por ejemplo, cuando un título no se encuentra, se retorna un warning en este objeto.
  }
Según lo visto, el contenido de la revisión se puede acceder de la siguiente manera: respuesta.query.pages[].revisions[0]['*']. Si consultamos por una sola página, tendremos un sólo ID de página.

El contenido retornado es texto con formato wikitext. Wikitext es un lenguaje de marcado liviano, es decir, como HTML o LaTeX, pero mucho más simple. El mismo se encuentra descripto en Help:Wiki markup. Existen parsers para este lenguaje, programados en distintos lenguajes. Una lista de parsers se puede encontrar en MediaWiki - Alternative parsers.
En caso que deseen obtener texto formateado en HTML, pueden utilizar el parámetro rvparse de la siguiente manera:
  http://es.wikipedia.org/w/api.php?format=json&action=query&titles=Mahatma_Gandhi&prop=revisions&rvprop=content&rvparse

Cuando vemos el contenido retornado en formato wikitext, observamos que las imágenes no tienen el link a donde se encuentran hosteadas, sino una referencia como "Archivo:Gandhi Nehru Indira.jpg". Si normalizamos el nombre del archivo y adherimos el contenido de lo anterior a un link de Wikipedia, encontramos que se obtiene la imagen en el sitio de Wikipedia: http://es.wikipedia.org/wiki/Archivo:Gandhi_Nehru_Indira.jpg. Pero si queremos embeber la imagen en nuestro site, debemos conocer la URL de la imagen. Para ello se utiliza la propiedad imageinfo, el parámetro iiprop=url|size y el nombre normalizado de la siguiente manera:
  http://es.wikipedia.org/w/api.php?format=json&action=query&titles=Archivo:Gandhi_Nehru_Indira.jpg&prop=imageinfo&iiprop=url|size
La cual responde con un objeto similar al anterior, pero en este caso el arreglo "pages" contiene solo un ítem con índice "-1". Este ítem es un objeto que ahora contiene un atributo denominado imageinfo, que es un arreglo de imagenes. Como solicitamos sólo una imagen, tendrá un solo elemento. Cada elemento de este arreglo tiene el siguiente formato:
  "size": el tamaño de la imagen.
  "width": el ancho de la imagen.
  "height": el alto.
  "url": la URL donde la imagen se encuentra hosteada.
Es decir, la URL se puede obtener de la siguiente manera: respuesta.query.pages[-1].imageinfo[0].url

Bien, con esto ya podemos hacer consultas a Wikipedia y obtener tanto el texto como las imagenes. Formatear el texto obtenido, si lo obtienen en lenguaje wikitext, es otro tema. Estuve programando un parser en javascript, el cual interpreta parte del lenguaje, pero todo lo que se encuentra encerrado entre llaves "{}" tiene muchas variantes e interpretarlo todo no es tan simple. Algún día publicaré el código si es que lo termino. Entre los parsers que se encuentran en la página que cité, implementan parte de lenguaje, no se si hay alguno que interprete todo.

Espero que les resulte útil la información, ya que me costó un par de días interpretar e implementar lo básico de lo que provee esta API.