<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Arragonán &#187; Javascript</title>
	<atom:link href="http://www.danilat.com/weblog/category/programacion/javascript/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.danilat.com/weblog</link>
	<description>Dani Latorre - Desarrollador y algunas cosas más</description>
	<lastBuildDate>Thu, 09 Feb 2012 00:58:23 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Elecciones al Congreso en Arredol</title>
		<link>http://www.danilat.com/weblog/2011/11/23/elecciones-al-congreso-en-arredol/</link>
		<comments>http://www.danilat.com/weblog/2011/11/23/elecciones-al-congreso-en-arredol/#comments</comments>
		<pubDate>Wed, 23 Nov 2011 18:05:29 +0000</pubDate>
		<dc:creator>dani</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Php]]></category>
		<category><![CDATA[Proyectos]]></category>

		<guid isPermaLink="false">http://www.danilat.com/weblog/?p=1844</guid>
		<description><![CDATA[Como publiqué en twitter el mismo domingo del 20-N (el día de las elecciones, vamos ), colaboré con Arredol, un pequeño diario online publicado en aragonés, desarrollando las gráficas de los resultados electorales a las elecciones del congreso español. Fue un desarrollo exprés, ya que tenía otros compromisos que no podía dejar de lado. Fueron [...]]]></description>
			<content:encoded><![CDATA[<p> Como <a href="https://twitter.com/#!/dani_latorre/status/138354700322996224">publiqué en twitter el mismo domingo</a> del 20-N (el día de las elecciones, vamos <img src='http://www.danilat.com/weblog/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> ), colaboré con <a href="http://www.arredol.com/">Arredol</a>, un pequeño diario online publicado en aragonés, desarrollando las gráficas de los <a href="http://www.arredol.com/eleccions-espanyolas-2011/">resultados electorales a las elecciones del congreso español</a>.</p>
<p>Fue un desarrollo exprés, ya que tenía otros compromisos que no podía dejar de lado. Fueron unas 6 o 7 horas de trabajo a tope ese mismo fin de semana, pero me apetecía colaborar por fin con algún medio, aunque fuera tan pequeñito como lo es arredol <img src='http://www.danilat.com/weblog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>Herramientas utilizadas:</p>
<ul>
<li>El <a href="http://politica.elpais.com/politica/2011/11/13/actualidad/1321193831_901025.html">API que puso a disposición El País</a>. Que básicamente hizo el trabajo que según los que defendemos el OpenData debería ser responsabilidad del Ministerio del Interior, poner a disposición de cualquier persona o entidad esos datos de forma estructurada para poder procesarlos.
</li>
<li>
El <a href="http://code.google.com/intl/es-ES/apis/chart/">API de Google Charts</a> para las representaciones gráficas. No pude adaptar los colores por partido por las limitaciones que tiene, o al menos no logré dar con la solución.
</li>
<li>En el lado del servidor <a href="http://php.net/manual/en/function.simplexml-load-file.php">PHP y simplexml</a> para procesar la información de El País. Básicamente por que el hosting de arredol sólo soporta php, no por otra cosa en especial.</li>
</ul>
<p><a href="http://www.flickr.com/photos/dlato/6390268891/" title="Elecciones en arredol.com por Dani Latorre, en Flickr"><img src="http://farm7.staticflickr.com/6043/6390268891_b3b02e95e4.jpg" width="456" height="429" alt="Elecciones en arredol.com"></a></p>
<p>Como podréis comprender, por haber sido un pequeño desarrollo hecho a toda prisa, el código en general es muy mejorable; pero el resultado cara al usuario creo que no está del todo mal. </p>
<p>Seguramente fuera una solución muy alejada de las herramientas de visualización de algunos grandes medios de comunicación, con una posibilidad de interacción mucho mayor. Pero en Aragón quizás fuera de lo mejor, cosa que casi me entristece. </p>
<p>No vi que tuviera mucho que envidiar a lo que vi que hicieron por ejemplo en la web de <a href="http://www.heraldo.es/">Heraldo</a>, y no digamos de <a href="http://elperiodicodearagon.com/">El Periódico de Aragón</a> donde no vi nada especial para la ocasión&#8230; Supongo que no dedicarían muchos esfuerzos&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.danilat.com/weblog/2011/11/23/elecciones-al-congreso-en-arredol/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Repintar mapas con el API de Google Maps V3</title>
		<link>http://www.danilat.com/weblog/2011/07/05/repintar-mapas-con-el-api-de-google-maps-v3/</link>
		<comments>http://www.danilat.com/weblog/2011/07/05/repintar-mapas-con-el-api-de-google-maps-v3/#comments</comments>
		<pubDate>Tue, 05 Jul 2011 02:31:14 +0000</pubDate>
		<dc:creator>dani</dc:creator>
				<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://www.danilat.com/weblog/?p=1708</guid>
		<description><![CDATA[Como (supongo) casi todo programador web que ha hecho desarrollos para internet, he tocado en múltiples ocasiones partes del API de google maps. Hace unos pocos días nos encontramos uno de esos problemas curiososos. Resulta que teníamos varios mapas en una misma página, dentro de la que habían mapas en capas ocultas usando css. La [...]]]></description>
			<content:encoded><![CDATA[<p>Como (supongo) casi todo programador web que ha hecho desarrollos para internet, he tocado en múltiples ocasiones partes del API de google maps.</p>
<p>Hace unos pocos días nos encontramos uno de esos problemas <em>curiososos</em>. Resulta que teníamos varios mapas en una misma página, dentro de la que habían mapas en capas ocultas usando css. La curiosidad en cuestión es que al hacer visibles esas capas no se pintaban correctamente los mapas.</p>
<p>Buscando un poco que podría estar pasando, resulta que cuando creas el mapa google maps coge los estilos que hay en ese momento, y al pasar de oculto a visible el API no es consciente que ha cambiado la visibilidad del elemento que lo contiene y donde se pinta. </p>
<p>Esto en la V2 del API se solucionaba usando <a href="http://code.google.com/apis/maps/documentation/javascript/v2/reference.html#GMap2.checkResize">checkResize</a>, pero resulta que para V3 no está disponible ese método para notificar al mapa que se redimensione. </p>
<p>La necesidad de un <em>checkResize</em> está reportado <a href="http://code.google.com/p/gmaps-api-issues/issues/detail?id=1448">como bug de la versión 3</a>. Pero por suerte en los mismos comentarios aparecen algunas soluciones que me han venido como anillo al dedo para ir trasteando y terminar implementando una solución un poco más a mi gusto, añadiendo a la clase de <strong>google.maps.Map</strong> un comportamiento equivalente:</p>
<p><code><br />
google.maps.Map.prototype.checkResize = function() {<br />
&nbsp;&nbsp;  var center = this.getCenter();<br />
&nbsp;&nbsp;  google.maps.event.trigger(this, 'resize')<br />
&nbsp;&nbsp;  this.setCenter(center);<br />
}<br />
</code></p>
<p>Y así ya puedo utilizar el <em>checkResize</em> en los mapas del mismo modo que en la versión 2.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.danilat.com/weblog/2011/07/05/repintar-mapas-con-el-api-de-google-maps-v3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL con Javascript: Web SQL Database</title>
		<link>http://www.danilat.com/weblog/2010/05/18/sql-con-javascript-web-sql-database/</link>
		<comments>http://www.danilat.com/weblog/2010/05/18/sql-con-javascript-web-sql-database/#comments</comments>
		<pubDate>Tue, 18 May 2010 00:20:56 +0000</pubDate>
		<dc:creator>dani</dc:creator>
				<category><![CDATA[Aplicaciones Web]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://www.danilat.com/weblog/?p=803</guid>
		<description><![CDATA[Como supongo que muchos ya sabréis, una especificación de HTML5 es Web SQL Database para persirtir datos en una base de datos relacional embebidos en el navegador web(la otra alternativa es Web Storage, para persistir datos como clave valor). Esto puede tener muchas aplicaciones, en mi caso lo he utilizado para implementar el sistema de [...]]]></description>
			<content:encoded><![CDATA[<p>Como supongo que muchos ya sabréis, una especificación de HTML5 es <a href="http://dev.w3.org/html5/webdatabase/">Web SQL Database</a> para persirtir datos en una base de datos relacional embebidos en el navegador web(la otra alternativa es <a href="http://dev.w3.org/html5/webstorage/">Web Storage</a>, para persistir datos como clave valor). Esto puede tener muchas aplicaciones, en mi caso lo he utilizado para implementar el sistema de favoritos de <a href="http://www.dndzgz.com/">DNDzgz</a>.</p>
<p>Cuando pretendamos sacar partido de las nuevas características de HTML5 debemos tener en cuenta que cada navegador puede soportar sólo algunas especificaciones, no es un todo o nada, por lo que lo primero que deberemos hacer es comprobar que soporta la especificación que queremos usar, por ejemplo:</p>
<p><code> function supports_local_database() {<br />
  return !!window.openDatabase;<br />
}</code></p>
<p>Si existe openDatabase, crearemos la conexión a la base de datos:</p>
<p><code><br />
db = openDatabase('dndzgz', '1.0',  'DNDzgz', 65536);</code></p>
<p>Una vez abierta la conexión, podremos ejecutar cualquier tipo de query SQL(compatible con <a href="http://www.sqlite.org/">SQLite</a>), dentro de una transacción. Por ejemplo crear una tabla:</p>
<p><code>db.transaction(<br />
function(transaction) {<br />
transaction.executeSql(<br />
'CREATE TABLE IF NOT EXISTS favorites ' +<br />
' (id INTEGER NOT NULL, ' +<br />
' service VARCHAR(255) NOT NULL, ' +<br />
' date DATE NOT NULL,' +<br />
' name VARCHAR(255) NOT NULL, ' +<br />
' latitude REAL NOT NULL, ' +<br />
' longitude REAL NOT NULL, ' +<br />
' PRIMARY KEY (id,service));'<br />
);<br />
}<br />
);</code></p>
<p>Insertar datos:</p>
<p><code>db.transaction(<br />
function(transaction) {<br />
transaction.executeSql(<br />
'INSERT INTO favorites (id, service, date, name, latitude, longitude) VALUES (?, ?, ?, ?, ?, ?);',<br />
[id, service, new Date(), name, latitude, longitude],<br />
callBack,<br />
errorCallBack<br />
);<br />
}<br />
);</code></p>
<p>Eliminar datos:</p>
<p><code>db.transaction(<br />
function(transaction) {<br />
transaction.executeSql('DELETE FROM favorites WHERE id=? AND service=?;',<br />
[id,service], null, errorCallBack);<br />
}<br />
);</code></p>
<p>Y por supuesto mostrarlos:</p>
<p><code>db.readTransaction(<br />
function(transaction) {<br />
transaction.executeSql(<br />
'Select * from favorites;', [],<br />
function(transaction, result){<br />
for (var i=0; i < result.rows.length; i++) {<br />
var row = result.rows.item(i);<br />
alert(row.name);<br />
alert(row.service);<br />
}<br />
},<br />
errorCallBack<br />
);<br />
}<br />
);</code></p>
<p>Como podéis ver, a <strong>executeSql</strong> se le pasa primero la query, seguidamente un array con los valores de los argumentos de la query, y finalmente una función de callback y otra de callback para el caso de que existan errores. Y existen dos tipos de transacciones: <strong>transaction</strong> y <strong>readTransaction</strong>, la primera es de lectura-escritura, mientras que la segunda es de sólo lectura.</p>
<p>En fin, supongo que a otros también os pasará lo mismo, resulta bastante raro estar tirando queries SQL desde javascript. Pero puede resultar útil para muchos casos, empezando por descargar de responsabilidades y carga al lado servidor.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.danilat.com/weblog/2010/05/18/sql-con-javascript-web-sql-database/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Las entrañas de DNDzgz</title>
		<link>http://www.danilat.com/weblog/2010/04/29/las-entranas-de-dndzgz/</link>
		<comments>http://www.danilat.com/weblog/2010/04/29/las-entranas-de-dndzgz/#comments</comments>
		<pubDate>Thu, 29 Apr 2010 08:20:26 +0000</pubDate>
		<dc:creator>dani</dc:creator>
				<category><![CDATA[Aplicaciones Web]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[Proyectos]]></category>

		<guid isPermaLink="false">http://www.danilat.com/weblog/?p=779</guid>
		<description><![CDATA[Lo prometido es deuda, tenía pendiente escribir un poco acerca de la parte técnica del fin de semana del desafío AbreDatos y de DNDzgz. A grosso modo las tecnologías utilizadas fueron Google App Engine(GAE) y Python del lado servidor; del lado cliente fueron Javascript con jQuery, la versión 3 del API de Google Maps, algunas [...]]]></description>
			<content:encoded><![CDATA[<p>Lo <a href="http://www.danilat.com/weblog/2010/04/20/nuestra-aportacion-en-el-desafio-abredatos-2010-dndzgz-com/">prometido es deuda</a>, tenía pendiente escribir un poco acerca de la parte técnica del fin de semana del <a href="http://www.abredatos.es/">desafío AbreDatos</a> y de <a href="http://www.dndzgz.com/">DNDzgz</a>. A <em>grosso modo</em> las tecnologías utilizadas fueron <a href="http://code.google.com/intl/es-ES/appengine/">Google App Engine</a>(GAE) y <a href="http://www.python.org/">Python</a> del lado servidor; del lado cliente fueron Javascript con <a href="http://jquery.com/">jQuery</a>, la versión <a href="http://code.google.com/intl/es-ES/apis/maps/documentation/v3/">3 del API de Google Maps</a>, algunas de las novedades de <a href="http://dev.w3.org/html5/spec/Overview.html">HTML5</a>, unas gotas de <a href="http://www.w3.org/TR/css3-roadmap/">CSS3</a> y <a href="http://jqtouch.com/">jQTouch</a> para ayudarnos para que tuviera pinta de aplicación nativa iPhone. Usamos <a href="http://git-scm.com/">Git</a> como repositorio de código, el repositorio está concretamente <a href="http://github.com/danilat/closin">en github</a>; para los documentos, diseños, fotos, etc. utilizamos <a href="https://www.dropbox.com/">dropbox</a>(antes del fin de semana yo no tenía ni cuenta <img src='http://www.danilat.com/weblog/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> ).</p>
<div align="center"><a href="http://www.dndzgz.com/" title="Logo DNDzgz"><img src="http://farm4.static.flickr.com/3120/4561892814_761c6fd258_o.jpg" width="292" height="113" alt="Logo DNDzgz" /></a></div>
<p>La elección de GAE fue casi instantánea cuando empezamos a hablar con <a href="http://gimenete.wordpress.com/"><strong>gimenete</strong></a> acerca de presentarnos al AbreDatos, las razones: hosting gratis y capacidad de escalar mucho sin tener que gastarnos ni un euro, despreocuparnos de la parte de sistemas, ningún problema con las limitaciones por correr sobre la plataforma de Google. </p>
<p>Que usáramos Python, aún siendo más <em>javeros</em> que otra cosa, fue por que ninguno de los 2 teníamos experiencia con GAE en Java(okok, yo había hecho <a href="http://www.danilat.com/weblog/2010/03/02/el-zaragoza-twitter-y-gaelykgroovy-appengine/">un pequeño experimento</a>, pero muy poca cosa para llegar a ninguna conclusión). Por eso preferimos aprovechar su experiencia desarrollando la primera versión de <a href="http://es.debugmodeon.com/">debug_mode=ON</a> con Python+GAE; mientras que varias semanas antes yo me ojeé un par de manuales de inicio rápido, retomé el ebook <a href="http://mundogeek.net/tutorial-python/">Python para todos</a> que tenía a medio leer(hace muuuucho <img src='http://www.danilat.com/weblog/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> ) y un par de días antes, me hice en poco rato <a href="http://code.google.com/intl/es-ES/appengine/docs/python/gettingstarted/">el proyecto de ejemplo de GAE</a>. Para extraer los datos utilizamos tanto <a href="http://www.crummy.com/software/BeautifulSoup/">Beautiful Soup</a> como expresiones regulares para hacer scraping de HTML o Javascript de <a href="http://www.tuzsa.es/">Tuzsa</a> y <a href="http://www.bizizaragoza.com/">Bizi</a>, y simplejson para cargar los datos JSON de <a href="http://datos.zaragoza.es/">datos.zaragoza.es</a>.</p>
<p>Que utilizáramos jQuery como framework Javascript, fue una elección posterior a jQTouch(que está basado en jQuery) pero de todas formas, seguramente lo hubiéramos elegido. Google Maps es la elección &#8220;por defecto&#8221; para todo el que quiere hacer algo con mapas <img src='http://www.danilat.com/weblog/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> . Gimenete es quien estuvo peleando con esto, teníamos problemas con la fluidez en la navegación de los mapas, que al final consiguió mejorar&#8230; Eso sí, fuera del navegador Safari del iPhone no conseguimos que los mapas funcionaran correctamente, ni en terminales con distintas versiones de Android y ni si quiera en el Safari de Mac(tenemos que ver que pasa exactamente, tras algunas pruebas, el sospechoso principal es jQTouch).</p>
<p>Gracias a que iPhone(y las últimas versiones de Android) soportan parte de HTML5, se ponían a nuestra disposición algunas de esas novedades que molan tanto (Flash, tiemblaaa!! <img src='http://www.danilat.com/weblog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> ): </p>
<ul>
<li>La posibilidad de geolocalizar al usuario por medio del GPS del terminal (<a href="http://diveintohtml5.org/detect.html#live-geolocation">no es exactamente HTML5</a>, pero parece que la mayoría lo ponemos en el mismo saco) muy fácilmente utilizando <strong>navigator.geolocation</strong>. </li>
<li>Para implementar los favoritos/acceso rápido estuvimos usando <a href="http://dev.w3.org/html5/webdatabase/">Web SQL Database</a>, lo que supone guardar los datos en una base de datos embebida al navegador web(actualmente parece que en todos es SQLite, o al menos parece ser la <em><a href="http://dev.w3.org/html5/webdatabase/#web-sql">implementación de referencia</a></em>), que finalmente se quedó fuera por falta de 3/4 horas :S.</li>
</ul>
<p>En fin, que debemos molar, porque nuestro proyecto es una pequeña colección de buzzwords: Cloud Computing vía Google App Engine, HTML5, iPhone&#8230; XD</p>
]]></content:encoded>
			<wfw:commentRss>http://www.danilat.com/weblog/2010/04/29/las-entranas-de-dndzgz/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Historia de los frameworks web</title>
		<link>http://www.danilat.com/weblog/2010/02/24/historia-de-los-frameworks-web/</link>
		<comments>http://www.danilat.com/weblog/2010/02/24/historia-de-los-frameworks-web/#comments</comments>
		<pubDate>Wed, 24 Feb 2010 01:38:03 +0000</pubDate>
		<dc:creator>dani</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Php]]></category>
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://www.danilat.com/weblog/?p=710</guid>
		<description><![CDATA[By @mraible]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.flickr.com/photos/mraible/4378559350/"><img src="http://farm5.static.flickr.com/4067/4378559350_70bd42f61f_b.jpg" alt="" /></a><br />
By <a href="http://twitter.com/mraible">@mraible</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.danilat.com/weblog/2010/02/24/historia-de-los-frameworks-web/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Testeando respuestas JSON con Grails</title>
		<link>http://www.danilat.com/weblog/2009/11/20/testeando-respuestas-json-con-grails/</link>
		<comments>http://www.danilat.com/weblog/2009/11/20/testeando-respuestas-json-con-grails/#comments</comments>
		<pubDate>Fri, 20 Nov 2009 01:35:08 +0000</pubDate>
		<dc:creator>dani</dc:creator>
				<category><![CDATA[Grails]]></category>
		<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://www.danilat.com/weblog/?p=611</guid>
		<description><![CDATA[Aunque en la documentación de Grails aparece un ejemplo de como escribir un test para una acción que recibe una petición en formato XML o JSON, no lo hace de como escribir un test de una acción que genera el JSON, que tampoco es que sea precisamente complicado. Si lo único que quisieramos probar es [...]]]></description>
			<content:encoded><![CDATA[<p>Aunque en la <a href="http://grails.org/doc/1.1.1/guide/9.%20Testing.html#9.2%20Integration%20Testing">documentación de Grails aparece un ejemplo</a> de como escribir un test para una acción que recibe una petición en formato XML o JSON, no lo hace de como escribir un test de una acción que genera el JSON, que tampoco es que sea precisamente complicado.</p>
<p>Si lo único que quisieramos probar es que, en una cadena JSON, se está devolviendo algún valor que estuvieramos esperando, podríamos utilizar el contenido que devuelve la response como una cadena(con <strong>contentAsString</strong>) y hacer alguna comprobación sobre el texto:</p>
<p><code>def response = controller.response.contentAsString<br />
assertTrue response.contains('"name":"Gustavo Poyet"')<br />
assertTrue response.contains('"goals":63')<br />
</code></p>
<p>Pero claro, este test es un muy ligero y no prueba demasiado. Si quisieramos probar más a fondo la respuesta(estructura, un elemento concreto de un array, etc), podríamos usar contains sobre la cadena devuelta, convertir tipos&#8230; vamos, que sería más que posible que el código del test terminara siendo infumable. Pero está disponible <em>out of the box</em> el <a href="http://grails.org/doc/1.1.1/api/grails/converters/JSON.html"><strong>converter JSON</strong></a> de Grails, que permite testear más a fondo fácilmente y con un código mucho más claro.</p>
<p>Es muy posible que si alguien se ve en la necesidad de escribir un test para una acción que devuelve un JSON, ya conozca el converter, por que es una de <a href="http://grails.org/doc/1.1.1/guide/6.%20The%20Web%20Layer.html#6.1.7%20XML%20and%20JSON%20Responses">las alternativas que hay para hacerlo</a>:</p>
<p><code>render object as JSON</code></p>
<p>Pues esa misma clase, tiene el paso contrario, pasar una cadena a un objeto groovy/java(<a href="http://grails.org/doc/1.1.1/api/org/codehaus/groovy/grails/web/json/JSONElement.html">JSONElement</a>). De esta forma ya nos ahorraremos trabajo sucio y el código quedará bastante claro:</p>
<p><code>def response = controller.response.contentAsString<br />
def responseJSON = grails.converters.JSON.parse(response)<br />
assertNotNull responseJSON.players<br />
assertEquals 5, responseJSON.players.size()<br />
assertEquals 63, responseJSON.players[0].goals<br />
assertEquals "Gustavo Poyet", responseJSON.players[0].name<br />
</code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.danilat.com/weblog/2009/11/20/testeando-respuestas-json-con-grails/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Cambiando de prototype a YUI con Grails</title>
		<link>http://www.danilat.com/weblog/2009/09/08/cambiando-de-prototype-a-yui-con-grails/</link>
		<comments>http://www.danilat.com/weblog/2009/09/08/cambiando-de-prototype-a-yui-con-grails/#comments</comments>
		<pubDate>Mon, 07 Sep 2009 23:46:25 +0000</pubDate>
		<dc:creator>dani</dc:creator>
				<category><![CDATA[Grails]]></category>
		<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://www.danilat.com/weblog/?p=508</guid>
		<description><![CDATA[Días antes del último despliegue de Jobsket, estuve dándole vueltas a un problemilla con Grails 1.0.5 y los taglibs estándar para usar Ajax, por defecto Grails utiliza la librería javascript prototype para abstraerse de los distintos navegadores. Para que funcionen los taglibs remoteFunction, remoteLink y formRemote debemos utilizar &#60;g:javascript library=&#8221;prototype&#8221; /&#62; para que cargue el [...]]]></description>
			<content:encoded><![CDATA[<p>Días antes del último despliegue de <a href="http://www.jobsket.com/">Jobsket</a>, estuve dándole vueltas a un problemilla con <strong>Grails 1.0.5</strong> y los <a href="http://grails.org/doc/1.0.x/guide/6.%20The%20Web%20Layer.html#6.7%20Ajax">taglibs estándar para usar Ajax</a>, por defecto Grails utiliza la librería javascript <a href="http://www.prototypejs.org/">prototype</a> para abstraerse de los distintos navegadores. Para que funcionen los taglibs remoteFunction, remoteLink y formRemote debemos utilizar <em>&lt;g:javascript library=&#8221;prototype&#8221; /&gt;</em> para que cargue el .js de la librería, la cuestión es que estamos utilizando algunos componentes de <a href="http://developer.yahoo.com/yui/">YahooUI</a>(y de <a href="http://grails.org/plugin/grails-ui">GrailsUI</a>) y para aligerar el peso de las peticiones, queríamos quitar todas nuestras dependencias con prototype.</p>
<p>Después de refactorizar nuestro código javascript dependiente de prototype, donde hemos encontrado que hay efectos muy sencillos de implementar gracias a <a href="http://script.aculo.us/">script.aculo.us</a> que no lo son tanto con YahooUI(la librería <a href="http://blog.davglass.com/files/yui/effects/">Effects Widget</a> nos ha ayudado en esta transición), nos encontramos que teniendo en el layout la declaración de qué librería deben usar para renderizar esos taglibs de Ajax, en las vistas seguía haciéndolo con el código para prototype, por lo que daba errores javascript. Para que en cada vista renderizara usando el código de YUI, debemos poner la declaración <em>&lt;g:javascript library=&#8221;yui&#8221; /&gt;</em> en cada vista, yendo con cuidado en el orden de las dependencias, ya que si hay un <em>&lt;g:javascript library=&#8221;yui&#8221;/&gt;</em> en el layout y en la vista sólo se renderizará el segundo, por lo que habría que hacer algo así:</p>
<p>En el layout:<br />
<code>&lt;g:javascript library="yui" /&gt;<br />
&lt;g:layoutHead /&gt;<br />
&lt;yui:javascript dir="..." file="..." /&gt;<br />
&lt;yui:javascript dir="..." file="..." /&gt;<br />
&lt;g:javascript library="application" /&gt;</code></p>
<p>En la vista:<br />
<code>&lt;g:javascript library="yui" /&gt;<br />
&lt;yui:javascript dir="..." file="..." /&gt;</code></p>
<p>En este orden se renderizarán primero las dependencias básicas de la librería YUI, luego las que necesitemos para usar componentes, y por último nuestro propio código que puede depender de algún componente.</p>
<p>En fin, no es una solución DRY, pero funciona para los pocos casos en los que lo necesitamos.</p>
<p>Otra de las soluciones de las que nos hemos ayudado, como muchos seguro que imaginaréis <img src='http://www.danilat.com/weblog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> , es implementar una función $(), que aunque no nos dé las bondades de las <a href="http://www.prototypejs.org/learn/extensions">extensiones DOM de prototype</a>, nos ha ayudado a tener que cambiar mucho menos código:</p>
<p><code>function $(id){ return YAHOO.util.Dom.get(id)}</code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.danilat.com/weblog/2009/09/08/cambiando-de-prototype-a-yui-con-grails/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Bug con IE 6 y LiveValidation</title>
		<link>http://www.danilat.com/weblog/2008/01/17/bug-con-ie-6-y-livevalidation/</link>
		<comments>http://www.danilat.com/weblog/2008/01/17/bug-con-ie-6-y-livevalidation/#comments</comments>
		<pubDate>Thu, 17 Jan 2008 16:56:00 +0000</pubDate>
		<dc:creator>dani</dc:creator>
				<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://www.danilat.com/weblog/2008/01/17/bug-con-ie-6-y-livevalidation/</guid>
		<description><![CDATA[Este dolor de cabeza en forma de bug hacía bastantes días que lo tenía, utilizando la librería LiveValidation para validaciones con javascript con IE 6. Pues resulta que cuando intentaba crear una nueva validación a un textarea concreto en un formulario, me daba un error: LiveValidation::getElementType &#8211; Element must be an input, select, or textarea!. [...]]]></description>
			<content:encoded><![CDATA[<p>Este dolor de cabeza en forma de bug hacía bastantes días que lo tenía, utilizando la librería <a href="http://www.livevalidation.com/">LiveValidation</a> para validaciones con javascript con IE 6.</p>
<p>Pues resulta que cuando intentaba crear una nueva validación a un textarea concreto en un formulario, me daba un error:</p>
<p><strong>LiveValidation::getElementType &#8211; Element must be an input, select, or textarea!</strong>. </p>
<p>A base de &#8220;debuggar&#8221; el código de la librería vi que al final la causa era porque ese textarea tenía un <strong>id=description</strong>,  y al hacer la comprobación de si el elemento con ese id es un <em>input</em>, un <em>textarea</em> o un <em>select</em> devolvía un <em>meta</em> por el <em>meta name=description&#8230;</em> del header.</p>
<p>La solución tan sencilla como cambiar el dichoso id y seguidamente informar a los autores de la librería sobre el bug.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.danilat.com/weblog/2008/01/17/bug-con-ie-6-y-livevalidation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>La forma correcta de usar window.onload</title>
		<link>http://www.danilat.com/weblog/2007/11/20/la-forma-correcta-de-usar-windowonload/</link>
		<comments>http://www.danilat.com/weblog/2007/11/20/la-forma-correcta-de-usar-windowonload/#comments</comments>
		<pubDate>Mon, 19 Nov 2007 23:18:00 +0000</pubDate>
		<dc:creator>dani</dc:creator>
				<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://www.danilat.com/weblog/2007/11/20/la-forma-correcta-de-usar-windowonload/</guid>
		<description><![CDATA[En ocasiones, necesitamos ejecutar funciones javascript al cargarse una página (validaciones, autocompletados&#8230;). Lo típico es hacerlo en el evento onload del body o poniendo las llamadas a nuestras funciones javascript dentro del código para que se vayan ejecutando mientras se carga la página, ésta sería la forma intrusiva de hacerlo, la forma no intrusiva sería [...]]]></description>
			<content:encoded><![CDATA[<p>En ocasiones, necesitamos ejecutar funciones javascript al cargarse una página (validaciones, autocompletados&#8230;).</p>
<p>Lo típico es hacerlo en el evento onload del body o poniendo las llamadas a nuestras funciones javascript dentro del código para que se vayan ejecutando mientras se carga la página, ésta sería la forma intrusiva de hacerlo, la forma no intrusiva sería utilizar window.onload.</p>
<p align="center"><strong>window.onload = mifuncion();</strong></p>
<p>Hay un problema que fácilmente nos puede surgir, cuando tenemos varias asignaciones a window.onload, ya que se ejecutará sólo la última.</p>
<p>En un principio se me ocurrió solucionarlo con una asignación común para toda la web, el problema es evidente, para una web más o menos grande llegaría a ser una macro-función, además de ser una solución nada elegante.<br />
Al final a googleando un poco, acabé encontrando la solución <a href="http://blog.roberthahn.ca/articles/2007/02/02/how-to-use-window-onload-the-right-way">en el blog de Robert Hahn</a>, donde plantea tres formas de hacerlo para <em>&#8220;que funcione&#8221;</em>, y una solución que al parecer es la ideal, simplemente es asignar a window.onload ésta función que nos devuelve una función anónima:</p>
<pre style="background: #ffffff none repeat scroll 0% 50%; color: #000000; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial">function makeDoubleDelegate(function1, function2) {
return function() {
if (function1)
function1();
if (function2)
function2();
}
}</pre>
<p>Para probarlo simplemente con éste código, podemos ver que funcina correctamente:</p>
<pre style="background: #ffffff none repeat scroll 0% 50%; color: #000000; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial">window<span style="color: #008c00">.</span>onload = makeDoubleDelegate(window<span style="color: #008c00">.</span>onload, alert('<span style="color: #008c00">1</span>'));
window<span style="color: #008c00">.</span>onload = makeDoubleDelegate(window<span style="color: #008c00">.</span>onload, alert('<span style="color: #008c00">2</span>'));
window<span style="color: #008c00">.</span>onload = makeDoubleDelegate(window<span style="color: #008c00">.</span>onload, alert('<span style="color: #008c00">3</span>'));</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.danilat.com/weblog/2007/11/20/la-forma-correcta-de-usar-windowonload/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Hijax, otro &#8220;sabor&#8221; de Ajax</title>
		<link>http://www.danilat.com/weblog/2007/10/29/hijax-otro-sabor-de-ajax/</link>
		<comments>http://www.danilat.com/weblog/2007/10/29/hijax-otro-sabor-de-ajax/#comments</comments>
		<pubDate>Mon, 29 Oct 2007 20:00:32 +0000</pubDate>
		<dc:creator>dani</dc:creator>
				<category><![CDATA[Accesibilidad]]></category>
		<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://www.danilat.com/weblog/2007/10/29/hijax-otro-sabor-de-ajax/</guid>
		<description><![CDATA[Leyendo el blog de Olga Carreras me encuentro un post explicando qué significa otro acrónimo(o palabreja;)) más, Hijax, de la que soy consciente que existe desde que Daniel Torres nos explicaba lo que iba ocurriendo en Fundamentos Web. Parece que existe una manía a poner nombres a cada &#8220;invento&#8221;, que como con Ajax no tenemos [...]]]></description>
			<content:encoded><![CDATA[<p>Leyendo el blog de Olga Carreras me encuentro <a href="http://olgacarreras.blogspot.com/2007/02/hijax.html">un post</a> explicando qué significa otro acrónimo(o palabreja;)) más, <a href="http://domscripting.com/blog/display/41">Hijax</a>, de la que soy consciente que existe desde que <a href="http://www.torresburriel.com/weblog/2007/10/03/fw2007-ajax-a-prueba-de-balas-jeremy-keith/">Daniel Torres nos explicaba</a> lo que iba ocurriendo en <a href="http://www.fundamentosweb.org/2007/index.html.es">Fundamentos Web</a>. Parece que existe una manía a poner nombres a cada &#8220;invento&#8221;, que como con Ajax no tenemos suficiente, encontramos los términos Ajaj(devolver JSON) y Ahah(devolver HTML), pues casi que me voy a adelantar y voy a acuñar Hihah y Hijaj:).</p>
<p>Pues resulta, que Hijax, es una &#8220;técnica&#8221; de uso de Ajax(y javascript en general) para realizar desarrollos accesibles, que se basa en no utilizar javascript hasta que no esté desarrollado el funcionamiento accesible, y una vez que introduzcamos el uso de javascript éste no sea intrusivo.</p>
<p>En mi opinión a raíz de lo vivido en carnes propias, es la mejor forma de enfocar un desarrollo que tenga como requisito ser accesible, ya que considero más sencillo desarrollar los efectos y añadidos a posteriori, que definir una forma accesible de uso de una aplicación sin haberlos tenido en cuenta desde el inicio, ya que puede suponer prácticamente un doble desarrollo. Y siendo egoístas, como desarrolladores, corremos el riesgo de que ese tiempo de trabajo extra no esté planificado, y luego pasa lo que pasa.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.danilat.com/weblog/2007/10/29/hijax-otro-sabor-de-ajax/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>

