<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" version="2.0">

<channel>
	<title>Ajimix.net</title>
	
	<link>http://www.ajimix.net/blog</link>
	<description>Mi vida, la programación</description>
	<lastBuildDate>Fri, 18 May 2012 17:45:43 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/ajimix" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="ajimix" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Comunicación background.js y script en extensiones de Chrome</title>
		<link>http://www.ajimix.net/blog/comunicacion-background-js-y-script-en-extensiones-de-chrome/</link>
		<comments>http://www.ajimix.net/blog/comunicacion-background-js-y-script-en-extensiones-de-chrome/#comments</comments>
		<pubDate>Fri, 18 May 2012 17:43:35 +0000</pubDate>
		<dc:creator>ajimix</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[extension]]></category>
		<category><![CDATA[google chrome]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://www.ajimix.net/blog/?p=257</guid>
		<description><![CDATA[Como comenté en una entrada anterior, en ocasiones requerimos de partes de nuestra extensión de chrome que se ejecuten en segundo plano, bien de forma constante o bien desde el inicio de Google Chrome, estas tareas las definiremos en nuestro background.js. Pero que hemos de hacer si queremos que el background.js se comunique con algún [...]]]></description>
			<content:encoded><![CDATA[<p>Como comenté en una <a href="capturar-peticiones-ajax-en-extensiones-de-chrome/">entrada anterior</a>, en ocasiones requerimos de partes de nuestra <strong>extensión de chrome</strong> que se ejecuten en <strong>segundo plano</strong>, bien de forma constante o bien desde el inicio de <strong>Google Chrome</strong>, estas tareas las definiremos en nuestro <strong>background.js</strong>.</p>
<div class="break"></div>
<p>Pero que hemos de hacer si queremos que el background.js se comunique con algún otro archivo js de nuestras extensiones? Podemos notificar a nuestro script mediante peticiones desde el <strong>background.js </strong>mediante la función <strong>sendRequest</strong> de la clase tabs.</p>
<p>Veamos un ejemplo:</p>
<pre class="brush: jscript; title: ; notranslate">
chrome.tabs.getSelected(null, function(tab) {
    chrome.tabs.sendRequest(tab.id, {
            foo: 'foo'
        }, function(response){
            console.log(response);
        }
    );
});
</pre>
<p>La primera línea ejecuta un callback con la pestaña activa como parámetro.</p>
<p>La segunda línea es la que propiamente creará un request a los scripts que tengamos activos en la pestaña que le pasemos como primer parametro &#8220;tab.id&#8221; en el caso del ejemplo. Como segundo parametro podemos pasarle datos al script y como último parametro podemos pasar una función anónima de callback tal y cono nos especifica la documentación:</p>
<pre class="brush: jscript; title: ; notranslate">chrome.tabs.sendRequest(integer tabId, any request, function responseCallback);</pre>
<div class="break"></div>
<p>Por el otro lado nuestro script integrado en la página deberá capturar nuestra petición de la siguiente manera:</p>
<pre class="brush: jscript; title: ; notranslate">
chrome.extension.onRequest.addListener(function(request) {
    if(request.foo === 'foo'){
        // Ejecutamos lo que queramos
    }
});
</pre>
<p>Tal y como nos indica la documentación de la API</p>
<pre class="brush: jscript; title: ; notranslate">chrome.extension.onRequest.addListener(function(any request, MessageSender sender, function sendResponse) {...});</pre>
<div class="break"></div>
<p>Esto nos permite una comunicación de lado a lado en las <strong>extensiones de Chrome</strong>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ajimix.net/blog/comunicacion-background-js-y-script-en-extensiones-de-chrome/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cargar css en función del tamaño de la pantalla</title>
		<link>http://www.ajimix.net/blog/cargar-css-en-funcion-del-tamano-de-la-pantalla/</link>
		<comments>http://www.ajimix.net/blog/cargar-css-en-funcion-del-tamano-de-la-pantalla/#comments</comments>
		<pubDate>Wed, 16 May 2012 13:09:37 +0000</pubDate>
		<dc:creator>ajimix</dc:creator>
				<category><![CDATA[HTML]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[css3]]></category>
		<category><![CDATA[responsive]]></category>
		<category><![CDATA[responsive design]]></category>

		<guid isPermaLink="false">http://www.ajimix.net/blog/?p=250</guid>
		<description><![CDATA[Últimamente se está poniendo muy de moda el adaptar en función del tamaño de la pantalla las páginas web para que puedan ser visualizadas de forma correcta en multitud de dispositivos. Esto se conoce comúnmente como &#8220;responsive design&#8221; o diseño que responde ya que como he comentado se adapta a la pantalla. Tenemos diferentes formas [...]]]></description>
			<content:encoded><![CDATA[<p>Últimamente se está poniendo muy de moda el adaptar en función del <strong>tamaño de la pantalla</strong> las páginas web para que puedan ser visualizadas de forma correcta en multitud de dispositivos. Esto se conoce comúnmente como &#8220;<strong>responsive design</strong>&#8221; o diseño que responde ya que como he comentado se adapta a la pantalla.</p>
<div class="break"></div>
<p>Tenemos diferentes formas de hacerlo, la mejor en mi opinión es mediante el uso de <strong><a href="http://www.w3.org/TR/css3-mediaqueries/" target="_blank">media queries</a></strong>, que nos permitirán cargar diferentes estilos en función del <strong>tamaño de dispositivo o de pantalla</strong>. Es bastante sencillo de realizar así que iré directamente a los ejemplos:</p>
<p>Supongamos que tenemos un elemento div de fondo negro que queremos que aparezca o no en función de el tamaño de dispositivos.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;div class='no-movil'&gt;&lt;/div&gt;
</pre>
<p>En la <strong>hoja de estilos</strong> css lo definiríamos de la siguiente manera</p>
<pre class="brush: css; title: ; notranslate">
@media(max-width:480px){
    .no-movil { display: none; }
}
</pre>
<p>Con esta sentencia no aparecerá en los dispositivos con la ventana del <strong>navegador</strong> con un ancho inferior a 480, pero si lo que queremos es que no aparezca en los <strong>dispositivos</strong> con ancho inferior a 480 deberemos realizarlo de la manera siguiente:</p>
<pre class="brush: css; title: ; notranslate">
@media(max-device-width:480px){
    .no-movil { display: none; }
}
</pre>
<div class="break"></div>
<p>Por último me gustaría aclarar que también es posible cargar toda una <strong>hoja de estilos</strong> únicamente cuando se cumpla cierta condición.</p>
<p>Veamos el ejemplo de el código que insertaríamos en la cabecera:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; media=&quot;screen and (max-device-width: 480px)&quot; href=&quot;estilo480.css&quot;&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ajimix.net/blog/cargar-css-en-funcion-del-tamano-de-la-pantalla/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Capturar peticiones ajax en extensiones de chrome</title>
		<link>http://www.ajimix.net/blog/capturar-peticiones-ajax-en-extensiones-de-chrome/</link>
		<comments>http://www.ajimix.net/blog/capturar-peticiones-ajax-en-extensiones-de-chrome/#comments</comments>
		<pubDate>Sat, 12 May 2012 13:40:23 +0000</pubDate>
		<dc:creator>ajimix</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[extension]]></category>
		<category><![CDATA[google chrome]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[xmlhttprequest]]></category>

		<guid isPermaLink="false">http://www.ajimix.net/blog/?p=215</guid>
		<description><![CDATA[Cuando desarrollamos una extensión para Google Chrome en la que integramos un script en alguna página para modificar el uso o funcionamiento de ella, podemos requerir la captura de ciertos eventos realizados por la página madre (en la que insertamos el script). En esta entrada, hablaremos sobre como capturar las peticiones ajax o XMLHttpRequest para reaccionar sobre [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.ajimix.net/blog/wp-content/uploads/2012/05/googleChromeExtensions.jpg"><img class="alignright  wp-image-221" title="Google chrome extensions" src="http://www.ajimix.net/blog/wp-content/uploads/2012/05/googleChromeExtensions.jpg" alt="" width="200" height="196" /></a>Cuando desarrollamos una extensión para <a href="http://www.google.es/chrome" target="_blank">Google Chrome</a> en la que integramos un <strong>script</strong> en alguna página para modificar el uso o funcionamiento de ella, podemos requerir la captura de ciertos eventos realizados por la página madre (en la que insertamos el script).</p>
<div class="break"></div>
<p>En esta entrada, hablaremos sobre como capturar las peticiones <strong>ajax</strong> o <strong>XMLHttpRequest</strong> para reaccionar sobre ellas de alguna forma en concreta, permitirlas, bloquearlas, etc.</p>
<div class="break"></div>
<p>Lo primero de todo es hacerle saber a nuestro fichero de manifiesto <a href="http://code.google.com/chrome/extensions/manifest.html" target="_blank">manifest.json</a> que queremos utilizar las llamadas a la <strong>API de extensiones</strong> de <strong>Google Chrome</strong> encargadas de capturar las peticiones <strong>request</strong>. Estas son <strong>webRequest</strong> y <strong>webRequestBlocking</strong> (en el caso de desear bloquear peticiones ajax).</p>
<div class="break"></div>
<h2>Dando permisos a la extensión</h2>
<p>Obtenemos un manifest.json básico de ejemplo de la siguiente manera:</p>
<pre class="brush: jscript; title: ; notranslate">
{
    &quot;name&quot;: &quot;Mi primera extensión&quot;,
    &quot;version&quot;: &quot;1.0&quot;,
    &quot;manifest_version&quot;: 2,
    &quot;permissions&quot;: [
        &quot;webRequest&quot;,
        &quot;webRequestBlocking&quot;,
        &quot;http://web.com/*&quot;
    ],
    &quot;background&quot;: {
    	&quot;scripts&quot;: [&quot;background.js&quot;]
    }
}
</pre>
<p>Es importante recalcar que debemos de tener un script que correrá en background (en mi ejemplo llamado background.js) que se encargará de <strong>capturar las peticiones ajax</strong>.</p>
<p>Ahora debemos decirle a la extensión de chrome que escuche atentamente a cualquier petición de la página que estamos monitorizando que haga via ajax a algún servidor via nuestro archivo background.js</p>
<div class="break"></div>
<h2>Capturando la petición</h2>
<pre class="brush: jscript; title: ; notranslate">
chrome.webRequest.onCompleted.addListener(function(details) {
    console.log(details); // Nos imprimirá los detalles de la petición
}, { urls: [&quot;http://web.com/*&quot;] });
</pre>
<p>De esta forma chrome quedará pendiente y cualquier petición que haga nuestra web host vía ajax, lanzará esta llamada. En este ejemplo en concreto, el evento se dispará al completar la petición, así lo indica &#8220;onCompleted&#8221;.<br />
Si deseas capturar la petición en cualquier otro momento, podeis hacerlo. Sencillamente buscar los <strong>diferentes eventos</strong> que se disparan en la documentación de <a href="http://code.google.com/chrome/extensions/webRequest.html" target="_blank">webRequest</a>.</p>
<div class="break"></div>
<h2>Ejemplo práctico: bloqueando peticiones ajax</h2>
<p>Vamos a imaginar que queremos hacer una extensión que bloquee todas las peticiones a los servicios tusestadisticas.com para proteger la privacidad de los usuarios que instalen nuestra extensión.</p>
<p>Primero deberemos añadir una escucha al inicio de cualquier petición ajax y para las que sean a los servidores de tusestadisticas.com, bloquearlas.</p>
<p>Veamos&#8230;</p>
<pre class="brush: jscript; title: ; notranslate">
chrome.webRequest.onBeforeRequest.addListener(
    function(details) {
        return {cancel: details.url.indexOf(&quot;://www.tusestadisticas.com/&quot;) !== -1};
    }, {urls: [&quot;*://*&quot;]}, [&quot;blocking&quot;]
);
</pre>
<div class="break"></div>
<p>Como se puede apreciar, la API de webRequest nos da juego a muchas cosas. Ahora ya es sólo cuestión de probar y jugar.</p>
<p><del>Mas adelante veremos como se comunica el archivo background.js con nuestro script para avisarle y llamar funciones.</del></p>
<p>Aquí está la nueva entrada: <a href="comunicacion-background-js-y-script-en-extensiones-de-chrome/">Comunicación background.js y script en extensiones de Chrome</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ajimix.net/blog/capturar-peticiones-ajax-en-extensiones-de-chrome/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bloquear autodetección teléfonos safari mobile</title>
		<link>http://www.ajimix.net/blog/bloquear-autodeteccion-telefonos-safari-mobile/</link>
		<comments>http://www.ajimix.net/blog/bloquear-autodeteccion-telefonos-safari-mobile/#comments</comments>
		<pubDate>Thu, 10 May 2012 18:13:07 +0000</pubDate>
		<dc:creator>ajimix</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[ipad]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[safari mobile]]></category>
		<category><![CDATA[webkit]]></category>

		<guid isPermaLink="false">http://www.ajimix.net/blog/?p=204</guid>
		<description><![CDATA[Cómo muchos de vosotros sabréis, llevo unos días peleando horas y horas con jQuery mobile para hacer una aplicación a nivel empresarial de gestión de pedidos que sea totalmente manejable desde dispositivos móbiles como iPhone, iPad o dispositivos Android así como a traves de web. &#160; En cualquier caso, hoy me he encontrado que safari mobile, detecta [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-205" title="Autodeteccion telefono safari mobile" src="http://www.ajimix.net/blog/wp-content/uploads/2012/05/safari-mobile.jpg" alt="" width="258" height="160" /></p>
<p>Cómo muchos de vosotros sabréis, llevo unos días peleando horas y horas con <a href="http://jquerymobile.com/" target="_blank">jQuery mobile</a> para hacer una aplicación a nivel empresarial de gestión de pedidos que sea totalmente manejable desde dispositivos móbiles como <strong>iPhone</strong>, <strong>iPad</strong> o dispositivos Android así como a traves de web.</p>
<p>&nbsp;</p>
<p>En cualquier caso, hoy me he encontrado que <strong>safari mobile</strong>, detecta ciertos datos como los <strong>teléfonos</strong> y las ¿fechas? (realmente no entiendo el porqué), como teléfonos y les añade un enlace automáticamente para poder realizar una llamada de forma cómoda. Podeis ver la imagen adjunta a la entrada donde se aprecia.</p>
<p>&nbsp;</p>
<p>En fin, como siempre hay una forma de deshabilitar a nivel global en toda la página y es añadiendo la siguiente línea a la cabecera &lt;head&gt; de la web.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;meta name=&quot;format-detection&quot; content=&quot;telephone=no&quot;&gt;
</pre>
<p>Con esto será suficiente para deshabilitar la <strong>autodetección de teléfonos</strong> en nuestros <strong>iPhone</strong> e <strong>iPad</strong> (<strong>safari mobile</strong>).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ajimix.net/blog/bloquear-autodeteccion-telefonos-safari-mobile/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Bloquear zoom ipad iphone web</title>
		<link>http://www.ajimix.net/blog/bloquear-zoom-ipad-iphone-web/</link>
		<comments>http://www.ajimix.net/blog/bloquear-zoom-ipad-iphone-web/#comments</comments>
		<pubDate>Mon, 07 May 2012 18:12:01 +0000</pubDate>
		<dc:creator>ajimix</dc:creator>
				<category><![CDATA[HTML]]></category>
		<category><![CDATA[ipad]]></category>
		<category><![CDATA[ipod]]></category>

		<guid isPermaLink="false">http://www.ajimix.net/blog/?p=199</guid>
		<description><![CDATA[Hoy traigo un snippet que nos puede ser muy útil cuando deseemos bloquear la posibilidad de hacer zoom en nuestra página web (teniendo en cuenta que puede ser un gran obstáculo para la accesibilidad). Es realmente simple y consiste en añadir esta línea a la parte del &#60;head&#62; de nuestra página web: Espero que os [...]]]></description>
			<content:encoded><![CDATA[<p>Hoy traigo un snippet que nos puede ser muy útil cuando deseemos <strong>bloquear</strong> la posibilidad de hacer <strong>zoom</strong> en nuestra página web (teniendo en cuenta que puede ser un <strong>gran obstáculo para la accesibilidad</strong>).</p>
<p>Es realmente simple y consiste en añadir esta línea a la parte del &lt;head&gt; de nuestra página web:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no&quot;&gt;
</pre>
<p>Espero que os sirva.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ajimix.net/blog/bloquear-zoom-ipad-iphone-web/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Offerum opiniones estafadores</title>
		<link>http://www.ajimix.net/blog/offerum-opiniones-estafadores/</link>
		<comments>http://www.ajimix.net/blog/offerum-opiniones-estafadores/#comments</comments>
		<pubDate>Fri, 04 May 2012 15:05:13 +0000</pubDate>
		<dc:creator>ajimix</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[estafa]]></category>
		<category><![CDATA[offerum]]></category>
		<category><![CDATA[opinion]]></category>
		<category><![CDATA[opiniones]]></category>

		<guid isPermaLink="false">http://www.ajimix.net/blog/?p=195</guid>
		<description><![CDATA[Imagino que todos conoceréis alguna de estas páginas que han proliferado en los últimos años como la espuma, en las que supuestamente, podemos conseguir durante un corto periodo de tiempo, un artículo o servicio por un precio bastante mas reducido del habitual. &#160; Siempre ha corrido por mi pensamiento, por lo que siempre quise escribir mi opinión [...]]]></description>
			<content:encoded><![CDATA[<p>Imagino que todos conoceréis alguna de estas páginas que han proliferado en los últimos años como la espuma, en las que supuestamente, podemos conseguir durante un corto periodo de tiempo, un artículo o servicio por un precio bastante mas reducido del habitual.</p>
<p>&nbsp;</p>
<p>Siempre ha corrido por mi pensamiento, por lo que siempre quise escribir mi <strong>opinión</strong> respecto a esto, que estas páginas se aprovechaban de su <strong>gran afluencia de visitantes</strong> que desesperados por la crisis o quizas por ahorrarse unos euros y poder disfrutar de algo de ocio, engañaban a sus usuarios haciendo crecer el precio real sin oferta de los productos o servicios.</p>
<p>Y así es, ya que casualmente, he podido comprobar que a fecha de 4 de mayo de 2012, <a href="http://www.offerum.com/" target="_blank">Offerum</a> ofrece entre sus <strong>ofertas</strong>, una que en mi <strong>opinión</strong> no es demasiado digna de ser considerada oferta, ya que ofrece un <strong>cupón</strong> para un buffet libre (puede verse <a href="http://www.offerum.com/barcelona/decenas-de-manjares-para-repetir-buffet-libre-en-restaurante-el-gloton-20237" target="_blank">aquí</a>), a un precio que en mi opinión no es demasiado &#8220;oferta&#8221;.</p>
<p>Hasta aquí todo correcto, <strong>Offerum</strong>, ofrece <strong>cupones</strong> para el buffet, podemos leer diferentes <strong>opiniones y comentarios</strong> supuestamente reales hablando de la maravillosa calidad del buffet (dudo de esas opiniones&#8230;), pero si nos dirijimos a la propia <a href="http://www.restauranteelgloton.com/" target="_blank">página web del restaurante</a>, nos daremos cuenta de la estafa.</p>
<p>Podemos ver <a href="http://www.restauranteelgloton.com/horarios/" target="_blank">aquí</a>, que el mismo buffet que <strong>Offerum</strong> nos ofrece por un precio de oferta de 9,90€ podemos consumirlo por precios que van desde los 8,50€ para los días laborables, hasta los 14€ para fines de semana y festivos, que se aleja de los supuestos 17€ que nos dice Offerum ser su precio habitual.</p>
<p>&nbsp;</p>
<h2>Resumiendo mi opinión</h2>
<p>Pienso, que no deberíamos creernos nunca lo que nos dicen estas páginas sin antes comprobarlo si que no quereis caer en mano de estafadores.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ajimix.net/blog/offerum-opiniones-estafadores/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Loading en ajax, notificar al usuario</title>
		<link>http://www.ajimix.net/blog/loading-en-ajax-notificar-al-usuario/</link>
		<comments>http://www.ajimix.net/blog/loading-en-ajax-notificar-al-usuario/#comments</comments>
		<pubDate>Wed, 02 May 2012 12:45:05 +0000</pubDate>
		<dc:creator>ajimix</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[loading]]></category>

		<guid isPermaLink="false">http://www.ajimix.net/blog/?p=188</guid>
		<description><![CDATA[Uno de los errores que suelen cometer los usuarios que empiezan en el mundo del javascript y especialmente en las peticiones asíncronas via ajax, es el de dejar al desconocimiento del usuario final, las cargas de contenido asíncrono, ya sea por falta de experiencia o bien porque en las pruebas locales los contenido han cargado [...]]]></description>
			<content:encoded><![CDATA[<p>Uno de los errores que suelen cometer los usuarios que empiezan en el mundo del <strong>javascript</strong> y especialmente en las <strong>peticiones asíncronas via ajax</strong>, es el de dejar al desconocimiento del usuario final, las <strong>cargas de contenido asíncrono</strong>, ya sea por falta de experiencia o bien porque en las pruebas locales los contenido han cargado con suma rapidez.</p>
<p>&nbsp;</p>
<p>Pero que pasaría si en algún momento nuestra conexión a internet es mas lenta de lo normal, o si por ejemplo el servidor tarda mas de lo normal en responder?</p>
<p>Si no notificamos al usuario que la página está cargando X contenido, lo mas probable es que el usuario haga clics recurridamente donde desea entrar (provocando multitud de peticiones al servidor) o que acabe abandonando la página. Es por ello que siempre insisto que se notifique al usuario cuando algo está cargando para que esté al corriente y espere a que el contenido aparezca.</p>
<p>&nbsp;</p>
<p>Una de las formas mas fáciles, rápidas y sencillas de hacerlo es añadiendo una clase <strong>CSS</strong> que posteriormente será eliminada.</p>
<p>Veamos el ejemplo práctico con <strong>jQuery</strong>.</p>
<pre class="brush: jscript; title: ; notranslate">
$('#cargarContenido').click(function(){
    $('#resultado').addClass('loading')
                   .load('granPagina.html', function(){
                        $(this).removeClass('loading');
                   });
});
</pre>
<p>Y deberemos tambien añadir una línea a nuestro css que defina el estilo del loading, en nuestro ejemplo simplemente añadiremos un bonito gif animado indicando que algo está cargando:</p>
<pre class="brush: css; title: ; notranslate">
.loading {
    background: url(loadingImage.gif) no-repeat center center;
}
</pre>
<p>Como veis, es una solución simple y sencilla de aplicar que mejorará las peticiones en ajax de cara al usuario que nunca se sentirá desatendido.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ajimix.net/blog/loading-en-ajax-notificar-al-usuario/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Asana API PHP class wrapper</title>
		<link>http://www.ajimix.net/blog/asana-api-php-class-wrapper/</link>
		<comments>http://www.ajimix.net/blog/asana-api-php-class-wrapper/#comments</comments>
		<pubDate>Tue, 24 Apr 2012 20:31:17 +0000</pubDate>
		<dc:creator>ajimix</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[api rest]]></category>
		<category><![CDATA[asana]]></category>
		<category><![CDATA[class]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.ajimix.net/blog/?p=181</guid>
		<description><![CDATA[Desde la salida este fin de semana de la API de Asana, me he puesto manos a la obra y he realizado una pequeña clase que envuelve toda la API para hacer mas fácil el trabajo mediante PHP. Podeis verlo en GitHub: https://github.com/ajimix/asana-api-php-class La clase se encarga de todo el tema de peticiones a la API REST [...]]]></description>
			<content:encoded><![CDATA[<p>Desde la salida este fin de semana de la <strong>API de Asana</strong>, me he puesto manos a la obra y he realizado una pequeña clase que envuelve toda la API para hacer mas fácil el trabajo mediante <strong>PHP</strong>.</p>
<p>Podeis verlo en GitHub: <a href="https://github.com/ajimix/asana-api-php-class" target="_blank">https://github.com/ajimix/asana-api-php-class</a></p>
<p>La clase se encarga de todo el tema de peticiones a la <strong>API REST</strong> de Asana devolviendo un string en JSON mediante sencillas funciones. Dejo un par de ejemplos, podeis ver alguno mas en la página de github o descargando la propia clase.</p>
<h2>Ejemplo API creación tarea</h2>
<pre class="brush: php; title: ; notranslate">
$asana-&gt;createTask(
    array(
        &quot;workspace&quot; =&gt; &quot;123456&quot;, // ID del worspace
        &quot;name&quot; =&gt; &quot;Hello World!&quot;, // El nombre de la tarea
        &quot;assignee&quot; =&gt; &quot;12234&quot;, // Asignamos la tarea a...
        &quot;followers&quot; =&gt; array(&quot;324234&quot;, &quot;2334545&quot;) // Finalmente añadimos a un par de miembros a que sigan la tarea
    )
);
</pre>
<h2>Ejemplo API buscar tareas asignadas a un proyecto</h2>
<p>La siguiente función nos devolverá las tareas contenidas dentro del proyecto 1234</p>
<pre class="brush: php; title: ; notranslate">
$asana-&gt;getTasksByFilter(array(&quot;project&quot; =&gt; &quot;1234&quot;));
</pre>
<p>Para ambos ejemplos debemos crear primeramente el objeto $asana</p>
<pre class="brush: php; title: ; notranslate">$asana = new Asana(&quot;API_KEY&quot;);</pre>
<p>Recordar que podeis ver mas ejemplos en la <a href="https://github.com/ajimix/asana-api-php-class" target="_blank">web del proyecto</a>.</p>
<p>Y por último recordar que la clase trabaja bajo la API de Asana, ver <a href="http://developer.asana.com/documentation/" target="_blank">documentación de la API</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ajimix.net/blog/asana-api-php-class-wrapper/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Asana API ejemplo PHP Hello World</title>
		<link>http://www.ajimix.net/blog/asana-api-ejemplo-php-hello-world/</link>
		<comments>http://www.ajimix.net/blog/asana-api-ejemplo-php-hello-world/#comments</comments>
		<pubDate>Sun, 22 Apr 2012 18:05:28 +0000</pubDate>
		<dc:creator>ajimix</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[asana]]></category>
		<category><![CDATA[gestion]]></category>
		<category><![CDATA[hello world]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programacion]]></category>
		<category><![CDATA[tareas]]></category>

		<guid isPermaLink="false">http://www.ajimix.net/blog/?p=172</guid>
		<description><![CDATA[Justo esta semana ha salido la API para la plataforma de gestión de tareas en grupo Asana. Para quien no lo conozca, debo decir que creo que es un gestor de tareas mas que interesante ya que permite la gestión de forma muy sencilla e intuitiva la gestión de tareas y proyectos para un equipo [...]]]></description>
			<content:encoded><![CDATA[<p>Justo esta semana ha salido la <strong>API</strong> para la plataforma de gestión de tareas en grupo <a href="http://www.asana.com" target="_blank">Asana</a>. Para quien no lo conozca, debo decir que creo que es un gestor de tareas mas que interesante ya que permite la gestión de forma muy sencilla e intuitiva la <strong>gestión de tareas</strong> y proyectos para un equipo de trabajo.</p>
<p>Como decía, justo esta semana ha aparecido la <strong>API</strong> que permite gestionar algunos aspectos de <strong>Asana</strong> desde nuestros proyectos. Como podemos ver en la <a href="http://developer.asana.com/documentation/" target="_blank">documentación</a>, crear una nueva tarea, es realmente sencillo gracias a la API <strong>REST</strong>. En la documentación podemos ver un ejemplo realizado en Ruby. He decidido pasar el mismo ejemplo a <strong>PHP</strong> y creo que debo compartirlo con vosotros.</p>
<pre class="brush: php; title: ; notranslate">
// Config
$timeout = 10;
$url = &quot;https://app.asana.com/api/1.0/tasks&quot;; // La URL para la petición
$apiKey = &quot;xxxxxxxxxxxxxxxxxxxxxx:&quot;; // La llave API

// Datos para la nueva tarea
$workspaceId = &quot;999999999&quot;; // El ID del workspace donde deseemos añadir la tarea
$taksName = &quot;Hello World!&quot;; // El titulo de la tarea
$assignee = &quot;jefe@granempresa.com&quot;; // A quien le asignaremos la tarea

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); // No imprimimos el resultado, lo guardamos en variable
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
curl_setopt($curl, CURLOPT_FAILONERROR, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // No verificamos la conexion SSL
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); //         &quot;&quot;           &quot;&quot;
curl_setopt($curl, CURLOPT_USERPWD, $apiKey);
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($curl, CURLOPT_HTTPHEADER, array(&quot;Content-Type: application/json&quot;)); // Ei! Enviaremos en formato JSON <img src='http://www.ajimix.net/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> 

//curl_setopt($curl, CURLOPT_VERBOSE, true); // Para pruebas, tests

// Construimos un array para posteriormente transformarlo a JSON
$data = array(
	&quot;data&quot; =&gt; array(
	    &quot;workspace&quot; =&gt; $workspaceId,
	    &quot;name&quot; =&gt; $taksName,
	    &quot;assignee&quot; =&gt; $assignee
	)
);

$data = json_encode($data);

curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);

try {
    $return = curl_exec($curl);
    //echo &quot;&lt;pre&gt;&quot;; print_r(curl_getinfo($curl)); echo &quot;&lt;pre&gt;&quot;;  // Tests
} catch(Exception $ex){
    // echo &quot;&lt;br&gt;cURL error num: &quot;.curl_errno($curl); // Tests
    // echo &quot;&lt;br&gt;cURL error: &quot;.curl_error($curl);  // Tests
    e(&quot;Error en el proceso cURL&quot;);
    $return = null;
}

curl_close($curl);

echo $return;
</pre>
<p>Creo que leyendo el código queda bastante claro, ademas de los comentarios que he incluido.<br />
Si queréis hacer tests, sólo debéis descomentar las líneas que así lo indican.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ajimix.net/blog/asana-api-ejemplo-php-hello-world/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Javascript sin punto y coma</title>
		<link>http://www.ajimix.net/blog/javascript-sin-punto-y-coma/</link>
		<comments>http://www.ajimix.net/blog/javascript-sin-punto-y-coma/#comments</comments>
		<pubDate>Wed, 18 Apr 2012 12:58:05 +0000</pubDate>
		<dc:creator>ajimix</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[punto y coma]]></category>
		<category><![CDATA[semicolons]]></category>

		<guid isPermaLink="false">http://www.ajimix.net/blog/?p=161</guid>
		<description><![CDATA[Uno de los temas que ha estado en pleno rodaje estos días ha sido el que gira entorno a poner o no el carácter punto y coma &#8220;;&#8221; al final de las sentencias javascript. La discusión se inició en base a un mensaje en github debido a que el bootstrap de twitter daba problemas de [...]]]></description>
			<content:encoded><![CDATA[<p>Uno de los temas que ha estado en pleno rodaje estos días ha sido el que gira entorno a poner o no el carácter <strong>punto y coma</strong> &#8220;;&#8221; al <strong>final</strong> de las sentencias <strong>javascript</strong>.</p>
<p>La discusión se inició en base a un mensaje en <a href="http://www.github.com">github</a> debido a que el bootstrap de twitter daba problemas de minificación al quitar los <strong>punto y coma</strong> de los finales de línea en los ficheros <strong>javascript</strong>. Se puede ver la discusión en el siguiente enlace: <a href="https://github.com/twitter/bootstrap/issues/3057">https://github.com/twitter/bootstrap/issues/3057</a></p>
<p>Ahora bien, aquí viene la pregunta,</p>
<p>&nbsp;</p>
<h2>Javascript obliga a usar punto y coma al final de línea?</h2>
<p>La respuesta es <strong>NO</strong></p>
<p>El lenguaje Javascript, un dialecto de <a href="http://www.ecmascript.org/">ECMAScript</a>, fue creado en su día para dotar de tecnología y dinamismo a las webs, si bien es un lenguaje interpretado, de la opción de finalizar o no las sentencias con punto y coma.</p>
<p>Por tanto tendremos que&#8230;</p>
<pre class="brush: jscript; title: ; notranslate">
var foo = 'test'
console.log(foo)
</pre>
<p>Es lo mismo que&#8230;</p>
<pre class="brush: jscript; title: ; notranslate">
var foo = 'test';
console.log(foo);
</pre>
<p>Pero bien, no siempre es todo oro lo que reluce. Ya que en numerosas ocasiones, nuestro código no funcionaría o simplemente no obtendriamos el mismo resultado.</p>
<p>Veamos algunos ejemplos</p>
<pre class="brush: jscript; title: ; notranslate">
// Lo siguiente nos lanzará un error
var foo = 'hola'
('test' + '1234').toString()
// Ya que Javascript intentará ejecutar lo siguiente...
var foo = 'hola'('test' + '1234').toString()
// Y 'hola' no es una funcion
</pre>
<pre class="brush: jscript; title: ; notranslate">
// En este caso nos pasará algo parecido ya que algo no definido, intentará ejecutar una función y si no está definido no podrá hacerlo...
var foo = function(){}
(function(){
    console.log(1)
})()
</pre>
<p>&nbsp;<br />
Como hemos podido ver, si que es posible programar en <strong>Javascript</strong> sin hacer uso de el <strong>punto y coma final</strong>, siempre en cuando tengamos presente casos como los mostrados arriba, pero en mi opinión, creo que no cuesta nada acostumbrarse a hacerlo con punto y coma y así evitarás futuros problemas que puedan surgir.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ajimix.net/blog/javascript-sin-punto-y-coma/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

