<?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>Chuso! &#187; javasctipt</title>
	<atom:link href="http://chusete.es/category/desarrollo/javasctipt/feed/" rel="self" type="application/rss+xml" />
	<link>http://chusete.es</link>
	<description>A la tercera va la vencida</description>
	<lastBuildDate>Thu, 17 Nov 2011 19:44:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Introducción a la programación en Facebook III</title>
		<link>http://chusete.es/2011/09/18/introduccion-a-la-programacion-en-facebook-iii/</link>
		<comments>http://chusete.es/2011/09/18/introduccion-a-la-programacion-en-facebook-iii/#comments</comments>
		<pubDate>Sun, 18 Sep 2011 00:50:00 +0000</pubDate>
		<dc:creator>chusete</dc:creator>
				<category><![CDATA[desarrollo]]></category>
		<category><![CDATA[javasctipt]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[graph api]]></category>
		<category><![CDATA[sdk javascript]]></category>

		<guid isPermaLink="false">http://chusete.es/?p=1161</guid>
		<description><![CDATA[Tercera parte de esta guía de introducción a la programación de aplicaciones en Facebook. Si seguiste la primera y la segunda parte, a estas alturas ya le habrás perdido el medio a muchos de los conceptos clave (tipos de aplicaciones, SDKs, Social Plugins, Open Graph, XFBML, Insights). Pero hay otros conceptos igualmente importantes que todavía [...]]]></description>
			<content:encoded><![CDATA[<p><img class="aligncenter size-full wp-image-1176" title="photos-facebook-f8-developers-conference-2008_1-550x331" src="http://chusete.es/wp-content/uploads/2011/09/photos-facebook-f8-developers-conference-2008_1-550x331.jpg" alt="" width="100%" />Tercera parte de esta guía de introducción a la programación de aplicaciones en Facebook. Si seguiste la <a href="/2011/09/13/introduccion-a-la-programacion-en-facebook/">primera</a> y la <a href="/2011/09/16/introduccion-a-la-programacion-facebook-ii/">segunda</a> parte, a estas alturas ya le habrás perdido el medio a muchos de los conceptos clave (tipos de aplicaciones, SDKs, Social Plugins, Open Graph, XFBML, Insights). Pero hay otros conceptos igualmente importantes que todavía no conocemos. Hoy vamos a tratar la autenticación OAuth, el SDK de JavaScript a fondo, y veremos cómo crear diálogos.</p>
<p><span id="more-1161"></span></p>
<h2>Paso 1 &#8211; Autenticación</h2>
<p>Vamos a añadir un sistema de autenticación mediante el Social Plugin &#8216;Login Button&#8217;, el diálogo OAuth, y el protocolo de autenticación OAuth. No te asustes, pues tras tanta palabreja se esconde una única línea de código HTML <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<div class="note">
<h3>OAuth</h3>
<p><a href="http://es.wikipedia.org/wiki/OAuth">OAuth</a> es un protocolo estándar que permite realizar autenticación segura contra una determinada API. Facebook en concreto se ciñe al estándar <a href="http://oauth.net/2/">OAuth 2.0</a>. Gracias a las herramientas que nos ofrece Facebook, no será necesario que conozcamos los entresijos de este protocolo, pero como siempre, sí es muy recomendable conocerlo.</p>
</div>
<p>En primer lugar, vamos a crear el <a href="https://developers.facebook.com/docs/reference/plugins/login/">Login Button</a>. Como ya sabemos, accedemos a la página del plugin, completamos el formulario, y obtenemos su código HTML, que será similar a éste:</p>
<pre name="code" class="html">&lt;div class="fb-login-button" data-show-faces="false" data-width="200" data-max-rows="1"&gt;&lt;/div&gt;</pre>
<p>Con sólo poner eso, ya tendremos el Login Button <a href="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-17-a-las-01.55.56.png"><img class="alignnone size-full wp-image-1162" title="Captura de pantalla 2011-09-17 a la(s) 01.55.56" src="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-17-a-las-01.55.56.png" alt="" width="71" height="23" /></a>. ¿Y qué ocurrirá cuando lo pulsemos? Se desplegará automáticamente un <a href="http://developers.facebook.com/docs/reference/dialogs/oauth/">diálogo OAuth</a> (¿recuerdas los diálogos? Hablamos sobre ellos en la <a href="/2011/09/13/introduccion-a-la-programacion-en-facebook/">primera parte</a>) que nos solicitará permiso para que la aplicación pueda acceder a nuestra información básica:</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-17-a-las-01.54.41.png"><img class="aligncenter size-medium wp-image-1163" title="Captura de pantalla 2011-09-17 a la(s) 01.54.41" src="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-17-a-las-01.54.41-300x183.png" alt="" width="300" height="183" /></a>Con esto quizás sea suficiente. Pero vamos a enriquecerlo un poco, y en lugar de solicitar sólo la información básica, vamos a pedir permisos también para poder publicar nuevas noticias en su muro. Si recuerdas, en el apartado &#8220;Autenticación y permisos&#8221; de la primera parte de esta guía, hablamos de los distintos tipos de permisos. Puedes volver a consultar la <a href="http://developers.facebook.com/docs/reference/api/permissions/">lista completa</a> de todos los que hay disponibles. En concreto el permiso para publicar en el muro se llama &#8216;publish_stream&#8217;. Para solicitarlo, debemos actualizar el código que genera el Loggin Button añadiendo el atributo &#8216;scope&#8217; (puedes ver más sobre los atributos de Login Button en <a href="https://developers.facebook.com/docs/reference/plugins/login/">su documentación</a>). Nos quedaría así:</p>
<pre name="code" class="html">&lt;div class="fb-login-button" data-show-faces="false" data-width="200" data-max-rows="1" scope="publish_stream" &gt;&lt;/div&gt;</pre>
<p>Y el nuevo diálogo OAuth:</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-17-a-las-02.08.36.png"><img class="aligncenter size-medium wp-image-1164" title="Captura de pantalla 2011-09-17 a la(s) 02.08.36" src="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-17-a-las-02.08.36-300x181.png" alt="" width="300" height="181" /></a></p>
<p>Como vemos, ha funcionado correctamente, y ahora también solicita permisos para publicar en el muro. <a href="http://chusete.es/facebook/step2_1.html">Ver ejemplo</a>.</p>
<div class="note">
<h3>Atributo &#8216;scope&#8217;</h3>
<p>Al código HTML que de define el Login Button le hemos añadido un atributo llamado &#8216;scope&#8217; en el que podemos añadir una lista de permisos, de entre todos los disponibles, separados por comas. Estos permisos serán los que se soliciten cuando se despliegue el diálogo OAuth.</p>
<p>Mientras se escribe esta guía, en la documentación oficial del Login Button no hay mención a un atributo llamado &#8216;scope&#8217;. Sin embargo, sí hablan del atributo &#8216;perms&#8217;. Realmente son el mismo, pero para guardar coherencia con el estándar OAuth 2, le han cambiado el nombre a &#8216;scope&#8217;.</p>
</div>
<h2>Paso 2 &#8211; Conocer el SDK JavaScript</h2>
<p>Hasta ahora no hemos usado directamente el SDK de JavaScript. Únicamente lo hemos cargado indicándole algunos valores, como por ejemplo que renderice automáticamente todos los objetos XFBML (gracias a eso hemos podido incluir los Social Plugins).</p>
<p>Vamos a revisar algunos métodos que nos van a ser especialmente útiles para nuestra demo (recuerda que puedes consultar la documentación completa del SDK de JavaScript en <a href="http://developers.facebook.com/docs/reference/javascript/">http://developers.facebook.com/docs/reference/javascript/</a>):</p>
<h3><a href="http://developers.facebook.com/docs/reference/javascript/FB.api/">FB.api</a></h3>
<p>Este método es el que nos permitirá realizar consultas al <a href="http://developers.facebook.com/docs/api">Graph API</a>, que como vimos en la primera parte, es la herramienta donde todos los objetos de Facebook (personas, páginas, imágenes, etc.) están interconectados, y a la que podemos invocar para realizar consultas o modificaciones. Este método acepta 4 parámetros:</p>
<ol>
<li><strong>path</strong> - String con la ruta al API.</li>
<li><strong>method</strong> - Tipo de petición (GET, POST o DELETE).</li>
<li><strong>params</strong> - Objeto con los parámetros de la consulta (si los necesitara).</li>
<li><strong>cb</strong> - Función callback.</li>
</ol>
<p>Usualmente sólo serán necesarios <em>path</em> y <em>cb</em>.</p>
<h3><a href="http://developers.facebook.com/docs/reference/javascript/FB.getLoginStatus/">FB.getLoginStatus</a></h3>
<p>Permite determinar si el usuario ha iniciado sesión y está conectado con nuestra aplicación. Acepta dos parámetros:</p>
<ol>
<li><strong>cb</strong> - Función callback con el parámetro &#8216;response&#8217;.</li>
<li><strong>force</strong> - Booleano que obligar a recargar el estado de login.</li>
</ol>
<p>Cuando se invoca a este método, se realiza una consulta HTTP que devuelve el objeto &#8216;response&#8217; de la función callback. Este objeto tiene la siguiente estructura:</p>
<pre name="code" class="javascript">{
    status: 'connected',
    authResponse: {
        accessToken: '...',
        expiresIn:'...',
        signedRequest:'...',
        userID:'...'
    }
}</pre>
<p>Si el objeto response contiene un objeto authResponse, sabremos con certeza que el usuario ha iniciado sesión y que está conectado a nuestra aplicación. Los campos accessToken y userID serán muy útiles para hacer llamadas a la API de Graph API. Pero no te preocupes por esto, ya que el SDK JavaScript se encarga de hacer todas las gestiones por nosotros como luego veremos sin necesidad de manejar nosotros esos parámetros <img src='http://chusete.es/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<h3><a href="http://developers.facebook.com/docs/reference/javascript/FB.getSession/">FB.getAuthResponse</a></h3>
<p>Su funcionamiento es equivalente al del método FB.getLoginStatus. La única diferencia es que, en lugar de devolver un objeto response, sólo devuelve su campo authResponse. Es decir, llamaremos a FP.getAuthResponse cuando tengamos la certeza de que el usuario ha iniciado sesión (y está conectado a nuestra aplicación) y queramos obtener información acerca de la sesión.</p>
<h3><a href="http://developers.facebook.com/docs/reference/javascript/FB.init/">FB.init</a></h3>
<p>Este es el único método que hemos invocado directamente hasta ahora. Se encarga de inicializar el SDK. Acepta un único parámetro, options, de tipo objeto, que incluye todas las propiedades que queramos establecer. En concreto, hemos usado estas propiedades (existen más):</p>
<ul>
<li><strong>appId</strong> &#8211; String con el ID público de nuestra aplicación.</li>
<li><strong>status</strong> &#8211; Booleano que indica si se debe o no comprobar el estado.</li>
<li><strong>cookie</strong> &#8211; Booleano que habilita o deshabilita el soporte para la cookie. Ésta podrá usarse posteriormente para que, desde el servidor, por ejemplo en PHP, se realicen peticiones al API.</li>
<li><strong>xfbml</strong> &#8211; Booleano que indica si se deben o no renderizar los objetos de tipo XFBML disponibles en la página. Gracias a esto, se han generado automáticamente hasta ahora los social plugins que hemos definido.</li>
<li><strong>channelURL</strong> &#8211; String con la URL del fichero channel.html. Usándolo se evitan algunos errores. Consulta la documentación de este método para saber más.</li>
<li><strong>oauth</strong> &#8211; Booleano que habilita o deshabilita soporte para OAuth 2.0. Tenlo siempre a true, pues muy pronto sólo se permitirá autenticación OAuth 2.0.</li>
</ul>
<h3><a href="http://developers.facebook.com/docs/reference/javascript/FB.login/">FB.login</a></h3>
<p>Este método se encarga de gestionar el login por nosotros. Es decir, renderiza el diálogo OAuth con los permisos necesarios, y gestiona la respuesta devuelta por éste. No lo vamos a invocar directamente, pero ten en cuenta que el Login Button por debajo utiliza este método.</p>
<p>Tan solo acepta dos parámetros:</p>
<ol>
<li><strong>cb</strong> - Función callback para gestionar la respuesta del usuario.</li>
<li><strong>opts</strong> - Objeto para modificar el comportamiento del login. Tan solo tiene una propiedad, &#8216;scope&#8217;, que como vimos más arriba acepta un string de los permisos que solicitamos, separados por coma.</li>
</ol>
<h3><a href="http://developers.facebook.com/docs/reference/javascript/FB.logout/">FB.logout</a></h3>
<p>Cierra la sesión del usuario. Sólo acepta un parámetro:</p>
<ol>
<li><strong>cb</strong> - Función callback para gestionar el cierre de sesión.</li>
</ol>
<h3><a href="http://developers.facebook.com/docs/reference/javascript/FB.ui/">FB.ui</a></h3>
<p>Es el responsable de renderizar por nosotros los diálogos. Ya lo hemos visto en funcionamiento cuando hemos pulsado el Login Button y se ha desplegado el diálogo OAuth. Pero, por supuesto, también podremos invocar a mano este método siempre que deseemos mostrar cualquier otro diálogo.</p>
<p>Acepta dos parámetros:</p>
<ol>
<li><strong>params</strong> - Objeto con todas las propiedades de configuración. Cada diálogo tiene sus propias propiedades (en la documentación de cada uno podrás conocerlas). Además, hay dos propiedades globales a todos los diálogos:</li>
<ol>
<li><strong>method</strong> - String con el nombre del diálogo que se desea mostrar. Obligatorio.</li>
<li><strong>display</strong> - String que indica la forma en que se mostrará el diálogo, por ejemplo &#8216;popup&#8217; . Opcional.</li>
</ol>
<li><strong>cb</strong> - Función callback para manejar la respuesta.</li>
</ol>
<h3><a href="http://developers.facebook.com/docs/reference/javascript/FB.Event.subscribe/">FB.Event.subscribe</a></h3>
<p>JavaScript es un lenguaje dirigido por eventos. Siguiendo este paradigma, el SDK JavaScript genera una serie de eventos a los que podemos suscribirnos para ejecutar una función callback. Este método acepta dos parámetros:</p>
<ol>
<li><strong>name</strong> &#8211; String con el nombre del evento al que nos queremos suscribir.</li>
<li><strong>fb</strong> &#8211; Función callback que se ejecutará cuando se dispare el evento.</li>
</ol>
<p>Entre los posibles eventos están <em>auth.login</em>, <em>auth.authResponseChange</em>, <em>auth.statusChange</em>, <em>auth.logout</em> además de otros muchos. Algunos de estos eventos generan un objeto que se pasará como parámetro a su función callback. Revisa la documentación para conocer más detalles.</p>
<p>Del mismo modo que nos podemos suscribir a un evento, también nos podemos desuscribir de él, mediante el método <a href="http://developers.facebook.com/docs/reference/javascript/FB.Event.unsubscribe/">FB.Event.unsubscribe</a>.</p>
<h3><a href="http://developers.facebook.com/docs/reference/javascript/FB.XFBML.parse/">FB.XFBML.parse</a></h3>
<p>Si bien en la demo no vamos a invocar este método, convine conocerlo, pues se ejecuta igualmente. En las propiedades de inicialización del SDK establecimos el valor <em>xfbml</em> a true. Esto significa que será el método FB.init el que llame a FB.XFBML.parse automáticamente por nosotros. Si no fuera así, lo podríamos invocar a mano con los siguientes parámetros:</p>
<ol>
<li><strong>dom</strong> &#8211; Elemento DOM raíz a partir del cual se parsearán todos sus hijos XFBML.</li>
<li><strong>cb</strong> &#8211; Función callback.</li>
</ol>
<h3>Resto de métodos</h3>
<p>Todavía quedan algunos métodos del SDK JavaScript. Dos de ellos (<a href="http://developers.facebook.com/docs/reference/javascript/FB.Data.query/">FB.Data.query</a> y <a href="http://developers.facebook.com/docs/reference/javascript/FB.Data.waitOn/">FB.Data.waitOn</a>) no los hemos visto, ya que quedarán obsoletos a partir del 1 de enero de 2012 (su comportamiento se puede llevar a cabo mediante FB.api). El resto de métodos tratan sobre canvas; es decir, para gestionar aspectos gráficos relacionados con el elemento iframe donde se ubican las aplicaciones que se empotran en la página de Facebook. Estos métodos sobre canvas los veremos en la siguiente parte.</p>
<h2>Paso 3 &#8211; Juntándolo todo</h2>
<p>Volviendo a nuestra demo, hemos visto que ésta ya nos permite autenticarnos. Pero esto por sí solo no es algo muy útil. Por eso ahora queremos que haga más cosas. En concreto:</p>
<ul>
<li>Queremos que cuando el usuario haya iniciado sesión, ya no se muestre el Login Button.</li>
<li>Cuando haya iniciado sesión, se mostrará un botón para cerrar sesión.</li>
<li>Además, consultaremos al Graph API algunos datos del usuario para mostrar su nombre y su avatar.</li>
<li>Añadiremos un botón que publicará automáticamente una historia en su muro.</li>
<li>Mostraremos un diálogo para invitar a nuestros amigos a usar la aplicación.</li>
<li>De paso, y por simplificar, vamos a eliminar el plugin Live Stream y el plugin del botón &#8220;Me gusta&#8221;.</li>
</ul>
<p>¿Parece mucho? Vas a ver qué sencillo es <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Añadimos este código HTML:</p>
<pre name="code" class="html">    &lt;div id="user-box" style="text-align:center; display:none;"&gt;
        &lt;img id="image"/&gt;
        &lt;div id="name"&gt;&lt;/div&gt;
        &lt;a href="#" id="logout" onclick="userLogout()"&gt;Cerrar sesión&lt;/a&gt; &lt;br /&gt;
        &lt;a href="#" id="publish" onclick="publishStream()"&gt;Publicar en el muro&lt;/a&gt; &lt;br /&gt;
        &lt;a href="#" id="request" onclick="requestDialog()"&gt;Invitar a amigos&lt;/a&gt;
    &lt;/div&gt;</pre>
<p>Simplemente es un contenedor div, por defecto oculto, que mostrará una imagen, el nombre del usuario, y tres enlaces.</p>
<p>Vamos a por el nuevo código JavaScript que hemos añadido:</p>
<pre name="code" class="javascript">        FB.Event.subscribe('auth.login', function () {
            window.location.reload();
        });

        FB.Event.subscribe('auth.logout', function (response) {
            window.location.reload();
        });

        FB.getLoginStatus(function(response) {
            if (response.authResponse) {
                document.getElementById('fb-login-button').style.display = 'none';
                document.getElementById('user-box').style.display = 'block';
                FB.api('/me', function(user) {
                    if(user != null) {
                        var image = document.getElementById('image');
                        image.src = 'https://graph.facebook.com/' + user.id + '/picture';
                        var name = document.getElementById('name');
                        name.innerHTML = user.name
                    }
                });
            }
        });

        function userLogout() {
            FB.getLoginStatus(function(response) {
                if (response.authResponse) {
                    FB.logout();
                }
            });
        }

        function publishStream() {
            var body = 'Probando la demo del SDK de JavaScript de Facebook';
            FB.api('/me/feed', 'post', { message: body }, function(response) {
                if (!response || response.error) {
                    alert('Ha ocurrido un error');
                } else {
                    alert('¡Éxito! Entra a tu muro y verás una nueva publicación');
                }
            });
        }

        function requestDialog() {
            FB.ui({
                method: 'apprequests',
                message: 'Echa un vistazo a esta demo.',
                title: 'Compartir aplicación'
            });
        }</pre>
<p>Paso a paso:</p>
<ol>
<li>En primer lugar llamamos a <strong>FB.Event.subscribe</strong> para que cuando el usuario inicie sesión (es decir, cuando se lance el evento <em>auth.login</em>), la página se recargue.</li>
<li>Del mismo modo, cuando el usuario cierre sesión (cuando se lance el evento <em>auth.logout</em>), la página también se recargará.</li>
<li>Después invocamos a <strong>FB.getLoginStatus</strong>. Como vimos, con este método podemos saber si el usuario ha iniciado sesión y está conectado con nuestra aplicación, en función de si el objeto authResponse está o no presente. En ese caso de que lo esté (está conectado):</li>
<ol>
<li>Ocultamos el Login Button</li>
<li>Mostramos el div contenedor.</li>
<li>Realizamos una llamada a la API (<strong>FB.api</strong>) consultando información sobre el usuario activo. Construimos la URL de su avatar y lo establecemos a la imagen que hay dentro del div contenedor. E igualmente, extramos su nombre completo y lo escribimos en el div con id &#8216;name&#8217;.</li>
</ol>
<li>Ahora definimos la función userLogout() que se invoca al hacer clic sobre el texto &#8220;Cerrar sesión&#8221;. Comprobará si se ha iniciado sesión, y en caso afirmativo, la cierra (<strong>FB.logout</strong>).</li>
<li>La función publishStream se ejecuta cuando se hace clic sobre el texto &#8220;Publicar en el muro&#8221;. Mediante <strong>FB.api</strong>, realiza una llamada al método &#8216;/me/feed&#8217; del Graph API, usando una petición POST, y con el mensaje de &#8216;body&#8217;. Tras realizar la petición, se le notifica al usuario de si se ha publicado con éxito o no la historia.</li>
<li>Por último, definimos la función requestDialog, que se invoca al hacer clic sobre &#8220;Invitar a amigos&#8221;. Esta función realiza una llamada a <strong>FB.ui</strong>, pasándole tres parámetros (nombre del diálogo, texto de la petición, título de la petición), y genera el diálogo Request que permite enviar una invitación a los amigos para que usen la aplicación.</li>
</ol>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-17-a-las-04.55.22.png"><img class="aligncenter size-medium wp-image-1165" title="Captura de pantalla 2011-09-17 a la(s) 04.55.22" src="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-17-a-las-04.55.22-300x65.png" alt="" width="300" height="65" /></a><a href="http://chusete.es/facebook/step2_2.html">Ver demo completa</a>.</p>
<h2>Resumen</h2>
<p>Hasta ahora ya conocíamos por encima todo el ecosistema de tecnologías para desarrollar en Facebook, y habíamos creado una primera aplicación que hacía uso de algunos Social Plugins y de Open Graph.</p>
<p>Esta vez ya nos hemos ensuciado más las manos. Hemos instanciado un nuevo Social Plugin (el <strong>Login Button</strong>), que nos ha generado el <strong>diálogo OAuth</strong>, con el que hemos podido solicitar determinados <strong>permisos</strong> para nuestra aplicación. Después hemos revisado los principales <strong>métodos del SDK JavaScript</strong>, y hemos visto cómo muchos de esos métodos ya estaban funcionando incluso sin invocarlos nosotros a manos. Después hemos puesto en práctica nuestro conocimiento del SDK: nos hemos atado a <strong>eventos</strong> generados por Facebook (<em>auth.login</em> y <em>auth.logout</em>), permitimos mostrar diferente contenido en función de si se ha iniciado o no sesión, <strong>consultamos en la API</strong> y mostramos información básica del usuario, hemos visto cómo <strong>cerrar sesión</strong>, cómo <strong>publicar en el muro del usuario</strong> directamente, y hemos creado un <strong>diálogo Request</strong> para invitar a nuestros amigos a usar la aplicación.</p>
<p>No está mal, ¿no? Con lo que ya conocemos, y un poco de imaginación, podemos crear aplicaciones muy ricas en funcionalidades. Pero todavía nos quedan algunas cosas por ver en esta serie introductoria a la programación en Facebook: cómo crear aplicaciones canvas, y cómo manejar el PHP SDK. Nos vemos en la siguiente parte y, como siempre, ¡gracias por leer!
<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fchusete.es%2F2011%2F09%2F18%2Fintroduccion-a-la-programacion-en-facebook-iii%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fchusete.es%2F2011%2F09%2F18%2Fintroduccion-a-la-programacion-en-facebook-iii%2F&amp;source=chuso&amp;style=normal&amp;service=bit.ly&amp;service_api=R_86054639b9f90148987197dfdc061697&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://chusete.es/2011/09/18/introduccion-a-la-programacion-en-facebook-iii/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Introducción a la programación Facebook II</title>
		<link>http://chusete.es/2011/09/16/introduccion-a-la-programacion-facebook-ii/</link>
		<comments>http://chusete.es/2011/09/16/introduccion-a-la-programacion-facebook-ii/#comments</comments>
		<pubDate>Fri, 16 Sep 2011 08:00:37 +0000</pubDate>
		<dc:creator>chusete</dc:creator>
				<category><![CDATA[desarrollo]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[javasctipt]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[facebook API]]></category>
		<category><![CDATA[insights]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[xfbml]]></category>

		<guid isPermaLink="false">http://chusete.es/?p=1139</guid>
		<description><![CDATA[Ok, el anterior artículo no estuvo mal; vimos una introducción conceptual a las piezas clave para la construcción de aplicaciones en Facebook. ¡Pero no llegamos a hacer nada! En este post vamos a construir algo sencillo, jugando con el SDK en JavaScript. Vamos a probar a mostrar algunos de los social plugins, usaremos Open Graph, y presentaremos [...]]]></description>
			<content:encoded><![CDATA[<p><img class="aligncenter size-full wp-image-1147" title="banner_fb2" src="http://chusete.es/wp-content/uploads/2011/09/banner_fb2.jpg" alt="" width="100%" /></p>
<p>Ok, el <a href="/2011/09/13/introduccion-a-la-programacion-en-facebook/">anterior artículo</a> no estuvo mal; vimos una introducción conceptual a las piezas clave para la construcción de aplicaciones en Facebook. ¡Pero no llegamos a hacer nada! En este post vamos a construir algo sencillo, jugando con el SDK en JavaScript. Vamos a probar a mostrar algunos de los social plugins, usaremos Open Graph, y presentaremos dos nuevas tecnologías: XFBML y Facebook Insights. ¡Al lío!</p>
<p><span id="more-1139"></span></p>
<h2>Paso 1 &#8211; Alojamiento para la aplicación</h2>
<p>Es responsabilidad del desarrollador buscar un alojamiento para su aplicación. Esto no suele ser un problema, ya que sirve cualquiera al que tengas acceso FTP. Sin embargo, desde el 1 de octubre de 2011 Facebook obliga a que las aplicaciones estén disponibles tanto por HTTP como por HTTPS.</p>
<p>Por lo pronto vamos a crear una carpeta llamada &#8220;/facebook&#8221; en el directorio raíz de la web, que será desde donde se acceda a nuestra aplicación.</p>
<div class="note">
<h3>Alojamiento gratuíto</h3>
<p>Desde el 15 de septiembre de 2011, Facebook ha llegado a un acuerdo con la compañía Heroku para ofrecer gratis un alojamiento reducido pero funcional para todo el que lo solicite. Queda fuera del alcance de esta guía explicar cómo utilizar este servicio. <a href="https://developers.facebook.com/blog/post/558/">Más información</a>.</p>
</div>
<h2>Paso 2 &#8211; Configurando la aplicación</h2>
<p>Ahora, accedemos a <a href="https://developers.facebook.com/">developers.facebook.com</a>, y de ahí vamos a la pestaña Aplicaciones. Seleccionamos la nuestra, y en el apartado de configuración pinchamos en &#8220;<em>Edit settings</em>&#8220;. En la parte inferior, tal como vimos en el anterior artículo, nos dan cuatro opciones para crear nuestra aplicación. Vamos a seleccionar Website e introducimos la URL completa con la que se accederá a nuestra aplicación. En mi caso, introduzco <a href="http://chusete.es/facebook">http://chusete.es/facebook</a>.</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-16-a-las-06.03.58.png"><img class="aligncenter size-medium wp-image-1150" title="Captura de pantalla 2011-09-16 a la(s) 06.03.58" src="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-16-a-las-06.03.58-300x29.png" alt="" width="300" height="29" /></a></p>
<p>Pulsamos en <em>Guardar cambios</em>, y ya está. Ésta ha sido fácil <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h2>Paso 3 &#8211; Creando el esqueleto</h2>
<p>Ahora, en la carpeta /facebook de nuestro alojamiento web, vamos a crear un fichero llamado index.html con la estructura básica de un documento HTML. Además, añadiremos el código JavaScript que vimos en el anterior artículo que había que insertar para usar el SDK. Quedaría así el esqueleto:</p>
<pre name="code" class="html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8" /&gt;
    &lt;title&gt;Demo Facebook&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;Demo Facebook&lt;/h1&gt;

    &lt;div id="fb-root"&gt;&lt;/div&gt;
    &lt;script type="text/javascript" src="http://connect.facebook.net/es_ES/all.js"&gt;&lt;/script&gt;
    &lt;script type="text/javascript"&gt;
        FB.init({
            appId  : '256797284360192',
            status : true, // comprobar estado de login
            cookie : true, // habilitar cookies para permitir al servidor acceder a la sesión
            xfbml  : true, // renderizar código XFBML
            channelURL : 'http://chusete.es/facebook/channel.html', // fichero channel.html
            oauth  : true // habilita OAuth 2.0
        });
    &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<div class="note">
<h3>Acerca de channelURL</h3>
<p>Si te fijas, verás que en la línea 18 hay una URL que apunta a channelURL. Este fichero tan sólo tendrá este contenido:</p>
<pre name="code" class="html">&lt;script src="http://connect.facebook.net/es_ES/all.js"&gt;&lt;/script&gt;</pre>
<p>Para saber más acerca de por qué es recomendable crear el fichero channel.html, consulta la documentación de la función <a href="https://developers.facebook.com/docs/reference/javascript/FB.init/">FB.init</a>.</p>
</div>
<p>Llegados a este punto, ya tenemos listo el esqueleto sobre el que construir una pequeña aplicación de demo. <a href="http://chusete.es/facebook/step3.html">Ver resultado del paso 3</a>.</p>
<h2>Paso 4 &#8211; Añadiendo Social Plugins (XFBML)</h2>
<p>Ya vimos que hay, ni más ni menos, que 10 social plugins. Vamos a insertar algunos a nuestra aplicación. Pero antes un poco de teoría. Hace tiempo, Facebook creó su propio lenguaje de marcado para poder insertar social plugins en nuestras aplicaciones. Hablamos del FBML (Facebook Markup Language). Para que pudierar interactuar con JavaScript, crearon FBJS; un dialecto de JavaScript para usarlo en conjunto con FBML dentro del espacio de Facebook. Sin embargo, desde el 11 de marzo de 2011, todo <a href="http://developers.facebook.com/blog/post/462">este conjunto de tecnologías ha quedado fuera de uso</a>. ¿Y qué hay en su lugar? Pues un sistema unificado para todas las aplicaciones, ya sean pestañas, aplicaciones en canvas, externas, etc., basado en tecnologías estándar: HTML, CSS y JavaScript. Mucho mejor, ¿verdad?</p>
<p>Para sustituir a FBML crearon XFBML, que es un sistema que, mediante etiquetas HTML estándar, permite definir Social Plugins. Por ejemplo, el botón &#8220;Me gusta&#8221; es algo tan sencillo como:</p>
<pre name="code" class="html">&lt;div data-send="false" data-width="450" data-show-faces="false"&gt;&lt;/div&gt;</pre>
<p>¿Cómo se hace para que ese código HTML se renderice como el Social Plugin &#8220;Me gusta&#8221;? Hay dos opciones:</p>
<ol>
<li>Si en el código de inicialización del SDK JavaScript (el método FB.init que hemos invocado en index.html) tenemos a true el campo xfbml, entonces se renderizarán todas las etiquetas XFBML automáticamente.</li>
<li>En caso contrario, podremos renderizarlas invocando a <a href="http://developers.facebook.com/docs/reference/javascript/FB.XFBML.parse/">FB.XFBML.parse</a>.</li>
</ol>
<p>Vale, ahora sólo nos queda saber cómo averiguar el código HTML que define cada Social Plugin. Accede a la página de <a href="http://developers.facebook.com/docs/plugins/">Social Plugins</a>, elige el que quieras usar, completa el formulario con los valores que desees (si es que el plugin te da esa opción), y finalmente pulsa sobre el botón <em>Get Code</em>. ¡Pero ojo! El código que te genera incluye tanto la inicialización del SDK, como el código HTML que define el plugin. Como nosotros ya tenemos el código del SDK, sólo tendremos que copiar el código HTML del plugin.</p>
<p>Por ejemplo, vamos a insertar un plugin <a href="http://developers.facebook.com/docs/reference/plugins/live-stream/">Live Stream</a> en nuestra demo. Al pulsar en <em>Get Code</em> obtenemos lo siguiente:</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-16-a-las-04.04.58.png"><img class="aligncenter size-medium wp-image-1140" title="Captura de pantalla 2011-09-16 a la(s) 04.04.58" src="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-16-a-las-04.04.58-300x179.png" alt="" width="300" height="179" /></a></p>
<p>Copiamos sólo el código HTML:</p>
<pre name="code" class="html">&lt;div data-event-app-id="282078738484719" data-width="400" data-height="500" data-always-post-to-friends="false"&gt;&lt;/div&gt;</pre>
<p>Con lo que ya tendríamos un chat en nuestra aplicación web, con el siguiente aspecto:</p>
<p><a href="http://chusete.es/facebook/step4.html"><img class="aligncenter size-full wp-image-1141" title="Captura de pantalla 2011-09-16 a la(s) 04.17.38" src="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-16-a-las-04.17.38.png" alt="" width="430" height="594" /></a></p>
<p><a href="http://chusete.es/facebook/step4.html">Ver resultado del paso 4</a>.</p>
<h2>Paso 5 &#8211; Botón &#8220;Me gusta&#8221; y Open Graph</h2>
<p>Del mismo modo que hemos insertado un plugin Live Stream, ahora vamos a insertar el famoso botón &#8220;Me gusta&#8221;. Como vimos, para obtener el código XFBML debemos acceder a la página del plugin, completar el formulario, obtenemos su código, y lo copiamos. Siguiendo esos pasos obtendrás algo similar a esto (en función de cómo complementes el formulario):</p>
<pre name="code" class="html">&lt;div data-send="false" data-width="450" data-show-faces="false"&gt;&lt;/div&gt;</pre>
<p>Con solo pegar ese código al documento HTML, ya tendremos el botón en nuestra página. ¡Pero un momento! Como vimos en la primera parte, existe una tecnología llamada Open Graph que convierte un documento web en todo un objeto social, referenciable y al que como administradores podemos seguirle el rastro. Pues bien, vamos a hacer esto. En la propia página del plugin del botón &#8220;Me gusta&#8221; tenemos un formulario que nos permite generar algunos códigos Open Graph -aunque generarlos a mano es algo trivial. En mi caso, lo he dejado así:</p>
<pre name="code" class="html">&lt;meta property="og:title" content="Página demo de Facebook" /&gt;
&lt;meta property="og:type" content="website" /&gt;
&lt;meta property="og:description" content="Ésta es la página de demo de la segunda parte de la introducción a programación en Facebook de chusete.es" /&gt;
&lt;meta property="og:url" content="http://chusete.es/facebook/index.html" /&gt;
&lt;meta property="og:image" content="http://chusete.es/facebook/logo.png" /&gt;
&lt;meta property="og:site_name" content="chuso!" /&gt;
&lt;meta property="fb:admins" content="1048522537" /&gt;</pre>
<p>Ahora, cuando alguien comparta esta página en Facebook, ésa será la información que se mostrará por defecto. Por ejemplo, en este caso quedaría así:</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-16-a-las-04.45.32.png"><img class="aligncenter size-medium wp-image-1142" title="Captura de pantalla 2011-09-16 a la(s) 04.45.32" src="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-16-a-las-04.45.32-300x154.png" alt="" width="300" height="154" /></a></p>
<p><a href="chusete.es/facebook/index.html">Ver resultado final</a>.</p>
<h2>Paso 6 &#8211; Página para administradores e Insights</h2>
<p>Pero hay más. Junto con la información Open Graph hemos insertado una etiqueta más, en la que el atributo property tiene como valor &#8220;fb:admins&#8221;. Ese campo contiene el id de nuestro usuario, de manera que así constaremos como el propietario de la página. ¿De qué nos sirve esto? Pues en resumen, para dos cosas. Fíjate en cómo queda el botón &#8220;Me gusta&#8221; cuando <strong>tú</strong> lo visualizas:</p>
<p><img class="aligncenter size-full wp-image-1143" title="Captura de pantalla 2011-09-16 a la(s) 05.14.40" src="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-16-a-las-05.14.40.png" alt="" width="416" height="40" /><br />
Interesante&#8230; Hay un link a &#8220;Página para administradores&#8221; y a &#8220;Estadísticas&#8221;. ¿Qué son?</p>
<h3>Página para administradores</h3>
<p>Cuando alguien pulse sobre el botón &#8220;Me gusta&#8221;, se creará un nuevo panel de administración con el que podrás comunicarte con tus &#8220;likers&#8221; (aquellos a los que les ha gustado tu publicación). Este panel estará disponible desde tu <a href="http://www.facebook.com/bookmarks/pages">lista de Facebook Pages</a>. Y lo más interesante: todo lo que publiques en el muro de esta página, aparecerá en las lista de novedades de los usuarios a los que les gustó tu publicación.</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-16-a-las-05.17.26.png"><img class="aligncenter size-medium wp-image-1144" title="Captura de pantalla 2011-09-16 a la(s) 05.17.26" src="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-16-a-las-05.17.26-300x190.png" alt="" width="300" height="190" /></a></p>
<h3>Insights</h3>
<p>Y en segundo lugar, tendrás acceso a las estadísticas en <a href="www.facebook.com/insights/">Facebook Insights</a> (¡otra más de las tecnologías de Facebook!). Básicamente, es un panel de análisis de tráfico web, similar a Google Analytics. Puedes acceder desde el enlace &#8220;Estadísticas&#8221; que acompaña al botón &#8220;Me gusta&#8221;, pero es preferible reclamar la propiedad de tu dominio ante Facebook, para de ese modo tener acceso completo a todo lo que ocurre con tu página. Para ello, accedemos a la página principal de Insights, y pulsamos sobre el botón <img class="alignnone size-full wp-image-1145" title="Captura de pantalla 2011-09-16 a la(s) 05.25.00" src="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-16-a-las-05.25.00.png" alt="" width="172" height="25" />. Mete el dominio de tu web, copia el código &#8220;meta&#8221; que te ha generado, y pégalo en la página principal del dominio:</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-16-a-las-05.25.56.png"><img class="aligncenter size-medium wp-image-1146" title="Captura de pantalla 2011-09-16 a la(s) 05.25.56" src="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-16-a-las-05.25.56-300x237.png" alt="" width="300" height="237" /></a>Finalmente pulsa en Get Insights y ya habrá finalizado el proceso de alta en Facebook Insights. Ahora, cada vez que accedas al dashboard de Insights, podrás consultar qué historias de tu página se han compartido o han gustado en Facebook.</p>
<p>Para más información, consulta la documentación de <a href="http://developers.facebook.com/docs/insights/">Facebook Insights</a>.</p>
<h2>Resumen</h2>
<p>En la primera parte dimos un repaso a las principales tecnologías que involucran el desarrollo de aplicaciones Facebook, y dimos de alta un nuevo perfil de aplicación.</p>
<p>Hoy, hemos visto cómo crear una aplicación en una web externa a Facebook vinculada a nuestro alojamiento. Hemos creado un documento HTML con el código de incialización del SDK JavaScript. Hemos conocido una tecnología de Facebook -XFBML- que nos permite crear plugins de una forma muy sencilla. Como ejemplo, hemos creado un plugin de tipo Live Stream, y otro con el botón &#8220;Me gusta&#8221;. También hemos añadido los códigos Open Graph y hemos visto su utilidad. Finalmente, hemos visto cómo interactuar con los usuarios a los que les gustan nuestras publicaciones, y cómo explorar las estadísticas de uso de nuestro sitio por los usuarios de Facebook.</p>
<p>&nbsp;
<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fchusete.es%2F2011%2F09%2F16%2Fintroduccion-a-la-programacion-facebook-ii%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fchusete.es%2F2011%2F09%2F16%2Fintroduccion-a-la-programacion-facebook-ii%2F&amp;source=chuso&amp;style=normal&amp;service=bit.ly&amp;service_api=R_86054639b9f90148987197dfdc061697&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://chusete.es/2011/09/16/introduccion-a-la-programacion-facebook-ii/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Introducción a la programación en Facebook</title>
		<link>http://chusete.es/2011/09/13/introduccion-a-la-programacion-en-facebook/</link>
		<comments>http://chusete.es/2011/09/13/introduccion-a-la-programacion-en-facebook/#comments</comments>
		<pubDate>Tue, 13 Sep 2011 00:09:47 +0000</pubDate>
		<dc:creator>chusete</dc:creator>
				<category><![CDATA[desarrollo]]></category>
		<category><![CDATA[javasctipt]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[API Graph]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[facebook API]]></category>
		<category><![CDATA[open graph]]></category>

		<guid isPermaLink="false">http://chusete.es/?p=1091</guid>
		<description><![CDATA[¿De modo que te han pedido que hagas una aplicación para Facebook y no sabes por dónde empezar? ¿Has llegado a la documentación oficial y te pierdes entre tanto Open Graph, SDK, plugins, dialogs y Graph API? Don&#8217;t panic! En este artículo vamos a ver paso a paso cómo empezar a programar en el nuevo sistema [...]]]></description>
			<content:encoded><![CDATA[<p><img class="aligncenter size-full wp-image-1129" title="head_fb1" src="http://chusete.es/wp-content/uploads/2011/09/head_fb1.jpg" alt="" width="100%" /></p>
<p>¿De modo que te han pedido que hagas una aplicación para Facebook y no sabes por dónde empezar? ¿Has llegado a la <a href="https://developers.facebook.com/docs/">documentación oficial</a> y te pierdes entre tanto Open Graph, SDK, plugins, dialogs y Graph API? Don&#8217;t panic! En este artículo vamos a ver paso a paso cómo empezar a programar en el nuevo sistema de Facebook. ¡Al lío!</p>
<p><span id="more-1091"></span></p>
<h2>Tipos de aplicaciones</h2>
<p>En el apartado <em><a href="http://developers.facebook.com/docs/">Getting Started</a></em> de la documentación oficial vemos que nos dan tres opciones:</p>
<ol>
<li><strong><a href="https://developers.facebook.com/docs/guides/web/">Páginas web</a></strong>. Para crear una aplicación que se ejecute en tu página web fuera de Facebook.</li>
<li><strong><a href="https://developers.facebook.com/docs/guides/mobile/">Aplicaciones móviles</a></strong>. Para crear apps para las principales infraestructuras móviles.</li>
<li><strong><a href="https://developers.facebook.com/docs/guides/canvas/">Aplicaciones en Facebook</a></strong>. Este decir, para crear una aplicación que se insertará dentro de la web de Facebook, en un <strong>canvas</strong>.</li>
</ol>
<p>En cualquiera de los tres casos, las tecnologías que utilizaremos serían básicamente las mismas.</p>
<p>Más adelante revisaremos algunas de las tecnologías que nos ofrece Facebook para integrar nuestra aplicación con su infraestructura.</p>
<div class="note">
<h3>Aplicaciones de Escritorio</h3>
<p>Existe un cuarto tipo de aplicaciones, que no se mencionan, y que pueden comunicarse con Facebook: Aplicaciones de escritorio. En esta guía no lo abordaremos.</p>
</div>
<p>Además, en la página de inicio ofrecen un <a href="https://developers.facebook.com/docs/samples/">apartado de ejemplos</a> donde podrás probar y descargar distintas demos, como el de una aplicación en página web, o una aplicación dentro de un canvas en Facebook. También puedes acceder a <a href="https://developers.facebook.com/videos/">vídeos</a> con charlas y guías.</p>
<h2>Dando de alta una aplicación</h2>
<p>Para entender mejor todos los apartados, y para poder realizar algunos ejemplos, vamos a crearnos una nueva aplicación. Para ello, vamos a seguir los siguientes pasos:</p>
<p>Accedemos a la página de desarrolladores de Facebook: <a href="https://developers.facebook.com/">https://developers.facebook.com/</a></p>
<p><a href="https://developers.facebook.com/"></a>Una vez ahí, seleccionamos &#8220;<a href="https://developers.facebook.com/apps">Aplicaciones</a>&#8221; en el menú.</p>
<p>En tercer lugar, pulsamos sobre el botón <a href="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-12-a-las-23.10.39.png"><img class="alignnone size-full wp-image-1110" title="Captura de pantalla 2011-09-12 a la(s) 23.10.39" src="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-12-a-las-23.10.39.png" alt="" width="120" height="24" /></a>.</p>
<p>Ahora indicamos un nombre y la local de la aplicación y pulsamos <em>Continuar</em>:</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-12-a-las-23.11.27.png"><img class="aligncenter size-medium wp-image-1111" title="Captura de pantalla 2011-09-12 a la(s) 23.11.27" src="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-12-a-las-23.11.27-300x109.png" alt="" width="300" height="109" /></a></p>
<p>Completamos el captcha y pulsamos sobre <em>Enviar:</em></p>
<p><em><a href="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-12-a-las-23.12.48.png"><img class="aligncenter size-medium wp-image-1112" title="Captura de pantalla 2011-09-12 a la(s) 23.12.48" src="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-12-a-las-23.12.48-300x127.png" alt="" width="300" height="127" /></a></em></p>
<p>Y con esto ya estaría dada de alta nuestra aplicación:</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-12-a-las-23.14.33.png"><img class="aligncenter size-medium wp-image-1113" title="Captura de pantalla 2011-09-12 a la(s) 23.14.33" src="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-12-a-las-23.14.33-300x252.png" alt="" width="300" height="252" /></a></p>
<p>Fíjate en la caja superior. Verás dos campos: App ID y App Secret. Estos código los necesitarás para hacer funcionar tu aplicación. El primero es el código que identifica la app, y el segundo es un código de seguridad que utilizarás para la autenticación en el lado del servidor.</p>
<p>Por lo pronto, podemos cambiar los siguientes campos:</p>
<ul>
<li><strong>Logo</strong>. Corresponde al logo de 75&#215;75 px de la aplicación.</li>
<li><strong>Icono</strong>. Icono de 16&#215;16 px de la aplicación</li>
<li><strong>App Secret</strong>. Este código no debemos compartirlo con nadie. Desde este apartado podremos reiniciarlo si lo deseáramos.</li>
<li><strong>App Display Name.</strong> Nombre con el que se mostrará la aplicación.</li>
<li><strong>App Namespace.</strong> Nombre del espacio de nombres de la aplicación, formado únicamente por caracteres en minúsculas, guiones medios y guiones bajos.</li>
<li><strong>Contact Email.</strong> Dirección de correo electrónico de contacto.</li>
<li><strong>App Domain.</strong> Dominio sobre el que se alojará la aplicación (por ejemplo www.example.com).</li>
<li><strong>Category</strong> y <strong>Sub-category.</strong> Categorías en las que catalogamos la aplicación.</li>
</ul>
<p>Además, vemos que podemos definir 4 formas distintas de integrar la aplicación con Facebook:</p>
<ol>
<li><strong>Website.</strong> Para cuando queramos que en nuestra página puedan los usuarios hacer login con su cuenta de Facebook.</li>
<li><strong>App on Facebook.</strong> Aplicación para incorporar en un canvas dentro de Facebook.</li>
<li><strong>Mobile Native.</strong> Para crear una aplicación para móviles.</li>
<li><strong>Page Tab.</strong> Permite crear una aplicación que se mostrará como una pestaña dentro de una Facebook Page.</li>
</ol>
<p>Y estas son todas las opciones básicas que tenemos disponibles para configurar una aplicación de Facebook. Sin embargo, podemos acceder a la configuración avanzada desde el menú de la izquierda, pulsando sobre <em>Configuration &gt; Advanced</em>:</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/Advanced-Desarrolladores-de-Facebook.png"><img class="aligncenter size-medium wp-image-1114" title="Advanced - Desarrolladores de Facebook" src="http://chusete.es/wp-content/uploads/2011/09/Advanced-Desarrolladores-de-Facebook-188x300.png" alt="" width="188" height="300" /></a></p>
<p>En este apartado avanzado por ahora podremos establecer la descripción de nuestra aplicación, y el <em>Sandbox Mode</em> (habilitado indica que sólo los desarrolladores pueden acceder a la aplicación).</p>
<p>Rápido e indoloro, ya tenemos nuestra aplicación creada <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Cada vez que queramos volver a la configuración de nuestra aplicación, tan solo tendremos que acceder a la página de desarrolladores de Facebook, apartado <a href="https://developers.facebook.com/apps">Aplicaciones</a>, y seleccionamos la opción deseada.</p>
<div class="note">
<h3>Página dentro de Facebook</h3>
<p>Si quisiéramos acceder a la página de la aplicación (su página dentro de Facebook, no su perfil de configuración), desde su pantalla de configuración, en el menú izquierda, pulsamos sobre <em>View App Profile Page</em>. Veremos una página en blanco esperando a ser completada:</p>
<p style="text-align: center;"><a href="http://chusete.es/wp-content/uploads/2011/09/chusete-demo.png"><img class="size-medium wp-image-1117 aligncenter" title="chusete demo" src="http://chusete.es/wp-content/uploads/2011/09/chusete-demo-192x300.png" alt="" width="192" height="300" /></a></p>
<p style="text-align: left;">Podremos completar la página de perfil de la aplicación en cualquier momento.</p>
</div>
<h2>Tecnologías disponibles</h2>
<p>Bien, y ¿qué tecnologías nos ofrece Facebook para implementar una aplicación? Éstas son las principales:</p>
<h3>1. <a href="https://developers.facebook.com/docs/plugins/">Social plugins</a></h3>
<p>Corresponde a pequeños plugins o <em>widgets</em> que se pueden incorporar muy fácilmente en cualquier página web ajena a Facebook. Accediendo a la página de cada uno de ellos verás un pequeño formulario que te genera el código necesario para que lo incorpores en tu página. Seguro que estás muy familiarizado con casi todos ellos:</p>
<div style="overflow: hidden; margin-top: 10px;"><img class="alignleft size-full wp-image-1093" style="margin-right: 10px;" title="like" src="http://chusete.es/wp-content/uploads/2011/09/like.png" alt="" width="128" height="88" /><strong><a href="https://developers.facebook.com/docs/reference/plugins/like">Botón &#8220;Me gusta&#8221;.</a></strong><br />
Es el más famoso de todos los plugins. Permite a los usuarios compartir con un solo clic la página que están visitando</div>
<div style="overflow: hidden; margin-top: 10px;"><img class="alignleft size-full wp-image-1094" style="margin-right: 10px;" title="send" src="http://chusete.es/wp-content/uploads/2011/09/send.png" alt="" width="128" height="88" /><strong><a href="https://developers.facebook.com/docs/reference/plugins/send">Botón &#8220;Enviar&#8221;.</a></strong><br />
Permite que los usuarios envíen a alguno/s de sus contactos la página que están visitando.</div>
<div style="overflow: hidden; margin-top: 10px;"><img class="alignleft size-full wp-image-1095" style="margin-right: 10px;" title="comments" src="http://chusete.es/wp-content/uploads/2011/09/comments-1.png" alt="" width="128" height="88" /><strong><a href="https://developers.facebook.com/docs/reference/plugins/comments"> Comentarios.</a></strong><br />
Para añadir un sistema de comentarios a tu página web.</div>
<div style="overflow: hidden; margin-top: 10px;"><img class="alignleft size-full wp-image-1096" style="margin-right: 10px;" title="activityfeed" src="http://chusete.es/wp-content/uploads/2011/09/activityfeed.png" alt="" width="128" height="88" /><strong><a href="https://developers.facebook.com/docs/reference/plugins/activity">Feed de actividades.</a></strong><br />
Muestra una lista de las últimas actividades que han llevado a cabo tus contactos de Facebook.</div>
<div style="overflow: hidden; margin-top: 10px;"><img class="alignleft size-full wp-image-1097" style="margin-right: 10px;" title="recommendations" src="http://chusete.es/wp-content/uploads/2011/09/recommendations.png" alt="" width="128" height="88" /><strong><a href="https://developers.facebook.com/docs/reference/plugins/recommendations">Recomendaciones.</a></strong><br />
Muestra al usuario una lista personalizada de enlaces recomendados, en función de diferentes parámetros, como por ejemplo las preferencias de sus amigos.</div>
<div style="overflow: hidden; margin-top: 10px;"><img class="alignleft size-full wp-image-1098" style="margin-right: 10px;" title="likebox" src="http://chusete.es/wp-content/uploads/2011/09/likebox.png" alt="" width="128" height="88" /><strong><a href="https://developers.facebook.com/docs/reference/plugins/like-box">Caja &#8220;me gusta&#8221;.</a></strong><br />
Similar al botón &#8220;Me gusta&#8221;, pero con más elementos. Por ejemplo, muestra las últimas actividades de la página, o una lista de personas a las que les gusta.</div>
<div style="overflow: hidden; margin-top: 10px;"><img class="alignleft size-full wp-image-1099" style="margin-right: 10px;" title="login" src="http://chusete.es/wp-content/uploads/2011/09/login.png" alt="" width="128" height="88" /><strong><a href="https://developers.facebook.com/docs/reference/plugins/login">Botón &#8220;Login&#8221;.</a></strong><br />
Botón que permite iniciar sesión en la página utilizando la infraestructura de sesiones de Facebook.</div>
<div style="overflow: hidden; margin-top: 10px;"><img class="alignleft size-full wp-image-1100" style="margin-right: 10px;" title="register" src="http://chusete.es/wp-content/uploads/2011/09/register.png" alt="" width="128" height="88" /><strong><a href="https://developers.facebook.com/docs/plugins/registration">Registro.</a></strong><br />
Formulario de registro a una página que se rellena automáticamente con tus datos de Facebook. De este modo, se ahorra tiempo a los usuarios.</div>
<div style="overflow: hidden; margin-top: 10px;"><img class="alignleft size-full wp-image-1101" style="margin-right: 10px;" title="facepile" src="http://chusete.es/wp-content/uploads/2011/09/facepile.png" alt="" width="128" height="88" /><strong><a href="https://developers.facebook.com/docs/reference/plugins/facepile">Facepile.</a></strong><br />
Muestra una lista de imágenes de perfil de los usuarios a los que les ha gustado la página que se está visitando.</div>
<div style="overflow: hidden; margin-top: 10px;"><img class="alignleft size-full wp-image-1102" style="margin-right: 10px;" title="livestream" src="http://chusete.es/wp-content/uploads/2011/09/livestream.png" alt="" width="128" height="88" /><strong><a href="https://developers.facebook.com/docs/reference/plugins/live-stream">Live Stream.</a></strong><br />
Muestra un pequeño &#8216;chat&#8217; vinculado a la página que se está visitando.</div>
<p>Como ves, a base de insertar este tipo de plugins, puedes crear una página web muy rica en funcionalidades en un tiempo récord. A modo de demostración, <a href="http://www.myfbse.com/winery/storybar.html">puedes consultar esta página</a>, que forma parte del apartado de ejemplos de Facebook. Esta demo hace uso del <em>botón &#8220;me gusta&#8221;</em>, del <em>feed de actividades</em>, de las <em>recomendaciones</em> y de los <em>comentarios</em>.</p>
<h3>2. <a href="https://developers.facebook.com/docs/reference/dialogs/">Diálogos</a></h3>
<p>Podemos definir los diálogos como ventanas emergentes que solicitan al usuario permiso para realizar alguna acción.</p>
<div class="note"><strong>Autorizaciones</strong><br />
Más adelante veremos que si, por ejemplo, quisiéramos que nuestra aplicación publicara una entrada en el muro de un usuario, necesitaríamos que éste nos hubiera concedido previamente permisos para realizar esta acción. Con los diálogos esto no es necesario, ya que por definición un diálogo necesita que el usuario lo autorice para realizar cualquier acción.</div>
<p>Podemos invocar los diálogos a mano, sin embargo en general suele ser mucho más cómo realizarlo mediante alguno de los SDK que Facebook nos ofrece. En concreto, para páginas web, utilizaremos el <a href="https://developers.facebook.com/docs/reference/javascript/">SDK JavaScript</a> mediante el método <a href="https://developers.facebook.com/docs/reference/javascript/FB.ui">FB.ui</a>. En el apartado del SDK de JavaScript veremos cómo invocar estos diálogos.</p>
<p>Por lo pronto, vamos a ver cuáles son los distintos diálogos que nos ofrece Facebook:</p>
<p><strong>Diálogo de Feed</strong></p>
<p>Permite al usuario añadir a su muro, desde nuestra aplicación, una publicación.</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/Facebook_Dialogs_Feed_Iframe.png"><img class="aligncenter size-medium wp-image-1104" title="Facebook_Dialogs_Feed_Iframe" src="http://chusete.es/wp-content/uploads/2011/09/Facebook_Dialogs_Feed_Iframe-300x170.png" alt="" width="300" height="170" /></a><strong>Diálogo de amigos</strong></p>
<p>Muestra un diálogo para añadir a un amigo.</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/friends-dialog2.png"><img class="aligncenter size-medium wp-image-1105" title="friends-dialog2" src="http://chusete.es/wp-content/uploads/2011/09/friends-dialog2-300x117.png" alt="" width="300" height="117" /></a></p>
<p><strong>Diálogo OAuth</strong></p>
<p>Solicita al usuario unas determinadas autorizaciones, y concede permisos a la aplicación.</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/oauth-page.png"><img class="aligncenter size-medium wp-image-1106" title="oauth-page" src="http://chusete.es/wp-content/uploads/2011/09/oauth-page-300x201.png" alt="" width="300" height="201" /></a></p>
<p><strong>Diálogo de Pago</strong></p>
<p>Permite al usuario adquirir nuevos créditos de Facebook.</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/2vsp2jb.png"><img class="aligncenter size-medium wp-image-1107" title="2vsp2jb" src="http://chusete.es/wp-content/uploads/2011/09/2vsp2jb-300x171.png" alt="" width="300" height="171" /></a><strong>Diálogo de petición</strong></p>
<p>Diálogo que permite al usuario enviar una petición a uno o más amigos.</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/165306_796701067511_703_41122128_101111_n.jpg"><img class="aligncenter size-medium wp-image-1108" title="165306_796701067511_703_41122128_101111_n" src="http://chusete.es/wp-content/uploads/2011/09/165306_796701067511_703_41122128_101111_n-300x277.jpg" alt="" width="300" height="277" /></a></p>
<p><strong>Diálogo de envío</strong></p>
<p>Diálogo para que el usuario envíe un mensaje a algún amigo, a un grupo de amigos, o a una dirección de correo.</p>
<h3><a href="http://chusete.es/wp-content/uploads/2011/09/Facebook_Dialogs_Send.png"><img class="aligncenter size-medium wp-image-1109" title="Facebook_Dialogs_Send" src="http://chusete.es/wp-content/uploads/2011/09/Facebook_Dialogs_Send-300x156.png" alt="" width="300" height="156" /></a>3. <a href="http://developers.facebook.com/docs/authentication/">Autenticación</a> y Permisos</h3>
<p>A menudo necesitaremos que los usuarios nos autoricen a acceder a su información. Por ejemplo, cuando queramos que puedan iniciar sesión en nuestra web utilizando su cuenta de Facebook, o cuando desde nuestra aplicación queramos acceder a determinados campos de su perfil de usuario. Para solicitar esta autorización utilizaremos el Diálogo OAuth.</p>
<p>Cada vez que se utiliza el diálogo OAuth, podremos pasarle información al diálogo acerca de la los permisos de acceso que autorizará el usuario. Te recomiendo que revises la <a href="http://developers.facebook.com/docs/reference/api/permissions/">lista de todos los posibles permisos</a>. Además, ten en cuenta que cuantos más permisos solicites a un usuario, menor será el número de personas que decidan autorizar a tu aplicación.</p>
<p>Existen dos métodos posibles de autenticación: Desde el servidor, o desde el cliente. Pero, para simplificar, podemos decir que son equivalentes el uno al otro.</p>
<h3>4. <a href="http://developers.facebook.com/docs/reference/api">Graph API</a></h3>
<p>El nucleo de Facebook es un grafo social, donde cada persona, foto, evento o página tiene su ID único, y donde existen conexiones entre todos ellos (por ejemplo, amistades, etiquetas en fotos, contenidos compartidos, etc.).</p>
<p>Para acceder a las propiedades de cualquiera de estos objetos accederemos a la URL: <strong>https://graph.facebook.com/ID</strong> cambiando ID por el identificador del objeto que queramos consultar. Como resultado, nos devolverá un objeto JSON.</p>
<p>Por ejemplo, al comienzo de este artículo creamos una aplicación. Puedes coger el App ID de tu aplicación y acceder a su información. Te saldrá algo similar a esto:</p>
<pre name="code" class="javascript">{
   "id": "256797284360192",
   "name": "chusete demo",
   "description": "Aplicaci\u00f3n de pruebas de Chusete",
   "category": "Utilities",
   "subcategory": "News",
   "link": "http://www.facebook.com/apps/application.php?id=256797284360192"
}</pre>
<p>En el caso de los usuarios y de las páginas, cuando tengan un alias, se podrá usar como alternativa al ID.</p>
<p>Por supuesto, todas estas peticiones devuelven por defecto tan solo la información pública de ese objeto/persona. Para acceder a información privada, debemos contar con su autorización. Esta autorización se proporciona mediante el parámetro GET access_token.</p>
<div class="note">
<h3>Graph API Explorer</h3>
<p>Lo mejor para aprender más sobre Graph API es utilizar la herramienta Graph API Explorer, un sencillo explorador para comprobar el resultado de todas las posibles consultas que podemos realizar: <a href="http://developers.facebook.com/tools/explorer">http://developers.facebook.com/tools/explorer</a>. Vamos a ver cómo se usa:</p>
<p>En primer lugar, debemos establecer los permisos que le otorgamos a la herramienta. Para ello pulsamos sobre el botón Get Access Token, donde se desplegarán casillas con todos los posibles permisos (tal como vimos en el apartado anterior, sobre Autenticación). Una vez establecidos, podemos realizar las consulta que queramos desde la columna derecha <em>Conexiones</em>:</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-13-a-las-00.50.30.png"><img class="aligncenter size-full wp-image-1118" title="Captura de pantalla 2011-09-13 a la(s) 00.50.30" src="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-13-a-las-00.50.30.png" alt="" width="245" height="197" /></a></p>
<p>En resumen, en esta utilidad veremos lo siguiente:</p>
<ul>
<li><strong>Access Token</strong> &#8211; Es el parámetro access_token que se proporciona en cada petición al Graph API.</li>
<li><strong>Tipo de petición</strong> &#8211; Es un campo desplegable. Por defecto tendrá el valor GET.</li>
<li><strong>URL de petición</strong> &#8211; Corresponde a la URL sobre la que se realiza la petición.</li>
<li><strong>Resultado</strong> &#8211; Es el bloque gris sobre el que se muestra el resultado JSON.</li>
<li><strong>Conexiones</strong> &#8211; Son enlaces a distintas conexiones sobre el objeto actual.</li>
<li><strong>Fields</strong> &#8211; Campos que muestra el objeto JSON para la petición actual. No tienen por qué mostrarse todos.</li>
</ul>
</div>
<h3>5. <a href="http://developers.facebook.com/docs/opengraph/">Open Graph Protocol</a></h3>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/open_graph_protocol_logo.png"><img class="alignleft size-medium wp-image-1116" title="open_graph_protocol_logo" src="http://chusete.es/wp-content/uploads/2011/09/open_graph_protocol_logo-300x300.png" alt="" width="300" height="300" /></a>Esto no es una tecnología del core de Facebook propiamente dicha, pero sí es algo sobre lo que se apoya. ¿De qué se trata? Voy a explicarlo mediante un ejemplo. Supón que creas una página web de restaurantes, donde cada uno tiene su propia URL. Un día un usuario comparte esta URL en Facebook. ¿Qué ocurrirá? Que Facebook elegirá la información y las imágenes que él considere relevante. Pero, ¿y si quisiéramos nosotros decirle a Facebook (y otras redes sociales) la información que debe mostrar? Para dar respuesta a eso surge el protocolo Open Graph.</p>
<p>En otras palabras: Hace que nuestras páginas web se conviertan en objetos &#8220;del mundo real&#8221; con el que pueden interactuar las redes sociales. Películas, restaurantes, celebridades, etc.</p>
<p>En el caso concreto de Facebook, además, cuando un usuario haga clic en el plugin del botón &#8220;Me gusta&#8221; de una de tus páginas, será equivalente a que hiciera clic en &#8220;Me gusta&#8221; de alguna de las Facebook Pages, por lo que podrás enviarle actualizaciones a su Feed. Mola, ¿no?</p>
<p>Su funcionamiento no podría ser más sencillo. Open Graph Protocol está basado en <a href="http://es.wikipedia.org/wiki/RDFa">RDFa</a>, por lo que mediante etiquetas meta puedes añadir semántica a tus páginas. Además, para una correcta integración con Facebook, debes añadir el plugin del botón &#8220;Me gusta&#8221;.</p>
<p>Para más información, revisa la página oficial de Open Graph Protocol: <a href="http://ogp.me/">http://ogp.me/</a></p>
<h3>6. Otras tecnologías</h3>
<p>Además de todas las tecnologías que hemos visto, existen otras de tipo <em>avanzado</em> que, por lo general, no será necesario usarlas. En concreto estaríamos hablando de:</p>
<ul>
<li><strong><a href="http://developers.facebook.com/docs/reference/fql">FQL</a></strong>. Facebook Query Language, o Lenguaje de consultas de Facebook. Similar a SQL, sirve para consultar los datos que ofrece Graph API.</li>
<li><strong><a href="http://developers.facebook.com/docs/internationalization">API de internacionalización</a></strong>. Mediante esta API puedes aprovechar la infraestructura de internacionalización de Facebook para tu aplicación.</li>
<li><strong><a href="http://developers.facebook.com/docs/creditsapi">API de créditos</a></strong>. Para que los usuarios puedan realizar pagos de créditos de Facebook para utilizar en tu aplicación.</li>
<li><strong><a href="http://developers.facebook.com/docs/reference/ads-api">API de publicidad</a></strong>. Permite crear y gestionar mediante código tus campañas publicitarias.</li>
<li><strong><a href="http://developers.facebook.com/docs/chat">API de Chat</a></strong>. Para aquellos desarrolladores que quieran integrar el chat de Facebook en sus aplicaciones, mediante el protocolo estándar <a href="http://es.wikipedia.org/wiki/Extensible_Messaging_and_Presence_Protocol">Jabber/XMPP</a>.</li>
</ul>
<p><strong>APIs obsoletas</strong>. Además, existen determinadas APIs que han quedado obsoletas y a las que pronto Facebook dejará de dar soporte, como la API REST, el lenguaje de marcado FBML, o la API JavaScript.</p>
<h2>SDKs</h2>
<p>Por último, vamos a repasar los distintos kits de desarrollo que nos regala Facebook. Cabe destacar que no es imprescindible utilizarlos, ya que podremos realizar la autenticación, invocación de diálogos, o las llamadas a la API a mano. Pero, como podrás imaginar, resulta mucho más sencillo utilizar una herramienta ya probada que lo haga por nosotros.</p>
<p>Existen cuatro SDKs:</p>
<ol>
<li><a href="http://developers.facebook.com/docs/reference/javascript/">JavaScript SDK</a>.</li>
<li><a href="http://github.com/facebook/php-sdk/">PHP SDK</a>.</li>
<li><a href="http://developers.facebook.com/docs/reference/ios">iOS SDK (iPhone &amp; iPad)</a>.</li>
<li><a href="http://developers.facebook.com/docs/reference/android">Android SDK</a>.</li>
</ol>
<p>Aquí vamos a hablar de los dos primeros.</p>
<h3>1. JavaScript SDK</h3>
<p>Permite realizar llamadas a la Graph API, crear diálogos, renderizar los Social Plugins, además de otras muchas cosas. Para usar el SDK, debemos  intrducir el siguiente código a nuestra aplicación:</p>
<pre name="code" class="javascript">&lt;div id="fb-root"&gt;&lt;/div&gt;
&lt;script src="http://connect.facebook.net/en_US/all.js"&gt;&lt;/script&gt;
&lt;script&gt;
  FB.init({
    appId  : 'ID DE TU APP',
    status : true, // comprobar estado de login
    cookie : true, // habilitar cookies para permitir al servidor acceder a la sesión
    xfbml  : true, // ejecutar código XFBML
    channelURL : 'http://WWW.MIDOMINIO.COM/channel.html', // fichero channel.html
    oauth  : true // habilita OAuth 2.0
  });
&lt;/script&gt;</pre>
<p>Y en el fichero channel.html añades el siguiente contenido:</p>
<pre name="code" class="javascript">&lt;script src="http://connect.facebook.net/en_US/all.js"&gt;&lt;/script&gt;</pre>
<p>Y ya lo tienes. Tu página está preparada para ejecutar código del SDK JavaScript de Facebook.</p>
<div class="note">
<h3>JavaScript Test Console</h3>
<p>Del mismo modo que teníamos una herramienta para poder probar la Graph API, también tenemos una <a href="http://developers.facebook.com/tools/console/">consola de desarrollo para el SDK de JavaSript</a>. Para ello, accedemos a <a href="http://developers.facebook.com/tools/console/">http://developers.facebook.com/tools/console/</a> pulsamos sobre Login para concederle permisos a la aplicación de la consola de desarrollo, introducimos el código JavaScript que queremos probar, y pulsamos sobre &#8220;Run Code&#8221;.</p>
<p>Para hacer las cosas más fáciles, podemos pulsar sobre el botón &#8220;Examples&#8221; al pie del textarea, y seleccionamos el ejemplo que deseamos probar.</p>
</div>
<h3>2. PHP SDK</h3>
<p>El SDK oficial para PHP de Facebook es un proyecto open source que se encuentra alojado en GitHub:  <a href="https://github.com/facebook/php-sdk/">https://github.com/facebook/php-sdk/</a>.</p>
<p>Si bien existe un <a href="https://github.com/facebook/php-sdk/blob/master/examples/example.php">ejemplo básico</a>, pero completo, sobre su uso, vamos a resumir aquí las principales operaciones:</p>
<p>Código de inicialización:</p>
<pre name="code" class="php">require 'php-sdk/src/facebook.php';

$facebook = new Facebook(array(
  'appId'  =&gt; 'TU_APP_ID',
  'secret' =&gt; 'TU_APP_SECRET',
));

// Obtener ID de usuario
$user = $facebook-&gt;getUser();</pre>
<p>Llamada a la API (Graph API):</p>
<pre name="code" class="php">if ($user) {
  try {
    // Procedemos sabiendo que tenemos un usuario que ha iniciado sesión y concedido permisos.
    $user_profile = $facebook-&gt;api('/me');
  } catch (FacebookApiException $e) {
    error_log($e);
    $user = null;
  }
}</pre>
<p>Obtener URLs de inicio de sesión y de salida:</p>
<pre name="code" class="php">if ($user) {
  $logoutUrl = $facebook-&gt;getLogoutUrl();
} else {
  $loginUrl = $facebook-&gt;getLoginUrl();
}</pre>
<h2>Resumen</h2>
<p>Este ha sido un post bastante extenso, al que le seguirán otros con distintos casos de uso. Por lo pronto, hemos visto que es posible implementar distintos tipos de aplicaciones para Facebook: para el móvil, para una página web, y empotradas en Facebook. Hemos revisado paso a paso el proceso de alta de una nueva aplicación, donde establecemos los parámetros básicos, el nombre, logo, descripción, etc. También hemos revisado todas las tecnologías que nos ofrece Facebook para desarrollar aplicaciones en su ecosistema: Social Plugins, Diálogos, Autenticación y permisos, Graph API y Open Graph. Por último, hemos repasado las distintas bibliotecas que nos da Facebook para facilitar el desarrollo de aplicaciones en JavaScript, PHP, iOS y Android, centrándonos en las dos primeras.</p>
<p>Ahora que conocemos bien todo marco de trabajo sobre el que se apoyan las aplicaciones en Facebook, estamos listos para comenzar. En el siguiente post realizaremos una pequeña aplicación que sirva como demo de todos estos conceptos.
<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fchusete.es%2F2011%2F09%2F13%2Fintroduccion-a-la-programacion-en-facebook%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fchusete.es%2F2011%2F09%2F13%2Fintroduccion-a-la-programacion-en-facebook%2F&amp;source=chuso&amp;style=normal&amp;service=bit.ly&amp;service_api=R_86054639b9f90148987197dfdc061697&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://chusete.es/2011/09/13/introduccion-a-la-programacion-en-facebook/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Bibliotecas JavaScript: Motores de física</title>
		<link>http://chusete.es/2011/05/11/bibliotecas-javascript-motores-de-fisica/</link>
		<comments>http://chusete.es/2011/05/11/bibliotecas-javascript-motores-de-fisica/#comments</comments>
		<pubDate>Wed, 11 May 2011 20:09:23 +0000</pubDate>
		<dc:creator>chusete</dc:creator>
				<category><![CDATA[desarrollo]]></category>
		<category><![CDATA[javasctipt]]></category>
		<category><![CDATA[box2d]]></category>
		<category><![CDATA[física]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[juegos]]></category>

		<guid isPermaLink="false">http://chusete.es/?p=1039</guid>
		<description><![CDATA[Hoy hemos visto en el Google I/O la noticia de que Angry Birds estará disponible para el navegador Google Chrome. ¿Cómo es esto posible? Gracias al objeto canvas Ahora que HTML5 ha llegado para quedarse, y que incluso Internet Explorer ofrece soporte para el elemento canvas, poco a poco se irán popularizando las animaciones y [...]]]></description>
			<content:encoded><![CDATA[<p>Hoy hemos visto en el Google I/O la noticia de que <a href="http://es.engadget.com/2011/05/11/angry-birds-disponible-en-google-chrome/">Angry Birds estará disponible para el navegador Google Chrome</a>. ¿Cómo es esto posible? Gracias al objeto canvas <img src='http://chusete.es/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' />  Ahora que HTML5 ha llegado para quedarse, y que incluso Internet Explorer ofrece soporte para el elemento canvas, poco a poco se irán popularizando las animaciones y juegos en el navegador, sin necesidad de Flash. Uno de los elementos clave son los <strong><a href="http://es.wikipedia.org/wiki/Physics_engine">motores de física</a></strong>; consiste en una serie de bibliotecas que permiten modelar sistemas donde exista gravedad, y se puedan definir objetos rígidos o dinámicos, con coeficientes de fricción, elasticidad, etc. Suena bien, ¿verdad? <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Uno de los motores más populares es <a href="http://www.box2d.org/">box2d</a>. De hecho, es el que utiliza el propio <a href="http://www.rovio.com/index.php?page=angry-birds">Angry Birds</a>. Y por supuesto existen ports de esta biblioteca para muchísimos lenguajes de programación, incluido, claro está, el pequeño gran JavaScript. En concreto la <a href="http://box2d-js.sourceforge.net/">versión JavaScript</a> está extraída automáticamente de la <a href="http://www.box2dflash.org/">versión de ActionScript</a>. Si quieres ver algunos ejemplos en vivo, entra a la web de box2d-js. Lo que ahora vamos a hacer, lo puedes ver aquí abajo (prueba a hacer clic sobre el lienzo).</p>
<p><iframe style="width: 100%; height: 360px" src="http://jsfiddle.net/chuso/dJ5yd/16/embedded/result%2Cjs"></iframe>
<p>Dejemos de hablar, y vamos a mancharnos las manos <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<div class="note">
<h3>Aviso sobre este artículo</h3>
<p>El código en el que he basado este artículo está extraído de <a href="http://savagelook.com/blog/code/box2d-js-physics-in-html5-javascript-guide">savagelook.com</a>. Te recomiendo que entres y lo revises, ya que su ejemplo es más completo que la versión que yo aquí expongo.</p>
<p>Del mismo modo, es muy recomendable el <a href="http://www.box2dflash.org/docs/2.0.2/manual">manual de uso de box2d</a> que han hecho en Box2DFlash.</p>
</div>
<h3>Paso 1 &#8211; Preparando el entorno</h3>
<p>Lo primero que tenemos que hacer es crear el código HTML. box2djs depende de dos bibliotecas:</p>
<ol>
<li><a href="http://www.prototypejs.org/">Prototype</a>, como framework javascript.</li>
<li><a href="http://excanvas.sourceforge.net/">excanvas</a>, para añadir soporte canvas a Internet Explorer.</li>
</ol>
<p>Además, crearemos ya el objeto canvas, al que le estableceremos el ancho y alto, y sus propiedades CSS. Nos quedará el siguiente código:</p>
<pre class="html" name="code">
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&gt;
&lt;!--[if IE]&gt;&lt;script type="text/javascript" src="lib/excanvas.js"&gt;&lt;/script&gt;&lt;![endif]--&gt;
&lt;script src="lib/prototype-1.6.0.2.js"&gt;&lt;/script&gt;
&lt;script src="lib/box2djs.min.js"&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;canvas id="canvas-world" style="position:absolute; top:0; left:0;background-color:#F5F5F5;width:800px; height:500px;"&gt;&lt;/canvas&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p><a href="http://chusete.es/demos/box2d/step1.html">Ver demo</a>. Como vemos, no ocurre gran cosa. Tan sólo vemos una gran caja gris</p>
<h3>Paso 2 &#8211; Crear el mundo</h3>
<p>En este paso vamos a crear el mundo en el que todo sucederá. Vamos a ver el código JavaScript que hace lo define:</p>
<pre class="javascript" name="code">            var world;
            var ctx;
            var canvasWidth;
            var canvasHeight;

            // Función que crea el mundo.
            function createWorld() {
                var worldAABB = new b2AABB();
                worldAABB.minVertex.Set(-1000, -1000);
                worldAABB.maxVertex.Set(1000, 1000);
                var gravity = new b2Vec2(0, 300);
                var doSleep = true;
                world = new b2World(worldAABB, gravity, doSleep);

                return world;
            }

            // Punto de entrada principal. Cuando se cargue la ventana:
            Event.observe(window, 'load', function() {
                world = createWorld();
       		ctx = $('canvas-world').getContext('2d');

       		var canvasElm = $('canvas-world');
       		canvasWidth = parseInt(canvasElm.width);
       		canvasHeight = parseInt(canvasElm.height);
       		var canvasTop = parseInt(canvasElm.style.top);
       		var canvasLeft = parseInt(canvasElm.style.left);
            });</pre>
<p>En primer lugar definimos cuatro variables globales que utilizaremos en el resto de la aplicación. Después, definimos la función createWorld(), y finalmente vinculamos el evento &#8220;load&#8221; de la ventana, al código de la función anónima. Este código por ahora hace una llamada a createWorld(), extrae el lienzo 2d del canvas, y calcula su ancho/alto y sus coordenadas. Pero vamos a ver qué hace createWorld():</p>
<p>La primera línea crea un nuevo objeto de tipo b2AABB. Estos objetos definen un espacio en 2 dimensiones. En las dos líneas siguientes establecemos los extremos donde este espacio termina. En concreto nuestro espacio, worldAABB, va desde las coordenadas (-1000,-1000) hasta las coordenadas (1000,1000).</p>
<p>Después creamos un vector gravitacional. El primer valor, 0, corresponde a la gravedad horizontal. El segundo, 300, la gravedad vertical. Es decir, podemos crear una gravedad lateral <img src='http://chusete.es/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<p>Otra opción que definimos es la posibilidad de que los objetos se &#8220;duerman&#8221; cuando entren en reposo. Esto lo hacemos asignando true a la variabel doSleep.</p>
<p>Finalmente creamos el objeto mundo, de la clase b2World, pasándole como parámetros al constructor las variables que acabábamos de crear.</p>
<p><a href="/demos/box2d/step2.html">Ver demo</a>. En este caso, de nuevo no ocurre nada. Tan sólo hemos definido el modelo virtual, sin atarlo al canvas.</p>
<h3>Paso 3 &#8211; Crear un suelo</h3>
<p>En nuestro ejemplo va a haber un suelo. En resumen, tan sólo es una caja con posición fija ocupando toda la parte inferior visible. Este es el código que lo define:</p>
<pre class="javascript" name="code">            // Añade un suelo al mundo
            function createGround(world) {
                var groundSd = new b2BoxDef();
                groundSd.extents.Set(400, 30);
                groundSd.restitution = 0.0;
                var groundBd = new b2BodyDef();
                groundBd.AddShape(groundSd);
                groundBd.position.Set(400, 470);
                return world.CreateBody(groundBd);
            }</pre>
<p>Además, añadimos una llamada a createGround(world) antes del return de la función createWorld(). Vamos a ver en qué consiste la creación del suelo:</p>
<p>Primero creamos un objeto b2BoxDef, que no es más que un objeto que define una forma rectangular. A continuación establecemos su tamaño (400 x 30), y su elasticidad (0.0). El factor de elasticidad 0.0 es el mínimo. Cuanto más alto, más elástico será el material de la forma que estamos definiendo.</p>
<p>A continuación creamos un cuerpo físico, al que le añadimos la forma que acabamos de crear. Por último establecemos las coordenadas en las que lo colocamos (400, 470), y lo añadimos al mundo.</p>
<p><a href="/demos/box2d/step3.html">Ver demo</a>. Todavía no ocurre nada. Tan sólo hemos añadido la definición y las características del suelo, pero nuestro mundo todavía no se ha arrancado, ni se ha vinculado al canvas.</p>
<h3>Paso 4 &#8211; Dibujando en el lienzo</h3>
<p>Bien, ya vamos avanzando <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  En este paso vamos a implementar el código encargado de dibujar en el canvas nuestro mundo virtual. Veamos cómo es:</p>
<pre class="javascript" name="code">            function drawWorld(world, context) {
                for (var b = world.m_bodyList; b; b = b.m_next) {
                    for (var s = b.GetShapeList(); s != null; s = s.GetNext()) {
                        drawShape(s, context);
                    }
                }
            }

            function drawShape(shape, context) {
                context.strokeStyle = '#ffffff';
                context.fillStyle = "black";
                context.beginPath();
                switch (shape.m_type) {
                    case b2Shape.e_polyShape:
                        {
                            var poly = shape;
    				        var tV = b2Math.AddVV(poly.m_position, b2Math.b2MulMV(poly.m_R, poly.m_vertices[0]));
                            context.moveTo(tV.x, tV.y);

                            for (var i = 0; i &lt; poly.m_vertexCount; i++) {
                                var v = b2Math.AddVV(poly.m_position, b2Math.b2MulMV(poly.m_R, poly.m_vertices[i]));
                                context.lineTo(v.x, v.y);
                            }
                            context.lineTo(tV.x, tV.y);
                        }
                        break;
                }

                context.fill();
                context.stroke();
            }</pre>
<p>Si nunca has trabajado con canvas, este es un buen momento para que revises algún artículo. Por ejemplo, <a href="https://developer.mozilla.org/en/Canvas_tutorial/Basic_usage">este de Mozilla</a>, o <a href="http://thinkvitamin.com/code/how-to-draw-with-html-5-canvas/">este de Thinkvitamin</a>.</p>
<p>Por un lado tenemos la función drawWorld, que se encarga de recorrer cada uno de los objetos del mundo, y cada una de las formas que contienen los objetos, para finalmente llamar a la función drawShape, que dibujará en el lienzo canvas la forma.</p>
<p>Por otro lado tenemos drawShape, que es la función que dibuja cada forma. En primer lugar establecemos los colores de línea (stroke) y de relleno (fill). Posteriormente indicamos que vamos a comenzar a dibujar en el lienzo. A continuación dibujamos la forma que corresponda; por ahora tan sólo dibujamos polígonos.</p>
<p>Para cada polígono, calculamos las coordenadas de su primer vértice. A continuación, dibujamos líneas entre cada uno de los siguientes vértices que encontremos, hasta finalmente, cerrar el polígono.</p>
<p>Y por último indicamos al contexto del lienzo que renderice el relleno y las líneas.</p>
<p><a href="/demos/box2d/step4.html">Ver demo</a>. ¡Cómo es posible! ¡Todavía no ocurre nada! Esto es porque falta la función que da vida y que arranca al sistema. ¡Vamos al siguiente paso!</p>
<h3>Paso 5 &#8211; Arrancando el sistema</h3>
<p>Ya ha llegado el momento; vamos a unir nuestro sistema, con nuestro canvas, y a hacer que funcione en el tiempo. Para ello vamos a añadir una nueva función:</p>
<pre class="javascript" name="code">            function step(cnt) {
                var timeStep = 1.0/60;
                var iteration = 1;
                world.Step(timeStep, iteration);
                ctx.clearRect(0, 0, canvasWidth, canvasHeight);
                drawWorld(world, ctx);
                setTimeout('step(' + (cnt || 0) + ')', 10);
            }</pre>
<p>Y vamos a hacer que la función anónima que se ejecuta al cargar la página, invoque a esta función, añadiendo al final:</p>
<pre class="javascript">step();</pre>
<p>¿Qué hace step()? Cada vez que se invoca, realiza una nueva iteración en el sistema. En primer lugar establece los frames per second del sistema físico. Por convenio suele utilizarse a 60Hz, es decir, 1.0/60. En cada uno de estos instantes, se realizará una simulación con las equaciones físicas.</p>
<p>A continuación definimos el número de iteraciones por cada instante. Cuanto más bajo sea el valor, más precisión, así como mayor consumo de recursos.</p>
<p>En la tercera línea, indicamos al mundo que avance un nuevo paso. Es en este momento cuando se realizan todos los cálculos para ver en qué estado se encuentra cada objeto del sistema.</p>
<p>Después, limpiamos el lienzo, ya que en la siguiente línea hacemos una llamada a drawWorld para dibujar todo el sistema.</p>
<p>Finalmente establecemos un timeout para volver a ejecutar un paso (step()) en los siguientes 10 milisegundos.</p>
<p><a href="/demos/box2d/step5.html">Ver demo</a>. ¡Viva! Al fin se ve algo <img src='http://chusete.es/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' />  No es gran cosa, pero ya tenemos dibujado el suelo en nuestro lienzo.</p>
<h3>Paso 6 &#8211; Añadiendo más objetos al mundo</h3>
<p>El paso anterior ha estado bien, pero vamos a hacer que nuestro mundo sea más rico en detalles. En concreto vamos a añadir unos polígonos que escriban el mensaje &#8220;Hola Mundo!&#8221; <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Esta es la función que lo crea:</p>
<pre class="javascript" name="code">            function createBox(world, x, y, width, height, fixed) {
                if (typeof(fixed) == 'undefined') fixed = true;
                var boxSd = new b2BoxDef();
                if (!fixed) boxSd.density = 1.0;
                boxSd.restitution = 0.0;
                boxSd.friction = 1.0;
                boxSd.extents.Set(width, height);
                var boxBd = new b2BodyDef();
                boxBd.AddShape(boxSd);
                boxBd.position.Set(x,y);
                return world.CreateBody(boxBd);
            }

            function createHelloWorld() {
                // H
                createBox(world, 50, 420, 10, 20, false);
                createBox(world, 90, 420, 10, 20, false);
                createBox(world, 70, 395, 30, 5, false);
                createBox(world, 50, 370, 10, 20, false);
                createBox(world, 90, 370, 10, 20, false);

                // O
        	createBox(world, 140, 435, 20, 5, false);
        	createBox(world, 155, 405, 5, 25, false);
       		createBox(world, 125, 405, 5, 25, false);
        	createBox(world, 140, 375, 20, 5, false);

        	// L
       		createBox(world, 200, 435, 20, 5, false);
       		createBox(world, 185, 400, 5, 30, false);

       		// A
       		createBox(world, 240, 410, 5, 30, false);
       		createBox(world, 278, 425, 5, 15, false);
       		createBox(world, 265, 405, 20, 5, false);
       		createBox(world, 280, 390, 5, 10, false);
       		createBox(world, 260, 375, 25, 5, false);

        	// M
        	createBox(world, 390, 355, 40, 5, false);
       		createBox(world, 360, 400, 10, 40, false);
       		createBox(world, 420, 400, 10, 40, false);
       		createBox(world, 390, 400, 5, 40, false);

       		// U
       		createBox(world, 460, 435, 20, 5, false);
       		createBox(world, 445, 405, 5, 30, false);
       		createBox(world, 475, 405, 5, 30, false);

       		// N
                createBox(world, 495, 415, 5, 30, false);
                createBox(world, 525, 415, 5, 30, false);
        	createBox(world, 510, 375, 20, 5, false);

       		// D
       		createBox(world, 558, 435, 18, 5, false);
       		createBox(world, 545, 405, 5, 25, false);
       		createBox(world, 575, 405, 5, 25, false);
       		createBox(world, 558, 375, 18, 5, false);

       		// O
        	createBox(world, 610, 435, 20, 5, false);
        	createBox(world, 595, 405, 5, 25, false);
       		createBox(world, 625, 405, 5, 25, false);
       		createBox(world, 610, 375, 20, 5, false);

       		// !
       		createBox(world, 650, 430, 10, 10, false);
       		createBox(world, 650, 380, 10, 40, false);
            }</pre>
<p>Definimos en primer lugar la función createBox(). A partir de 6 parámetros crea una nueva caja en el mundo. En concreto los parámetros son: (1) objeto mundo, (2) coordenada x, (3) coordenada y, (4) ancho, (5) altura, y (6) si tiene o no posición fija.</p>
<p>Su código es prácticamente equivalente al código que usamos para crear el objeto suelo. Además, establecemos la densidad de los objetos que no tienen posición fija, y un coeficiente de rozamiento.</p>
<p>Luego tenemos la función createHelloWorld, que tan sólo crea rectángulos.</p>
<p>Por último, vamos a añadir una llamada a createHelloWorld(); antes de step(), en la función anónima que se ejecuta al cargar la ventana.</p>
<p><a href="/demos/box2d/step6.html">Ver demo</a>. La cosa ya va cambiando <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Ahora tenemos ya un montón de cajas, que hasta vemos cómo se tambalean.</p>
<h3>Paso 7 &#8211; Creando círculos</h3>
<p>Nuestro programa ya sabe cómo crear rectángulos en el sistema (createBox()), y cómo dibujarlos en el canvas. Ahora vamos a añadir la opción de crear círculos, y de dibujarlos. Primero, vamos a añadir esta función:</p>
<pre class="javascript" name="code">            function createBall(world, x, y) {
                var ballSd = new b2CircleDef();
                ballSd.density = 1.0;
                ballSd.radius = 20;
                ballSd.restitution = 0.5;
                ballSd.friction = 0.5;
                var ballBd = new b2BodyDef();
                ballBd.AddShape(ballSd);
                ballBd.position.Set(x,y);
                return world.CreateBody(ballBd);
            }</pre>
<p>Como vemos, es prácticamente igual que createBox(). En este caso al crear el objeto forma, no hemos elegido la clase b2BoxDef, sino b2CircleDef. Y además no tenemos la opción de especificar el tamaño, sino que todas las esferas tendrán el mismo radio, como vemos en &#8220;ballSd.radius = 20;&#8221;.</p>
<p>El sistema ya sabe añadir y reconocer círculos. Ahora vamos a indicarle cómo dibujarlos. En el switch de la función drawShape() que añadimos en el paso 4, vamos a añadir un nuevo caso:</p>
<pre class="javascript" name="code">                    case b2Shape.e_circleShape:
                        {
            				var circle = shape;
            				var pos = circle.m_position;
            				var r = circle.m_radius;
            				var segments = 16.0;
            				var theta = 0.0;
            				var dtheta = 2.0 * Math.PI / segments;
    				        context.moveTo(pos.x + r, pos.y);

    				        for (var i = 0; i &lt;= segments; i++) {
            					var d = new b2Vec2(r * Math.cos(theta), r * Math.sin(theta));
            					var v = b2Math.AddVV(pos, d);
            					context.lineTo(v.x, v.y);
            					theta += dtheta;
                            }
                            context.moveTo(pos.x, pos.y);
                            var ax = circle.m_R.col1;
                            var pos2 = new b2Vec2(pos.x + r * ax.x, pos.y + r * ax.y);
                            context.lineTo(pos2.x, pos2.y);
                        }
                        break;</pre>
<p>Ahora en la función drawShape(), en caso de que le proporcionen un círculo, sabrá cómo dibujarlo. En concreto lo hará dividiéndolo en 16 segmentos, y con un poco de trigonometría, se calculará el vector de cada segmento, y sus coordenadas finales.</p>
<p>Además, tras dibujar el círculo, se añadirá un radio, que nos permitirá observar cómo realmente gira el círculo.</p>
<p><a href="/demos/box2d/step7.html">Ver demo</a>. Nada nuevo, ya que todavía no hemos creado en ningún momento un círculo.</p>
<h3>Paso 8 &#8211; Creando objetos con el ratón</h3>
<p>Ahora vamos a ver cómo crear nuevos objetos al vuelto, haciendo clic con el ratón. Veremos también cómo impactan con los que ya hay, y cómo efectivamente se ve que se respetan las leyes físicas <img src='http://chusete.es/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Vamos a añadir este código antes de la llamada a step() en la función anónima:</p>
<pre class="javascript" name="code">                Event.observe('canvas-world', 'click', function(e) {
                    if (Math.random() &gt; 0.5) {
                        createBox(world, e.clientX, e.clientY, 10, 10, false);
                    } else {
                        createBall(world, Event.pointerX(e), Event.pointerY(e));
                    }
                });</pre>
<p>Al hacer clic en el canvas, habrá un 50% de probabilidades de que se cree o bien una caja, o bien un círculo. Lo interesante es que se creará donde hayamos hecho clic, y desde ahí caerá <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><a href="/demos/box2d/step8.html">Ver demo final</a>. Si quieres, también puedes <a href="/demos/box2d/tutorial_box2d-js.zip">descargarte el código completo</a>, con el ejemplo final documentando cada línea.</p>
<p>Por supuesto, ahora se pueden añadir imágenes de fondo al canvas, o añadir sprites a nuestros objetos. Y desde luego también se pueden añadir sonidos. <a href="http://www.effectgames.com/effect/article.psp.html/plugins/Box2D_Physics">Aquí tienes un ejemplo</a> prácticamente igual que el que acabamos de hacer, pero con sonidos y texturas:</p>
<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fchusete.es%2F2011%2F05%2F11%2Fbibliotecas-javascript-motores-de-fisica%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fchusete.es%2F2011%2F05%2F11%2Fbibliotecas-javascript-motores-de-fisica%2F&amp;source=chuso&amp;style=normal&amp;service=bit.ly&amp;service_api=R_86054639b9f90148987197dfdc061697&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://chusete.es/2011/05/11/bibliotecas-javascript-motores-de-fisica/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Mejorar el rendimiento de javascript con timers</title>
		<link>http://chusete.es/2010/10/18/mejorar-el-rendimiento-javascript-con-timers/</link>
		<comments>http://chusete.es/2010/10/18/mejorar-el-rendimiento-javascript-con-timers/#comments</comments>
		<pubDate>Mon, 18 Oct 2010 15:44:09 +0000</pubDate>
		<dc:creator>chusete</dc:creator>
				<category><![CDATA[desarrollo]]></category>
		<category><![CDATA[javasctipt]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[rendimiento]]></category>
		<category><![CDATA[timers]]></category>
		<category><![CDATA[web workers]]></category>

		<guid isPermaLink="false">http://chusete.es/?p=889</guid>
		<description><![CDATA[Uno de mis últimos encargos consiste en una aplicación financiera para el navegador. En resumen, se trata de &#8220;traducir&#8221; una serie de hojas en Excel a javascript. El cómo lo he implementado da para otro artículo. Básicamente el funcionamiento es el siguiente: Creamos un campo de texto por cada celda del fichero Excel. Muchas celdas [...]]]></description>
			<content:encoded><![CDATA[<p>Uno de mis últimos encargos consiste en una aplicación financiera para el navegador. En resumen, se trata de &#8220;traducir&#8221; una serie de hojas en Excel a javascript. El cómo lo he implementado da para otro artículo.</p>
<p>Básicamente el funcionamiento es el siguiente:</p>
<ul>
<li>Creamos un campo de texto por cada celda del fichero Excel.</li>
<li>Muchas celdas tienen valores dinámicos, es decir, se generan a partir del valor de otras.</li>
<li>Definimos la fórmula que genera el valor de cada celda dinámica, y esa fórmula la añadimos a la pila de callbacks del evento &#8216;change&#8217; de todas las celdas de las que depende.</li>
</ul>
<p>Problema: Hay miles de celdas, prácticamente todas dinámicas. Esto implica que a menudo, al cambiar un sólo valor, se generan cientos o miles de cálculos. Javascript es <em>single threaded</em>, es decir, sólo se ejecuta una única hebra (para realizar cálculos, modificar el árbol DOM, gestionar eventos, o redibujar la pantalla). Si una operación muy costa en cálculos conlleva 8 segundos, la interfaz de usuario se quedará bloqueada hasta que finalice. Mal asunto.</p>
<p>El experto en usabilidad Jakob Nielsen dijo:</p>
<blockquote><p><em>0,1 segundos es el límite para que el usuario perciba que el sistema responde inmediatamente.</em></p></blockquote>
<h2>¿Son los Web Workers la solución?</h2>
<p>Quizás te preguntes qué son los <a href="http://en.wikipedia.org/wiki/Web_Workers">Web Workers</a>. Se trata de una especificación de <a href="http://www.whatwg.org/">WHATWG</a>, el equipo que ha dado forma a lo que hoy conocemos como HTML5, para permitir programar aplicaciones multihebra en javascript, es decir, correr procesos en segundo plano.</p>
<p>Si bien es una funcionalidad que han empezando a incorporar recientemente los navegadores (<a href="http://www.webmonkey.com/2010/03/internet-explorer-9-shows-up-faster-but-still-lacking/">a excepción de IE9</a>), no es nada nuevo; el paquete Google Gears ya ofrecía estos mecanismos. De hecho, los web workers están basados en la API <a href="http://code.google.com/apis/gears/api_workerpool.html">WorkerPool</a> de Google Gears.</p>
<p>Por tanto, ¿son la solución al problema? Sí, pero&#8230;</p>
<p>A pesar de que una hoja de cálculo puede ser un ejemplo de libro para el uso de Web Workers, finalmente no los he utilizado. Existen algunas limitaciones, por cuestiones de seguridad, a la hora de usar Web Workers. A destacar, que no tiene acceso a:</p>
<ol>
<li>DOM.</li>
<li>objeto window.</li>
<li>objeto document.</li>
<li>objeto parent.</li>
</ol>
<p>Toda la comunicación con la hebra principal se realiza mediante mensajes. Esto interfiere con el código que ya tenía, de modo que implicaría reescribirlo en gran parte. No es una opción por desgracia.</p>
<p>Luego está el motivo de que no funcionan ni funcionarán en Internet Explorer.</p>
<h2>Timers al rescate</h2>
<p>Repasemos conceptos de sistemas operativos. En un sistema multitarea, en un momento dado no se pueden ejecutar más tareas que procesadores tiene el equipo. Por eso existe el <a href="http://en.wikipedia.org/wiki/Scheduling_(computing)">planificador de procesos</a>, que es la parte que se encarga de repartir el tiempo disponible entre los distintos procesos en ejecución. Si se asignan tiempos bajos de ejecución, el efecto será que están funcionando varios procesos concurrentemente. Sintetizando muchísimo, podríamos decir que el planificador de procesos se encarga de asignar bloques de tiempo a cada proceso.</p>
<p>Ahora repasemos los timers. ¿Qué hacen exactamente? Posponen la ejecución de un comando. Esto significa que, mientras se espera ese tiempo, el navegador queda libre para hacer otras cosas.</p>
<p>¿Y si añadimos pausas voluntarias en la propagación de eventos &#8216;change&#8217; de las celdas? De esta forma, habrá pausas que permitirán &#8220;descongelar&#8221; la interfaz de usuario, <strong>emulando</strong> que los cálculos se están ejecutando en un segundo plano, haciendo que la interfaz de usuario sea fluida. Miremos el siguiente gráfico:</p>
<p><a href="http://chusete.es/wp-content/uploads/2010/10/jstimers.png"><img class="alignnone size-medium wp-image-891" title="Relación de tiempo" src="http://chusete.es/wp-content/uploads/2010/10/jstimers-300x63.png" alt="Gráfico de relación de tiempos con y sin timers" width="300" height="63" /></a></p>
<p>El color azul representa los cálculos. El verde, es cuando no realizamos cálculos y la interfaz responde a eventos (el equivalente a este proceso en sistemas operativos se llama <em><a href="http://en.wikipedia.org/wiki/Idle_(CPU)">idle</a></em>).</p>
<p>En el primer caso no utilizamos timers. Lo que ocurre es que el navegador se queda congelado durante más de tres segundos.</p>
<p>Sin embargo, en el segundo caso añadimos pausas voluntarias, con lo que percibimos que en todo momento el navegador reacciona inmediatamente a nuestras acciones.</p>
<h2 id="demo">Demo</h2>
<p>He hecho una sencilla demo. El script se encarga de calcular los números primos menores de 300.000. En un caso con timers y en otro sin él:</p>
<ol>
<li><a href="http://chusete.es/demos/timers/sample01_without.html">Sin timers</a>. La página se quedará congelada hasta que finalice el cálculo.</li>
<li><a href="http://chusete.es/demos/timers/sample01_with.html">Con timers</a>. Podrás interactuar con la página mientras hace los cálculos.</li>
</ol>
<p>Si miramos el código, veremos que hay algunas diferencias. En el primer caso, esto es lo que ocurre:</p>
<pre>jQuery("#button").bind('click', function() {
  for (var i=1; i&lt;=300000; i++) {
    if(isPrime(i)) {
      jQuery('#prime').append(" "+ i);
    }
  }</pre>
<p>Comprobamos uno a uno cada número desde un bucle, y si es primo, lo mostramos en pantalla. Seguramente haga saltar un aviso en el navegador de que el script está llevando demasiado tiempo.</p>
<p>El segundo ejemplo es un poco más elaborado:</p>
<pre>function comprobarPrimo(numero, fin,total) {
  var delay = 10;
  var heap = 500;
  if (isPrime(numero)) {
    jQuery('#prime').append(" "+ numero);
  }
  if(++numero &lt; fin) {
    if (total%heap === 0) {
      setTimeout("comprobarPrimo("+numero+","+fin+","+(total+1)+")", delay);
    } else {
      comprobarPrimo(numero, fin, (total+1));
    }
  }
}

jQuery("#button").bind('click', function() {
  comprobarPrimo(1,300000,0);
});</pre>
<p>En lugar de usar un bucle, usamos una función recursiva. Esto lo hacemos porque, cada vez que llamamos a setTimeout, se ejecuta el código que le sigue sin esperar el delay. Es decir, que al añadir un timer no pararíamos realmente toda la ejecución. Con una función recursiva corregimos esto.</p>
<p>Y definimos dos variables: <em>delay</em>, que es el retardo en milisegundos que se aplicará, y <em>heap</em>, que define cada cuántas llamadas se aplica delay. En este ejemplo se establece un delay de 20 milisegundos que se aplica cada 500 números primos. Los otros 499 se ejecutan sin retardo.</p>
<p>El resultado es completamente distinto al del primer ejemplo. Y únicamente añadimos pausas de 20 milisegundos cada 500 números primos. Por supuesto el tiempo de ejecución se ve incrementado.
<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fchusete.es%2F2010%2F10%2F18%2Fmejorar-el-rendimiento-javascript-con-timers%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fchusete.es%2F2010%2F10%2F18%2Fmejorar-el-rendimiento-javascript-con-timers%2F&amp;source=chuso&amp;style=normal&amp;service=bit.ly&amp;service_api=R_86054639b9f90148987197dfdc061697&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://chusete.es/2010/10/18/mejorar-el-rendimiento-javascript-con-timers/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Programación basada en prototipos</title>
		<link>http://chusete.es/2010/08/23/programacion-basada-en-prototipos/</link>
		<comments>http://chusete.es/2010/08/23/programacion-basada-en-prototipos/#comments</comments>
		<pubDate>Sun, 22 Aug 2010 22:08:27 +0000</pubDate>
		<dc:creator>chusete</dc:creator>
				<category><![CDATA[javasctipt]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[programación orientada a objetos]]></category>
		<category><![CDATA[prototipos]]></category>

		<guid isPermaLink="false">http://chusete.es/?p=820</guid>
		<description><![CDATA[En los resúmenes de los distintos paradigmas de programación se suele mencionar la programación funcional, lógica, procedural, orientada a objetos&#8230; Dentro de la programación orientada a objetos, hay distintos tipos. El más conocido es el basado en clases, donde encontramos lenguajes como Java, C++, C#&#8230; Sin embargo, hay más tipos de programación orientada a objetos, [...]]]></description>
			<content:encoded><![CDATA[<p>En los resúmenes de los distintos paradigmas de programación se suele mencionar la programación funcional, lógica, procedural, orientada a objetos&#8230;</p>
<p>Dentro de la programación orientada a objetos, hay distintos tipos. El más conocido es el basado en clases, donde encontramos lenguajes como Java, C++, C#&#8230; Sin embargo, hay más tipos de programación orientada a objetos, y es usada por lenguajes muy conocidos. Me estoy refiriendo a la <strong>programación basada en prototipos</strong>, y su lenguaje más conocido es JavaScript.</p>
<p>Según la Wikipedia: <strong><em>Programación basada en prototipos</em></strong><em> es un estilo de </em><em>programación orientada a objetos</em><em> en el cual, las &#8220;clases&#8221; no están presentes, y la re-utilización de procesos (conocida como </em><em>herencia</em><em> en lenguajes basados en clases) se obtiene a través de la clonación de objetos ya existentes, que sirven de prototipos, extendiendo sus funcionalidades.</em></p>
<p>Es decir, se trata de un paradigma orientado a objetos sin clases. ¿Cómo es esto? En lugar de definir una clase, para después crear una instancia de ella, lo que hacemos es definir directamente el nuevo objeto, con sus métodos y atributos. En la página web de Mozilla tenemos un buen resumen de las <a href="https://developer.mozilla.org/en/JavaScript/Guide/Details_of_the_Object_Model#Summary_of_differences">diferencias existentes</a> entre la POO basada en prototipos y la basada en clases.</p>
<p>Una guía muy buena para entender, paso a paso, en qué consiste, y cómo funciona, es la que proporciona de nuevo Mozilla en su artículo &#8220;<a href="https://developer.mozilla.org/en/A_re-introduction_to_JavaScript">A re-introduction to JavaScript</a>&#8220;, en el apartado &#8220;<a href="https://developer.mozilla.org/en/A_re-introduction_to_JavaScript#Custom_objects">Custom Objects</a>&#8220;. Al no estar en español, voy a copiarlos aquí:</p>
<p><em>Consideremos un objeto persona con los campos nombre y apellido. Hay dos formas de mostrar: &#8220;nombre apellido&#8221; o &#8220;apellido, nombre&#8221;. Esta es una forma de hacerlo:</em></p>
<pre>function makePerson(first, last) {
    return {
        first: first,
        last: last
    }
}
function personFullName(person) {
    return person.first + ' ' + person.last;
}
function personFullNameReversed(person) {
    return person.last + ', ' + person.first
}</pre>
<p><em>Esto funciona, pero es bastante feo. Terminas con docenas de funciones y tu espacio de nombres global. Lo que realmente necesitamos es una forma de vincular una función a un objeto. Puesto que las funciones son objetos, esto es fácil:</em></p>
<pre>function makePerson(first, last) {
    return {
        first: first,
        last: last,
        fullName: function() {
            return this.first + ' ' + this.last;
        },
        fullNameReversed: function() {
            return this.last + ', ' + this.first;
        }
    }
}</pre>
<p><em>Podemos aprovechar la palabra clave &#8216;</em><code><em>this</em></code><em>&#8216; para mejorar nuestra función </em><code><em>makePerson</em></code><em>:</em></p>
<pre>function Person(first, last) {
    this.first = first;
    this.last = last;
    this.fullName = function() {
        return this.first + ' ' + this.last;
    }
    this.fullNameReversed = function() {
        return this.last + ', ' + this.first;
    }
}</pre>
<p><em>Nuestro objeto persona ha mejorado, pero aun tiene algunos flecos feos. Cada vez que creamos un objeto persona, estamos creando dos veces las funciones que hay en cada uno &#8211; ¿no sería genial si pudieran compartir este código?</em></p>
<pre>function personFullName() {
    return this.first + ' ' + this.last;
}
function personFullNameReversed() {
    return this.last + ', ' + this.first;
}
function Person(first, last) {
    this.first = first;
    this.last = last;
    this.fullName = personFullName;
    this.fullNameReversed = personFullNameReversed;
}</pre>
<p><em>Esto está mejor: estamos creando las funciones sólo una vez, y asignando referencias a ellas dentro del constructor. ¿Podemos hacerlo todavía mejor? La respuesta es sí:</em></p>
<pre>function Person(first, last) {
    this.first = first;
    this.last = last;
}
Person.prototype.fullName = function() {
    return this.first + ' ' + this.last;
}
Person.prototype.fullNameReversed = function() {
    return this.last + ', ' + this.first;
}</pre>
<p><code><em>Person.prototype</em></code><em> es un objeto compartido por todas las instancias de </em><code><em>Person</em></code><em>. Forma parte de una cadena de búsqueda (que tiene un nombre especial, &#8220;prototype chain&#8221;): cada vez que intentas acceder a una propiedad de </em><code><em>Person</em></code><em> que no está asignada, JavaScript comprobará en </em><code><em>Person.prototype</em></code><em> para ver si esta propiedad existe ahí. Como resultado, cualquier cosa que asignemos a </em><code><em>Person.prototype</em></code><em> estará disponible en todas las instancias de ese constructor mediante el objeto </em><code><em>this</em></code><em>.</em></p>
<p>Ahora, si os pasaba como a mí, ya tendréis claro qué es eso que hace tan &#8220;rarito&#8221; a JavaScript. Y se trata ni más ni menos de su forma de ser orientado a objetos.
<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fchusete.es%2F2010%2F08%2F23%2Fprogramacion-basada-en-prototipos%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fchusete.es%2F2010%2F08%2F23%2Fprogramacion-basada-en-prototipos%2F&amp;source=chuso&amp;style=normal&amp;service=bit.ly&amp;service_api=R_86054639b9f90148987197dfdc061697&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://chusete.es/2010/08/23/programacion-basada-en-prototipos/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Historial y botón volver en JavaScript</title>
		<link>http://chusete.es/2010/08/05/historial-y-boton-volver-en-javascript/</link>
		<comments>http://chusete.es/2010/08/05/historial-y-boton-volver-en-javascript/#comments</comments>
		<pubDate>Thu, 05 Aug 2010 16:43:26 +0000</pubDate>
		<dc:creator>chusete</dc:creator>
				<category><![CDATA[desarrollo]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[bbq]]></category>
		<category><![CDATA[botón volver]]></category>
		<category><![CDATA[hashchange]]></category>
		<category><![CDATA[historial]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[navegador]]></category>

		<guid isPermaLink="false">http://chusete.es/?p=812</guid>
		<description><![CDATA[Cada día son más frecuentes las aplicaciones web que hace un uso extensivo de JavaScript, relegando una mayor carga computacional al cliente, dentro de la arquitectura cliente-servidor, lo que habitualmente se conoce como cliente pesado. Con ello, entre otras cosas, se logra una interfaz de usuario mucho mas rica en prestaciones. Algunos ejemplos de webs [...]]]></description>
			<content:encoded><![CDATA[<p>Cada día son más frecuentes las aplicaciones web que hace un uso extensivo de JavaScript, relegando una mayor carga computacional al cliente, dentro de la arquitectura cliente-servidor, lo que habitualmente se conoce como <a href="http://es.wikipedia.org/wiki/Cliente_pesado">cliente pesado</a>. Con ello, entre otras cosas, se logra una interfaz de usuario mucho mas rica en prestaciones.</p>
<p>Algunos ejemplos de webs que hacen uso de esto es el cliente de correo de Google Gmail, o las famosas redes sociales como Facebook o Tuenti. En estas aplicaciones, toda la interfaz está gobernada por JavaScript. Cuando accedemos a un enlace, generalmente no conlleva una nueva petición HTTP sino que, en su lugar, el documento actual se actualiza con nuevo contenido (AJAX).</p>
<p>Pero existe un inconveniente: Al hacer las webs así, no se almacenan las actualizaciones de la página en el historial del navegador, de modo que los botones de volver y avanzar del navegador no funcionan como esperaríamos. Esto ocurre porque la URL no ha cambiado, y por tanto, para el navegador no ha habido ningún cambio de página.</p>
<p>Pero en Facebook o GMail, pese a funcionar con JavaScript, sí funciona el botón de volver. ¿Cómo lo hacen? La magia está en el caracter almohadilla (#). Repasemos HTML: Cuando en un documento queremos hacer un enlace a una parte del mismo (Por ejemplo, para saltar a un apartado), lo hacemos con el caracter almohadilla seguido de la palabra clave. Por ejemplo:</p>
<pre name="code" class="html">&lt;h1 id="top"&gt;Inicio&lt;/h1&gt;
&lt;p&gt;Un párrafo con mucho contenido...&lt;/p&gt;
&lt;a href="#top"&gt;Volver arriba&lt;/a&gt;</pre>
<p>Una de las ventajas de estos enlaces es que no conllevan una nueva petición HTTP, por lo que son inmediatos. Además, el navegador tiene constancia de ellos, por lo que los almacena en el historial. Bien, pues ahí está el truco. Si nos fijamos en una URL de Facebook, veremos que son de este tipo:</p>
<p>http://www.facebook.com/#!/?sk=messages&#038;filter=[fb]unread</p>
<p>Es decir, en este caso el enlace es a la página principal (http://www.facebook.com/) y <strong>dentro de ese documento</strong>, a un apartado (#!/?sk=messages&amp;filter=[fb]unread). Con JavaScript podemos consultar ese apartado para, en función de él, cargar el contenido que proceda. Ya tenemos todas las piezas para hacer una aplicación web en JavaScript, donde funcionará el historial del navegador, y además podremos guardar las URLs en nuestros marcadores.</p>
<h2>Acerca del evento hashchange</h2>
<p>Para poder realizar eso, necesitamos un método para que, desde JavaScript, sepamos cuándo se ha actualizado el historial #hash, es decir, para saber cuándo se enlaza a otro apartado dentro del documento actual. En HTML5 queda resuelto esto con el evento windows.onhashchange. Sin embargo, al ser un evento nuevo, no está disponible en todos los navegadores, por lo que se hacen necesarios algunos hacks que permitan que nuestra aplicación funcione en la mayoría de navegadores.</p>
<p>En el caso de utilizar jQuery, el plugin más extendido es jQuery BBQ. Podemos leer más acerca de cómo funciona aqui:<br />
<a href="http://benalman.com/projects/jquery-hashchange-plugin/">http://benalman.com/projects/jquery-hashchange-plugin/</a></p>
<h2>Implementación básica en jQuery</h2>
<p>Este ejemplo es muy sencillo. Únicamente tendremos una lista de enlaces, y marcaremos en negrita al activo, y mostraremos su contenido. Entendiendo eso, podremos aplicarlo a todo lo demás.</p>
<p>En primer lugar, necesitaríamos incluir la biblioteca <a href="http://jquery.com/">jquery</a>, y además también el <a href="http://benalman.com/projects/jquery-bbq-plugin/">plugin de jquery BBQ</a>.</p>
<pre name="code" class="html">&lt;!DOCTYPE html&gt;
&lt;html lang="es"&gt;
&lt;head&gt;
&lt;script type="text/javascript" src="jquery-1.4.1.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="jquery.ba-bbq.js"&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Después definimos una lista de enlaces y sus bloques de contenido:</p>
<pre name="code" class="html">&lt;ul&gt;
    &lt;a href="#enlace1"&gt;Enlace 1&lt;/a&gt;
    &lt;a href="#enlace2"&gt;Enlace 2&lt;/a&gt;
    &lt;a href="#enlace3"&gt;Enlace 3&lt;/a&gt;
    &lt;a href="#enlace4"&gt;Enlace 4&lt;/a&gt;
&lt;/ul&gt;
&lt;div id="enlaces"&gt;
    &lt;div id="enlace1"&gt;Contenido Enlace 1&lt;/div&gt;
    &lt;div id="enlace2"&gt;Contenido Enlace 2&lt;/div&gt;
    &lt;div id="enlace3"&gt;Contenido Enlace 3&lt;/div&gt;
    &lt;div id="enlace4"&gt;Contenido Enlace 4&lt;/div&gt;
&lt;/div&gt;</pre>
<p>Y ahora el código JavaScript:</p>
<pre name="code" class="javascript">$(function(){
  $(window).bind('hashchange', function(e) {
    var url = $.param.fragment();
    $('a.current').removeClass('current');
    if (url) {
        $('a[href="#' + url + '"]').addClass( 'current' );
        $("#enlaces &gt; div").hide();
        $("#"+url).show();
    }
  });

  $(window).trigger( 'hashchange' );

});</pre>
<p>El código hace lo siguiente:</p>
<ol>
<li>En primer lugar definimos una función que irá atada al evento &#8216;hashchange&#8217;. Este evento se dispara, como hemos visto, cada vez que se actualiza el #hash.</li>
<li>En segundo lugar, consultamos el parámetro #hash y lo almacenamos en la variable &#8216;url&#8217;.</li>
<li>Desactivamos el enlace previamente activo.</li>
<li>En caso de que esté definido el parámetro #hash:
<ol>
<li>Activamos el nuevo enlace activo. Tan sólo le añadimos una clase.</li>
<li>Ocultamos todos los bloques de contenido.</li>
<li>Mostramos el bloque de contenido activo.</li>
</ol>
</li>
<li>Lanzamos el evento hashchange para provocar una actualización, por si en la primera carga de la página ya hubiera un parámetro #hash (Por ejemplo, porque alguien ha guardado una URL en favoritos).</li>
</ol>
<p>Finalmente, definimos el estilo para la clase &#8220;current&#8221; y ya lo tenemos.</p>
<p>Podéis <a href="/demos/hashchange">probar una demo</a>. Como veis, tras moverte entre los distintos apartados, los botones de Volver y Avance del navegador funcionan. Además, se pueden almacenar las URLs para su futura consulta.
<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fchusete.es%2F2010%2F08%2F05%2Fhistorial-y-boton-volver-en-javascript%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fchusete.es%2F2010%2F08%2F05%2Fhistorial-y-boton-volver-en-javascript%2F&amp;source=chuso&amp;style=normal&amp;service=bit.ly&amp;service_api=R_86054639b9f90148987197dfdc061697&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://chusete.es/2010/08/05/historial-y-boton-volver-en-javascript/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>WebApps Working Group</title>
		<link>http://chusete.es/2009/12/23/webapps-working-group/</link>
		<comments>http://chusete.es/2009/12/23/webapps-working-group/#comments</comments>
		<pubDate>Wed, 23 Dec 2009 04:22:04 +0000</pubDate>
		<dc:creator>chusete</dc:creator>
				<category><![CDATA[javasctipt]]></category>
		<category><![CDATA[file API]]></category>
		<category><![CDATA[selectores]]></category>
		<category><![CDATA[w3c]]></category>
		<category><![CDATA[web SQL database]]></category>
		<category><![CDATA[web storage]]></category>
		<category><![CDATA[web workers]]></category>
		<category><![CDATA[webapps]]></category>
		<category><![CDATA[webScokes]]></category>
		<category><![CDATA[widgets]]></category>
		<category><![CDATA[workers]]></category>

		<guid isPermaLink="false">http://chusete.es/?p=670</guid>
		<description><![CDATA[Últimamente leo bastante la página del w3c (Qué acierto fue cambiar su diseño), y casi siempre me veo a mí mismo leyendo sobre el Grupo de Trabajo de Aplicaciones Web (WebApps Working Group). ¿Qué es? &#8220;El W3C Web Applications (WebApps) Working Group, una fusión de los grupos de trabajoWebAPI y WAF, se constituye para desarollar [...]]]></description>
			<content:encoded><![CDATA[<p>Últimamente leo bastante la página del <a href="http://www.w3.org">w3c</a> (Qué acierto fue cambiar su diseño), y casi siempre me veo a mí mismo leyendo sobre el Grupo de Trabajo de Aplicaciones Web (<a href="http://www.w3.org/2008/webapps/">WebApps Working Group</a>). ¿Qué es?</p>
<p>&#8220;<em>El W3C Web Applications (WebApps) Working Group, una fusión de los grupos de trabajoWebAPI y WAF, se constituye para desarollar APIs estándar para el desarrollo de Aplicaciones Web del lado del cliente. Este trabajo incluirá tanto la documentación de APIs existentes como el XMLHttpRequest, como el <strong>desarrollo de nuevas APIs que enriquezcan las aplicaciones web</strong>.</em>&#8221;</p>
<p>Veamos en qué consisten algunas de esas APIs que están desarrollando:</p>
<h2><a href="http://www.w3.org/TR/2009/CR-widgets-apis-20091222/">Interfaz para Widgets</a></h2>
<p>Cada widget podrá tener un documento de configuración que almacenará metadatos relativos al Widget. Además, cada instancia de un widget podrá almacenar datos de manera persistente.  ¿Cómo se hará esto? Gracias a otra API de almacenamiento de datos locales.</p>
<p>Está bastante maduro (En estado de <a href="http://www.w3.org/Consortium/Process/Process-19991111/tr.html#RecsCR">Recomendación Candidata</a>), y existe una <a href="http://dev.w3.org/2006/waf/widgets-api/test-suite/">suite de tests</a> para probar su correcta implementación.</p>
<h2><a href="http://www.w3.org/TR/2009/CR-selectors-api-20091222/">API de selectores Level 1</a></h2>
<p>Supongamos el siguiente bloque de código HTML 4.01:</p>
<pre>&lt;table id="score"&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Test
      &lt;th&gt;Result
  &lt;tfoot&gt;
    &lt;tr&gt;
      &lt;th&gt;Average
      &lt;td&gt;82%
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;A
      &lt;td&gt;87%
    &lt;tr&gt;
      &lt;td&gt;B
      &lt;td&gt;78%
    &lt;tr&gt;
      &lt;td&gt;C
      &lt;td&gt;81%
&lt;/table&gt;</pre>
<p>Si quisiéramos obtener los valores de todas las celdas tendríamos que ejecutar algo similar a esto con la API de DOM Level 2:</p>
<pre>var table = document.getElementById("score");
var groups = table.tBodies;
var rows = null;
var cells = [];

for (var i = 0; i &lt; groups.length; i++) {
  rows = groups[i].rows;
  for (var j = 0; j &lt; rows.length; j++) {
    cells.push(rows[j].cells[1]);
  }
}
</pre>
<p>¡Qué feo! La nueva API permite hacerlo de este modo mucho más conciso:</p>
<pre>
<pre>var cells = document.querySelectorAll("#score&gt;tbody&gt;tr&gt;td:nth-of-type(2)");</pre>
</pre>
<p>Como véis, es exactamente igual que lo que ya hacemos con los <a href="http://docs.jquery.com/Selectors">selectores de jQuery</a>, salvo que en un tiempo podremos realizarlo directamente desde el motor de JavaScript del navegador, sin necesidad de frameworks.</p>
<p>Esta API también está muy madura, y al igual que la anterior es una Recomendación Candidata. Está disponible en <a href="https://developer.mozilla.org/En/Code_snippets/QuerySelector">Firefox</a> desde su versión 3.1+, en Internet Explorer 8 y en Safari 3.1+. Pero hasta que no borremos del mapa a IE6 e IE7 tendremos que seguir utilizando herramientas como jQuery.</p>
<h2><a href="http://www.w3.org/TR/2009/WD-webstorage-20091222/">Web Storage</a></h2>
<p>Es un nuevo mecanismo de almacenamiento local que, a diferencia de las Cookies, permite almacenar un gran volumen de datos (Por ejemplo, los emails de una cuenta, haciendo innecesario plugins como <a href="http://code.google.com/apis/gears/">Google Gears</a>), y también permite almacenarlo accesible a todas las ventanas del dominio al que pertenecen.</p>
<p>Todo se realizaría de un modo muy sencillo: Simplemente accediendo al atributo que proceda dentro del objeto <a href="http://www.w3.org/TR/2009/WD-webstorage-20091222/#dom-localstorage">localStorage</a>.</p>
<p>De nuevo, está disponible ya en <a href="https://developer.mozilla.org/en/DOM/Storage">Firefox</a> 3.5, IE8, <a href="http://developer.apple.com/safari/library/documentation/iPhone/Conceptual/SafariJSDatabaseGuide/Name-ValueStorage/Name-ValueStorage.html">Safari 4.0</a>, Chromium&#8230;</p>
<h2><a href="http://www.w3.org/TR/2009/WD-workers-20091222/">Web Workers</a></h2>
<p>Permite lanzar distintos hilos de ejecución que se ejecutan en paralelo a la página principal. De este modo, se puede trabjar en un entorno thread-like trabajando con un mecanismo de coordinación de pase de mensajes.</p>
<p>Como ejemplos, podríamos:</p>
<ul>
<li>Generar una hebra que busque números primos en background.</li>
<li>Un worker que actualice una base de datos local. Estaría permanentemente escuchando al servidor mediante un WebSocket, y cuando hubiera algún cambio, modificaría la base de datos local.</li>
<li>Operaciones de Lectura/Escritura de fondo.</li>
<li>Workers compartido. Distintas ventanas podría compartir un único Worker que, en un momento dado, podría actualizar a todas a la vez.</li>
<li>Delegación. Aprovechando las distintas CPUs de los microprocesadores multi-core.</li>
</ul>
<p>Lógicamente, esto abre un gran número de posibilidades en cuanto al rendimiento de las páginas web.</p>
<p>Por el momento disponible en <a href="https://developer.mozilla.org/En/Using_web_workers">Firefox 3.5+</a>, Safari 4, Chromium.</p>
<h2><a href="http://www.w3.org/TR/2009/WD-eventsource-20091222/">Server-Sent Events</a></h2>
<p>La API que define esta especificación puede no parecer muy revolucionaria: Permite recivir notificaciones PUSH desde el servidor en forma de evento DOM. Perfectamente podemos lograr el mismo objetivo mediante XHR o un iframe. Sin embargo, dada su naturaleza, permitiria que, cuando el navegador se pueda coordinar con el operador de red, se ahorraran notablemente recursos de red. Uno de los efectos colaterales sería aumentar la duración de las baterías de los dispositivos portátiles.</p>
<h2><a href="http://www.w3.org/TR/2009/WD-websockets-20091222/">WebSockets API</a></h2>
<p>Esta API permite una auténtica conexión bidireccional entre el navegador y el servidor. Ya fue cubierta en <a href="/2009/12/11/google-chrome-ahora-con-web-sockets/">este blog</a> cuando Google Chrome anunció su implementación.</p>
<h2><a href="http://www.w3.org/TR/2009/WD-webdatabase-20091222/">Web SQL Database</a></h2>
<p>Es exactamente lo que su nombre sugiere. Consiste en una especificación de un API que permitirá almacenar información en una base de datos locale accesible mediante SQL.</p>
<p>Veamos un ejemplo de su funcionamiento:</p>
<pre>function prepareDatabase(ready, error) {
  return openDatabase('documents', '1.0', 'Offline document storage', 5*1024*1024, function (db) {
    db.changeVersion('', '1.0', function (t) {
      t.executeSql('CREATE TABLE docids (id, name)');
    }, error);
  });
}

function showDocCount(db, span) {
  db.readTransaction(function (t) {
    t.executeSql('SELECT COUNT(*) AS c FROM docids', [], function (t, r) {
      span.textContent = r.rows[0].c;
    }, function (t, e) {
      // couldn't read database
      span.textContent = '(unknown: ' + e.message + ')';
    });
  });
}

prepareDatabase(function(db) {
  // got database
  var span = document.getElementById('doc-count');
  showDocCount(db, span);
}, function (e) {
  // error getting database
  alert(e.message);
});</pre>
<p>En primer lugar se define la función   <code>prepareDatabase()</code> que, en caso de que fuera necesario, crea la base de datos con una tabla llamada &#8220;docids&#8221; con dos columnas (&#8220;id&#8221; y &#8220;name&#8221;). Si hay éxito, o no es necesario crearla, se llama a la función <code>getDatabase()</code>, que obtiene un manejador de la base de datos, y entonces llama a la función que hace realmente el trabajo, en este caso <code>showDocCount()</code>.</p>
<h2><a href="http://dev.w3.org/2006/webapi/FileAPI/">File API</a></h2>
<p>Como último ejemplo de apartados en los que trabaja el WebApps Working Group, voy a mosotrar la File API. Permitirá un manejo avanzado de ficheros desde JavaScript, pudiendo:</p>
<ul>
<li>Una vez que el usuario conceda permisos, el navegador permitirá leer y parsear un fichero.</li>
<li>Se podrá almacenar información de forma local.</li>
<li>Se permitirá guardar los archivos, del mismo modo que ahora se pueden descargar ficheros de servidores remotos.</li>
<li>Se podrán enviar ficheros grandes a servidores de un modo más eficiente que el actual. Por ejemplo, se podrá dividir en porciones.</li>
<li>Los navegadores implementarán mecanismos para poder cancelar o impedir los casos de uso enumerados anteriormente.</li>
</ul>
<hr />Sin duda, APIs como éstas permitirán realizar aplicaciones reales que funcionen en el navegador sin necesidad de un servidor. Como ejemplo, un reproductor multimedia avanzado, que guarde una caché local con metadatos de nuestra música y películas.</p>
<p>Creo que muy pronto comenzaremos a ver todas estas nuevas aplicaciones ir aparenciendo, poco a poco, hasta que un día el navegador realmente sea un framework de aplicaciones más.
<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fchusete.es%2F2009%2F12%2F23%2Fwebapps-working-group%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fchusete.es%2F2009%2F12%2F23%2Fwebapps-working-group%2F&amp;source=chuso&amp;style=normal&amp;service=bit.ly&amp;service_api=R_86054639b9f90148987197dfdc061697&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://chusete.es/2009/12/23/webapps-working-group/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Vídeo, audio e imágenes de entrada al navegador</title>
		<link>http://chusete.es/2009/12/21/video-audio-e-imagenes-de-entrada-al-navegador/</link>
		<comments>http://chusete.es/2009/12/21/video-audio-e-imagenes-de-entrada-al-navegador/#comments</comments>
		<pubDate>Mon, 21 Dec 2009 01:39:10 +0000</pubDate>
		<dc:creator>chusete</dc:creator>
				<category><![CDATA[javasctipt]]></category>
		<category><![CDATA[cámara]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[microfono]]></category>
		<category><![CDATA[w3c]]></category>
		<category><![CDATA[webcam]]></category>

		<guid isPermaLink="false">http://chusete.es/?p=665</guid>
		<description><![CDATA[Hace poco se ha publicado un nuevo borrador del w3c (The Capture API) que permitirá conectar dispositivos de entrada al navegador, permitiendo por ejemplo capturar una fotografía, mensaje de audio por el micrófono, o un vídeo. Aun se encuentra en un estado muy prematuro, pero nos enumeran una serie de posibles casos de uso: Captura [...]]]></description>
			<content:encoded><![CDATA[<p>Hace poco se ha publicado un nuevo borrador del w3c (<a href="http://dev.w3.org/2009/dap/camera/">The Capture API</a>) que permitirá conectar dispositivos de entrada al navegador, permitiendo por ejemplo capturar una fotografía, mensaje de audio por el micrófono, o un vídeo.</p>
<p>Aun se encuentra en un estado muy prematuro, pero nos enumeran una serie de posibles casos de uso:</p>
<ul>
<li><strong>Captura y envío de imágenes.</strong> Permitiendo el envío por XHR de varias imágenes.</li>
<li><strong>Captura de imagen panorámica.</strong> Por ejemplo, con 3 tomas que posteriormente se &#8220;concatenan&#8221; automáticamente para mostrar la panorámica.</li>
<li><strong>Video Chat</strong>. Aun está sin definir el método para realizar streaming, sin embargo todas las soluciones propuestas pasan por <a href="http://chusete.es/2009/12/11/google-chrome-ahora-con-web-sockets/">websockets</a>.</li>
<li><strong>Cámara web.</strong> Permitirá realizar una aplicacion de vigilancia para controlar la cámara, incluyendo movimientos como arriba, abajo, izquierda o derecha, o hasta aplicaciones de detección de movimiento.</li>
<li><strong>Búsqueda por voz.</strong> Introduciendo por el micrófono la cadena de búsqueda.</li>
<li><strong>Recordatorio de voz.</strong> De nuevo, desde el micrófono.</li>
</ul>
<p>Por supuesto, para proteger la privacidad de los usuarios, el navegador tendrá que pedir explícitamente confirmación del usuario para permitir que se acceda a estos dispositivos.</p>
<p>Ejemplo de uso:</p>
<pre name="code" class="javascript">
// Create a container div element and append it to the document body.
var container = document.createElement("div");
document.body.appendChild(container);

// The browser viewport width in pixels.
var screenWidth = window.innerWidth;

function successCallback(data) {
for (var i in data) {
var img = document.createElement("img");
img.src = data[i].uri;
// If the image width exceeds that of the browser viewport, the image
// is scaled to fit the screen keeping the aspect ratio intact.
if (data[i].format.width > screenWidth) {
img.style.width = screenWidth + "px";
img.style.height = (data[i].format.height/data[i].format.width)*screenWidth + "px";
}
container.appendChild(img);
}
}

function errorCallback(err) {
alert(err.message + " (" + err.code + ")");
}

// Launch the device camera application and invoke the callback once
// the user exits the camera application.
transactionId = navigator.device.captureImage(successCallback, 1, errorCallback);
</pre>
<p>Mientras tanto, y hasta que esto sea una realidad, se puede utilizar el paquete <a href="http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/media/package-detail.html">flash.media de ActionScript3</a>, en concreto las clases <a href="http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/media/Camera.html">Camera</a> y <a href="http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/media/Microphone.html">Micrphone</a>. Pero claro, no es lo mismo. Una verdadera lástima tener que esperar tanto tiempo. Veremos cuándo tiene el navegador más utilizado estas funcionalidades.</p>
<p><span> </span>
<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fchusete.es%2F2009%2F12%2F21%2Fvideo-audio-e-imagenes-de-entrada-al-navegador%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fchusete.es%2F2009%2F12%2F21%2Fvideo-audio-e-imagenes-de-entrada-al-navegador%2F&amp;source=chuso&amp;style=normal&amp;service=bit.ly&amp;service_api=R_86054639b9f90148987197dfdc061697&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://chusete.es/2009/12/21/video-audio-e-imagenes-de-entrada-al-navegador/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

