<?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>Digital Icon: Desarrollo web versátil</title>
	<atom:link href="http://digitalicon.es/feed/" rel="self" type="application/rss+xml" />
	<link>http://digitalicon.es</link>
	<description></description>
	<lastBuildDate>Fri, 04 May 2012 13:12:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Probamos Zippopotam.us</title>
		<link>http://digitalicon.es/blog/probamos-zippopotam-us/</link>
		<comments>http://digitalicon.es/blog/probamos-zippopotam-us/#comments</comments>
		<pubDate>Fri, 04 May 2012 13:12:56 +0000</pubDate>
		<dc:creator>Saúl González Fernández</dc:creator>
				<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://digitalicon.es/?p=3220</guid>
		<description><![CDATA[Probamos Zippopotam.us, una <abbr title="Application Programming Interface">API</abbr> de la que extraer datos asociados a un código postal.]]></description>
			<content:encoded><![CDATA[<p id="intro">¿Al lector le suena <a href="http://www.zippopotam.us/">Zippopotam.us</a>? Ciertamente a nosotros no hasta que hace unas horas nos hemos encontrado la referencia en <a href="http://css-tricks.com/using-ziptastic/">esta entrada de CSS-Tricks</a>. Básicamente se trata de una <abbr title="Application Programming Interface">API</abbr> que devuelve datos asociados a un código postal en formato <abbr title="JavaScript Object Notation">JSON</abbr>. Y hemos querido probarla.</p>
<h2>¿Y para qué sirve?</h2>
<p>La aplicación más obvia es la que se indica en la entrada del blog que hemos vinculado: rellenar campos de un formulario para ahorrarle el esfuerzo al usuario. Lo que la <abbr>API</abbr> hace es devolver a una petición como <var>api.zippopotam.us/ES/01001</var> un documento con este contenido:</p>
<pre><code>
{
  "post code": "01001",
  "country": "Spain",
  "country abbreviation": "ES",
  "places": [
    {
      "place name": "Vitoria-Gasteiz",
      "longitude": "-2.6667",
      "state": "Pais Vasco",
      "state abbreviation": "PV",
      "latitude": "42.85"
    }
  ]
}
 </code></pre>
<p>En <a href="http://digitalicon.es/ejemplos/form-zippopotamus/">nuestra demo</a> simplemente hacemos la petición cuando el usuario introduce cinco caracteres de código postal, y con los datos recibidos rellenamos los demás campos. Lo de incluir un mapa de Google no era más que por aprovechar la información acerca de la latitud y la longitud.</p>
<p>El <i lang="en" xml:lang="en">script</i> es el que sigue, que por agilizar hemos basado en jQuery:</p>
<pre><code>
$(document).ready(function(){
  $('input').val('');
  $('#mapa').html('');
  $('#cp').keyup(function(){
    if($('#cp').val().length==5){
      $.ajax({
        url: 'zippo.php',
        cache: false,
        type: 'GET',
        data: 'cp='+$('#cp').val(),
        success: function(datos){
          datos = $.parseJSON(datos);
          if(datos.places){
            $('#poblacion').val(datos.places[0]['place name']);
            $('#provincia').val(datos.places[0]['state']);
            if(GBrowserIsCompatible()){
              var mapa = new GMap2(document.getElementById('mapa'));
              mapa.setCenter(new GLatLng(datos.places[0]['latitude'],datos.places[0]['longitude']),13);
              mapa.addOverlay(new GMarker(new GLatLng(datos.places[0]['latitude'],datos.places[0]['longitude'])));&nbsp;
            }
          } else {
            $('#poblacion').val('');
            $('#provincia').val('');
            $('#mapa').html('&lt;p id="error"&gt;No parece que haya datos para ese CP&lt;/p&gt;');
          }
        }
      });
    }
  });
});
 </code></pre>
<p>Un apunte: la llamada por AJAX no la estamos haciendo directamente a la dirección de la <abbr>API</abbr> porque no funciona, ni siquiera en <a href="http://www.zippopotam.us/static/sample_es.html">la prueba de la propia página de Zippopotam.us</a>; pensamos que puede ser porque el documento que devuelve no cuenta con extensión, aunque no estamos seguros. Para solventar este problema, cargamos <strong>zippo.php</strong>, que proporciona a nuestro <i lang="en" xml:lang="en">script</i> el contenido del documento, y cuyo código es éste:</p>
<pre><code>
&lt;?php
  $c = curl_init();
  curl_setopt($c,CURLOPT_RETURNTRANSFER,1);
  curl_setopt($c,CURLOPT_HEADER,0);
  curl_setopt($c,CURLOPT_URL,'http://api.zippopotam.us/ES/'.$_GET['cp']);&nbsp;
  $json = curl_exec($c);
  curl_close($c);
  echo $json;
?&gt;
 </code></pre>
<h2><i lang="la" xml:lang="la">Caveat lector</i></h2>
<p>Para finalizar, queremos indicar que hemos hecho esta prueba por contar con una herramienta más en nuestro haber, pero de cara a aplicarla en un proyecto real habría que tener en cuenta algunas limitaciones:</p>
<ul>
<li>Los datos que devuelve la <abbr>API</abbr> proceden de <a href="http://www.geonames.org/">GeoNames</a>, por lo que son todo lo exactos que hayan sido registrados en esa base de datos. Como detalle, nos habría convencido más si la ortografía fuera un poco más correcta.</li>
<li>El <abbr>JSON</abbr> que proporciona a veces cuenta con varios sitios en <var>places</var>; estamos asumiendo que el primero de ellos es el más relevante.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://digitalicon.es/blog/probamos-zippopotam-us/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Compartir una entrada de WordPress en Twitter con Tinyurl</title>
		<link>http://digitalicon.es/blog/compartir-entrada-wordpress-twitter-tinyurl/</link>
		<comments>http://digitalicon.es/blog/compartir-entrada-wordpress-twitter-tinyurl/#comments</comments>
		<pubDate>Thu, 15 Mar 2012 11:20:30 +0000</pubDate>
		<dc:creator>Saúl González Fernández</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://digitalicon.es/?p=3164</guid>
		<description><![CDATA[Creamos una sencilla función para incluir un vínculo de compartir en Twitter en una entrada de WordPress sin necesidad de un <i lang="en" xml:lang="en">plugin</i>.]]></description>
			<content:encoded><![CDATA[<p id="intro">Hace poco un conocido me preguntó qué <i lang="en" xml:lang="en">plugin</i> de WordPress había empleado en la página de <a href="http://relatosbluetales.com/">otro de mis proyectos</a> para compartir publicaciones en Twitter generando una dirección abreviada de <a href="http://tinyurl.com/" hreflang="en">Tinyurl</a>. Como comenté <a href="http://digitalicon.es/blog/anadir-meta-description-individual-entradas-wordpress/">en una entrada del mes pasado</a>, ese tipo de funcionalidad prefiero implementarla por código en el tema.</p>
<p>En el archivo <strong>functions.php</strong> de mi tema de WordPress creo esta función:</p>
<pre><code>
function tinyURL($url){
  if(!is_preview()){
    $c = curl_init();
    curl_setopt($c,CURLOPT_RETURNTRANSFER,1);
    curl_setopt($c,CURLOPT_HEADER,0);
    curl_setopt($c,CURLOPT_URL,&quot;http://tinyurl.com/api-create.php?url=&quot;.$url);&nbsp;
    $tiny = curl_exec($c);
    curl_close($c);
    return $tiny;
  }
}
 </code></pre>
<p>Y en <strong>loop.php</strong>, para cuando se trata de una entrada de blog añado al pie esta línea:</p>
<pre><code>
&lt;a href=&quot;http://twitter.com/home?status=%23relatosbluetales%20<i>&lt;?php echo tinyURL(wp_get_shortlink()); ?&gt;</i>&quot;&gt;[…]&lt;/a&gt;&nbsp;
 </code></pre>
<p>Simple y efectivo.</p>
]]></content:encoded>
			<wfw:commentRss>http://digitalicon.es/blog/compartir-entrada-wordpress-twitter-tinyurl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Un acordeón fallido con CSS3</title>
		<link>http://digitalicon.es/blog/acordeon-fallido-css3/</link>
		<comments>http://digitalicon.es/blog/acordeon-fallido-css3/#comments</comments>
		<pubDate>Thu, 01 Mar 2012 08:50:54 +0000</pubDate>
		<dc:creator>Saúl González Fernández</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[css3]]></category>
		<category><![CDATA[efectos javascript]]></category>
		<category><![CDATA[javascript no obstrusivo]]></category>

		<guid isPermaLink="false">http://digitalicon.es/?p=3162</guid>
		<description><![CDATA[Creamos una interfaz de acordeón con un híbrido de transiciones de <abbr title="Cascading Style Sheets">CSS</abbr>3 y JavaScript.]]></description>
			<content:encoded><![CDATA[<p id="intro">Como ya he mostrado en entradas anteriores &mdash;<a href="http://digitalicon.es/blog/menus-desplegables-animados-css3/">para menús desplegables</a> o <a href="http://digitalicon.es/blog/replicando-comportamiento-barra-navegacion-apple/">replicando la barra de Apple</a>&mdash;, creo que es una buena idea emplear los efectos de transición de <abbr>CSS</abbr>3 para crear animaciones de interfaz en lugar de JavaScript puro. Siguiendo en esta línea, he estado probando crear un acordeón mediante estilos sin más. El resultado ha sido un fracaso, pero uno muy enriquecedor.</p>
<h2>El punto de partida</h2>
<p>La idea inicial era emplear <a href="http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#target-pseudo" hreflang="en">la pseudoclase <code>:target</code></a> para variar la altura de los elementos con los contenidos a mostrar. El marcado es el siguiente:</p>
<pre><code>
&lt;ul id=&quot;menu1&quot;&gt;
  &lt;li&gt;
    &lt;a href=&quot;#menu11&quot;&gt;Lorem ipsum&lt;/a&gt;
    &lt;div id=&quot;menu11&quot;&gt;
      &lt;p lang=&quot;la&quot;&gt;Lorem ipsum dolor sit amet [&hellip;] &lt;/p&gt;&nbsp;
    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;a href=&quot;#menu12&quot;&gt;Lorem ipsum&lt;/a&gt;
    &lt;div id=&quot;menu12&quot;&gt;
      &lt;p lang=&quot;la&quot;&gt;Duis aute irure dolor [&hellip;] &lt;/p&gt;
    &lt;/div&gt;
  &lt;/li&gt;
  &hellip;
    &lt;!-- Todos los elementos que hagan falta --&gt;
  &hellip;
&lt;/ul&gt;
 </code></pre>
<p>Con asignar una altura inicial de <code>0</code> a los <code>div</code> y otra altura a su <code>:target</code>, parecía suficiente:</p>
<pre><code>
ul div{
  background: #FFF;
  -moz-transition: .75s;     /* Que no se diga que somos en parte responsables */&nbsp;
  -ms-transition: .75s;      /* de la debacle de -webkit-. */
  -webkit-transition: .75s;
  -o-transition: .75s;       /* Si no se entiende la referencia, */
  transition: .75s;          /* aquí hay <a href="http://css-tricks.com/tldr-on-vendor-prefix-drama/" hreflang="en">un compendio de vínculos relevantes</a>. */
  overflow: hidden;
  height: 0;
}
  &hellip;
#menu1 div:target{
  height: 16em;
}
 </code></pre>
<p>Así, el <a href="http://digitalicon.es/ejemplos/acordeon-css3/acordeon01.htm">ejemplo funciona</a>&#8230; pero <strong>desgraciadamente funciona sólo como ejemplo</strong>. ¿A qué me refiero? A que aislado, el acordeón se comporta como deseamos, pero incluido en una página real mostraría un comportamiento tarado. <a href="http://digitalicon.es/ejemplos/acordeon-css3/acordeon02.htm">Si incluimos otro acordeón</a>, cuando activamos uno de los dos el elemento desplegado del otro se contrae al perder el foco del vínculo. Igual ocurriría al hacer clic sobre cualquier otro vínculo del documento.</p>
<h2>JavaScript al rescate</h2>
<p>No obstante, empleando algo de JavaScript, podemos corregir este problema y algunos otros detalles, como son:</p>
<ul>
<li>Las transiciones de <abbr>CSS</abbr>3 no funcionan desde o hacia un valor de <code>auto</code>. En el ejemplo hemos asignado un valor de <code>16em</code> calculándolo por aproximación sobre la cantidad de contenido que tenemos, pero no serviría si ésta fuese indeterminada.</li>
<li>Al hacer clic en el vínculo, se actualiza el <i lang="en" xml:lang="en">hash</i> de la <abbr title="Uniform Resource Locator">URL</abbr>, algo que no tiene mucho sentido si su funcionalidad es la de un mero botón.</li>
<li>Sólo por medio de <code>:target</code> no se puede implementar la funcionalidad de <strong>cerrar</strong> un desplegable.</li>
</ul>
<p>El peso de la animación, sin embargo, sigue recayendo sobre las propiedades de <abbr>CSS</abbr>3. <a href="http://digitalicon.es/ejemplos/acordeon-css3/acordeon03.htm">Aquí está la prueba</a>, y aquí el código del <i lang="en" xml:lang="en">script</i>:</p>
<pre><code>
var AC = {
  $: function(el){return document.getElementById(el);},
  $$: function(et,el){el===undefined ? el = document : el = el;return el.getElementsByTagName(et);},
  $$$: function(cl,el){el===undefined ? el = document : el = el;return el.getElementsByClassName(cl);},
  cl: 'ac',
  t: '.75s',
  cA: 'AC'+(new Date().getTime()),
  alts: [],
  cntr: function(x){
    var ex = AC.$(x[0].id);
    var cT = (ex.className.toString()).replace(' expandir','');
    ex.className = cT;
    ex.style.height = '0';
  },
  estado: function(x){
    x.preventDefault() ? x.preventDefault() : x.returnValue=false;
    var t = x.target.toString().split('#'), it = t[t.length-1], p = /expandir/i;
    var ex = AC.$$$('expandir',AC.$(it).parentNode.parentNode);
    if(!(AC.$(it).className.match(p))){
      if(ex[0]!==undefined){
        AC.cntr(ex);
      };
      AC.$(it).className+=' expandir';
      AC.$(it).style.height = AC.alts[it]+'px';
      AC.$(it).focus();
    }else{
      AC.cntr(ex);
    };
  },
  ini: function(){
    var eA = document.styleSheets[document.styleSheets.length-1];
     eA.insertRule('.'+AC.cA+'{overflow:hidden;-moz-transition:'+AC.t+';-ms-transition:'+AC.t+';-webkit-transition:'+AC.t+';-o-transition:'+AC.t+';transition:'+AC.t+';}',eA.cssRules.length);&nbsp;
    var m = AC.$$$(AC.cl);
    for(i=0;i&lt;m.length;i++){
      var b = AC.$$('li',m[i]);
      for(j=0;j&lt;b.length;j++){
        AC.$$('a',b[j])[0].onclick = AC.estado;
      }
      var d = AC.$$('div',m[i]);
      for(k=0;k&lt;d.length;k++){
        var al = d[k].offsetHeight;
        AC.alts[d[k].id] = al;
        d[k].className+=AC.cA;
        d[k].style.height='0';
        d[k].tabIndex = '-1';
      }
    }
  }
}
window.onload = AC.ini;
 </code></pre>
<p>Hay dos variables de configuración para quien quiera emplearlo:</p>
<ul>
<li><var>cl</var>: es la clase que se va a emplear en el marcado para indicar cuáles son los menús desplegables.</li>
<li><var>t</var>: define el tiempo que se desea que dure la animación; se puede expresar en segundos (<var>s</var>) o milisegundos (<var>ms</var>).</li>
</ul>
<p>El <i lang="en" xml:lang="en">script</i> lo que hace es buscar los menús con la clase indicada y almacenar en una matriz las alturas de los elementos para modificarlas posteriormente. Para que no sea necesario añadir una regla en la hoja de estilo con la definición de la transición, la crea al vuelo y por medio de <a href="http://www.w3.org/TR/2000/REC-DOM-Level-2-Style-20001113/css.html#CSS-CSSMediaRule-insertRule" hreflang="en"><code>insertRule</code></a> la añade a la última hoja de estilo de la página &mdash;tranquilos, le asigno un número aleatorio para que no entre en conflicto con ninguna de las reglas ya definidas (bueno, a menos que alguien haya definido una clase como <code>AC1329215346055</code>&#8230;)&mdash;. El resto del código simplemente se encarga de coordinar los estados de los elementos de los menús.</p>
<h3>Accesibilidad</h3>
<p>Como es un tema que me preocupa, me agrada comprobar que la funcionalidad está disponible para navegación por medio de teclado. Además, hay tres posibilidades cubiertas:</p>
<ol>
<li>El usuario no cuenta con JavaScript: los contenidos aparecen desplegados sin más.</li>
<li>El usuario cuenta con JavaScript, pero el navegador no soporta transiciones de <abbr>CSS</abbr>: los deplegables se abren y cierran de manera inmediata sin animación.</li>
<li>El usuario cuenta con JavaScript, y el navegador soporta transiciones de <abbr>CSS</abbr>: perfecto.</li>
</ol>
<p>No está mal para un experimento fallido, ¿verdad?</p>
]]></content:encoded>
			<wfw:commentRss>http://digitalicon.es/blog/acordeon-fallido-css3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Añadir &lt;meta name=&quot;description&quot;/&gt; individual a las entradas de WordPress</title>
		<link>http://digitalicon.es/blog/anadir-meta-description-individual-entradas-wordpress/</link>
		<comments>http://digitalicon.es/blog/anadir-meta-description-individual-entradas-wordpress/#comments</comments>
		<pubDate>Mon, 13 Feb 2012 09:03:29 +0000</pubDate>
		<dc:creator>Saúl González Fernández</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://digitalicon.es/?p=3127</guid>
		<description><![CDATA[Explicamos cómo añadir una descripción individual a las publicaciones en WordPress sin necesidad de ningún <i lang="en" xml:lang="en">plugin</i>.]]></description>
			<content:encoded><![CDATA[<p id="intro">Con la publicación del nuevo rediseño de nuestra página hemos aprovechado para mejoras aquellos detalles que en la anterior versión quedaron pendientes. Uno de ellos era encontrar la manera de poder asignar un <code>&lt;meta name="description"/&gt;</code> individual a cada página y entrada del blog, pero sin emplear un <i lang="en" xml:lang="en">plugin</i>.</p>
<p>¿Por qué sin un <i lang="en" xml:lang="en">plugin</i>? Bueno, en general prefiero emplear extensiones cuando se trata de funcionalidades que quiero activar temporalmente y luego desactivar, como por ejemplo el <a href="http://wordpress.org/extend/plugins/wp-maintenance-mode/" hreflang="en"><i lang="en" xml:lang="en">WP Maintenance Mode</i> de Frank Bültge</a>; si lo que voy a hacer es instalar un complemento para que permanezca activo indefinidamente, creo que tiene más sentido añadir la funcionalidad como código a mi tema y así no sobrecargar mi página de administración. Aunque si alguien quiere emplear un <i lang="en" xml:lang="en">plugin</i>, <a href="http://wordpress.org/extend/plugins/tags/meta-description" hreflang="en">hay decenas</a>.</p>
<p>Dicho esto, veamos el código.</p>
<h2>La descripción de las entradas del blog</h2>
<p>Viendo que la descripción del <code>meta</code> debe ser un resumen no demasiado extenso de la entrada, ¿qué mejor contenido que el resumen que WordPress permite añadir a cada entrada? Este resumen se incluye en el campo <i>Extracto</i> bajo el formulario de edición; si no aparece, hay que activarlo en <i>Opciones de pantalla &rarr; Extracto</i>.</p>
<p>Para que el mismo se convierta en la descripción del documento, en un primer momento simplemente incluí este código en el <i>header.php</i>:</p>
<pre><code>
&lt;meta name="description" content="&lt;?php echo get_the_excerpt(); ?&gt;" /&gt;'
 </code></pre>
<p>No obstante, surgía un problema, y es que el campo del extracto sólo está disponible para las entradas del blog&#8230;</p>
<h2>La descripción de las demás páginas</h2>
<p>Primero, hay que asignar un resumen a las páginas, algo que es posible gracias a la opción de añadir <a href="http://codex.wordpress.org/Custom_Fields" hreflang="en">campos personalizados</a> a una publicación. De nuevo, en <i>Opciones de pantalla</i> podemos activar los <i>Campos personalizados</i>. Una vez hecho esto, al pie del editor de la página tenemos esta interfaz:</p>
<dl class="ilustracion">
<dt><img src="http://digitalicon.es/ejemplos/meta-description-wp/captura.gif" alt="" /></dt>
<dd>La interfaz de campos personalizados [Firefox 9]</dd>
</dl>
<p>Lo que hago es crear un campo <samp>desc</samp> y añadir la descripción. Tras especificar un campo personalizado, todas las páginas contarán con éste en el desplegable.</p>
<p>Sólo queda extraer su contenido pra incluirlo en el documento, lo que se hace por medio de la función <a href="http://codex.wordpress.org/Function_Reference/get_post_meta" hreflang="en"><code>get_post_meta()</code></a>. Y con esto y un par de detalle adicionales, el código final es el siguiente:</p>
<pre><code>
&lt;?php
  if((is_single())&amp;&amp;(has_excerpt())){
    $d = get_the_excerpt();
  } elseif(is_page()){
    $d = get_post_meta(get_the_ID(),'desc',true);
  }
  if($d){
    $d = preg_replace("/&lt;.*?&gt;/", "", $d);
    echo '&lt;meta name="description" content="'.$d.'" /&gt;';&nbsp;
  }
?&gt;
 </code></pre>
<p>El <i lang="en" xml:lang="en">script</i> comprueba si el documento es una entrada con un extracto o una página, <var>$d</var> almacena esta información, y si no es nula se crea el <code>meta</code>. El <code>preg_replace()</code> limpia las posibles etiquetas de la descripción.</p>
<p>Como se ve, no es complicado. Y nos libra de añadir el enésimo <i lang="en" xml:lang="en">plugin</i> a nuestra instalación.</p>
]]></content:encoded>
			<wfw:commentRss>http://digitalicon.es/blog/anadir-meta-description-individual-entradas-wordpress/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cómo hacer accesibles contenidos de terceras partes: cuestión de imaginación</title>
		<link>http://digitalicon.es/blog/hacer-accesibles-contenidos-terceras-partes-cuestion-imaginacion/</link>
		<comments>http://digitalicon.es/blog/hacer-accesibles-contenidos-terceras-partes-cuestion-imaginacion/#comments</comments>
		<pubDate>Tue, 07 Feb 2012 10:29:05 +0000</pubDate>
		<dc:creator>Saúl González Fernández</dc:creator>
				<category><![CDATA[Accesibilidad]]></category>
		<category><![CDATA[recursos de terceras partes]]></category>

		<guid isPermaLink="false">http://digitalicon.es/?p=3063</guid>
		<description><![CDATA[Mostramos un ejemplo de cómo volver accesible un recurso no accesible proporcionado por una tercera parte, concretamente StatCounter.]]></description>
			<content:encoded><![CDATA[<p id="intro">En algunas ocasiones como desarrolladores nos encontramos con que nos sería de mucha utilizad incluir en nuestras páginas contenidos incrustados que ofrecen terceras partes, pero que en muchos casos hay que plantearse si merece la pena mostrar los datos si estos no van a ser accesibles. No obstante, a veces es sólo cuestión de buscar una solución alternativa prestando atención a recursos poco evidentes.</p>
<h2>El problema inicial</h2>
<p>Para nuestra página de <a href="http://www.movilizaweb.com/" class="dv">MovilizaWeb</a> nos planteamos que sería interesante incluir datos estadísticos comparativos del acceso a Internet desde equipos de escritorio y desde dispositivos móviles del último año, para mostrar cómo el segundo va en aumento mes a mes.</p>
<p>Dichos datos nos los porporciona <a href="http://gs.statcounter.com/" hreflang="en">StatCounter</a>, pero los formatos digamos que no son los que consideramos más aptos desde el punto de vista de la accesibilidad. Por un lado, podemos descargar el gráfico en JPG, pero esto nos plantea el problema de la descripción alternativa de los contenidos de la imagen, mucho más cuando queremos que esta información sea dinámica y que cambie de manera automática mes a mes. Por otro lado, tenemos el <i lang="en" xml:lang="en">snippet</i> que la página proporciona para incrustar el gráfico:</p>
<pre><code>
&lt;div id=&quot;mobile_vs_desktop-ww-monthly-201101-201201&quot; width=&quot;600&quot; height=&quot;400&quot; style=&quot;width:600px; height:400px;&quot;&gt;&lt;/div&gt;
&lt;!-- You may change the values of width and height above to resize the chart --&gt;
&lt;p&gt;Source: &lt;a href=&quot;http://gs.statcounter.com/#mobile_vs_desktop-ww-monthly-201101-201201&quot;&gt;StatCounter Global Stats - Mobile vs. Desktop Market Share&lt;/a&gt;&lt;/p&gt;&nbsp;
&lt;script type=&quot;text/javascript&quot; src=&quot;http://www.statcounter.com/js/FusionCharts.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;http://gs.statcounter.com/chart.php?mobile_vs_desktop-ww-monthly-201101-201201&quot;&gt;&lt;/script&gt;
 </code></pre>
<p>&#8230;que desde el punto de vista de la accesibilidad es una pesadilla:</p>
<ul>
<li>Los contenidos se cargan por medio de JavaScript, por lo que los usuarios con un cliente que no tenga soporte no podrán visualizarlos.</li>
<li>El JavaScript lo que hace es incrustar un objeto de Flash, por lo que los usuarios que empleen un dispositivo sin soporte del <i lang="en" xml:lang="en">plugin</i> se encontrarán en la misma situación que los anteriores.</li>
<li>Los porcentajes de acceso de cada línea de la gráfica sólo se muestran cuando se sitúa el ratón sobre ellos, lo que impide que los usuarios que no puedan emplear un dispositivo de puntero conozcan las cifras. Además, su tamaño también dificulta el acceso a esos datos de los que no puedan emplear un ratón con precisión.</li>
</ul>
<p>Así, teníamos que buscar una alternativa.</p>
<h2>¿Y ahora qué hacemos?</h2>
<p>Frente a este problema, el desarrollador perezoso puede encogerse de hombros y aferrarse a hacer una <a href="http://www.w3.org/TR/2008/REC-WCAG20-20081211/#conformance-partial" hreflang="en">declaración de conformidad parcial con las <abbr title="Web Content Accessibility Guidelines">WCAG</abbr> 2.0</a>, que es algo así como decir «sí, bueno, esta página sería accesible si no fuera por el formato en el que me proporciona los datos StatCounter; yo ya he hecho mi parte&#8230;»; pero esa es una actitud que reduce la accesibilidad a una especie de trámite administrativo a cumplimentar y que delega toda responsabilidad ética para con los usuarios discapacitados, además de que muestra muy poco respeto para los visitantes &mdash;o clientes&mdash; en situaciones análogas.</p>
<p>Una solución sería emplear la <a href="http://api.statcounter.com/docs/v3" hreflang="en"><abbr title="Application Programming Interface">API</abbr> de StatCounter</a> &mdash;que permite recibir los datos en <abbr title="JavaScript Object Notation">JSON</abbr> u <abbr title="eXtensible Markup Language">XML</abbr>&mdash; y trabajar con ellos, pero en principio consideramos que las <abbr>API</abbr> tiene sentido emplearlas para un uso intensivo de los recursos que proporcionan, que no es nuestro caso puesto que los datos van a tener una aplicación muy restringida.</p>
<p>Y ahora es cuando viene la solución simple.</p>
<h2>La solución: imaginar una alternativa</h2>
<p>Un tercer formato que proporciona StatCounter es un <abbr title="Comma-Separated Values">CSV</abbr>. Se trata de un pequeño archivo con este escueto contenido:</p>
<pre><code>
"Date","Desktop","Mobile"
2011-01,95.7,4.3
2011-02,95.55,4.45
2011-03,95.3,4.7
2011-04,94.79,5.21
2011-05,94.25,5.75
2011-06,93.47,6.53
2011-07,92.98,7.02
2011-08,92.88,7.12
2011-09,93.26,6.74
2011-10,93.45,6.55
2011-11,93.05,6.95
2011-12,91.96,8.04
2012-01,91.47,8.53
 </code></pre>
<p>Revisando el código de la página, localizamos el vínculo que se genera junto a cada gráfica:</p>
<pre><code>
&lt;a href=&quot;chart.php?statType_hidden=mobile_vs_desktop&amp;amp;region_hidden=ww&amp;amp;granularity=monthly&amp;amp;statType=Mobile%20vs.%20Desktop&amp;amp;region=Worldwide&amp;amp;fromMonthYear=2011-02&amp;amp;toMonthYear=2012-01&amp;amp;csv=1&quot; id=&quot;csv-version&quot;&gt;&nbsp;
 </code></pre>
<p>Tras esto, el proceso para crear una tabla accesible era trivial:</p>
<ol>
<li>Generamos la <abbr title="Uniform Resource Locator">URL</abbr> que necesitamos dependiendo del mes actual.</li>
<li>Cargamos el .csv que nos interesa por medio de <a href="http://php.net/manual/es/book.curl.php" hreflang="en">cURL</a>.</li>
<li>Creamos una matriz con los datos separando primero por saltos de línea y despues por comas.</li>
</ol>
<p>Con la matriz resultante, <a href="http://digitalicon.es/ejemplos/hacer-accesibles-contenidos-terceras-partes/index.php">generamos la tabla</a>. Misión cumplida.</p>
<h2>Conclusión</h2>
<p>Por supuesto, habrá situaciones en las que no se cuente con los medios para hacer accesibles los contenidos de terceras partes, pero un desarrollador competente debe ser capaz de imaginar todas las alternativas posibles a su disposición para intentarlo.</p>
]]></content:encoded>
			<wfw:commentRss>http://digitalicon.es/blog/hacer-accesibles-contenidos-terceras-partes-cuestion-imaginacion/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dar un comportamiento natural a un botón</title>
		<link>http://digitalicon.es/blog/comportamiento-natural-boton/</link>
		<comments>http://digitalicon.es/blog/comportamiento-natural-boton/#comments</comments>
		<pubDate>Sat, 21 Jan 2012 12:59:31 +0000</pubDate>
		<dc:creator>Saúl González Fernández</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[Diseño]]></category>
		<category><![CDATA[css3]]></category>

		<guid isPermaLink="false">http://s396559901.mialojamiento.es/?p=3004</guid>
		<description><![CDATA[Explicamos como simular un comportamiento más natural de un botón.]]></description>
			<content:encoded><![CDATA[<p id="intro">El diseño está en los detalles, pero no sólo en su vertiente gráfica, sino también en lo referente a la interacción de una interfaz. En esta entrada indicamos cómo lograr que un botón se comporte de una forma más nátural, empleando sólo <abbr title="Cascading Style Sheets">CSS</abbr>3.</p>
<p>Según <a href="http://www.useit.com/alertbox/response-times.html" hreflang="en">Jakob Nielsen en <i lang="en" xml:lang="en">Website Response Times</i></a>, contamos con una décima de segundo para convencer a nuestros usuarios de que un elemento interactivo de una interfaz funciona correctamente y que le proporciona el control que su diseño sugiere. Pero no sólo eso, sino que la respuesta inmediata de la interfaz puede además evitar que el usuario realice acciones indeseadas, como reenviar un formulario si piensa que su primer clic no ha tenido efecto.</p>
<p>Técnicamente sólo necesitamos emplear la pseudoclase <code>:active</code> para modificar el aspecto de un vínculo o botón cuando nuestro usuario hace clic sobre el elemento en cuestión. Pero lo que queremos explicar aquí es cómo hacer que un botón se comporte de una forma más natural, y para ello hemos elegido un diseño que últimamente se ha puesto de moda:</p>
<dl class="ilustracion">
<dt><a href="http://digitalicon.es/ejemplos/boton-comportamiento-natural/boton.htm"><img src="http://digitalicon.es/ejemplos/boton-comportamiento-natural/captura.jpg" alt="" /></a></dt>
<dd><a href="http://digitalicon.es/ejemplos/boton-comportamiento-natural/boton.htm">El botón</a> [Firefox 9]</dd>
</dl>
<p>La idea es que si se ha empleado un diseño que simula las tres dimensiones, lo coherente es que el botón, al activarlo, se comporte como lo haría un botón real, es decir, que se «hunda» al presionarlo, lo que significa que:</p>
<ul>
<li>su posición debe variar verticalmente,</li>
<li>la sombra que hemos empleado para fingir el relieve inferior debe reducirse, y</li>
<li>la sombra que proyecta debe contraerse.</li>
</ul>
<p>Primero lo primero. Para lograr el relieve hemos empleado sombras múltiples, tal y como se indica en <a href="http://www.w3.org/TR/2011/CR-css3-background-20110215/#the-box-shadow" hreflang="en">la especificación de la propiedad <code>box-shadow</code></a>:</p>
<pre><code>
button{
  [...]
  -webkit-box-shadow: 0 6px 0 0 #80123C,0 8px 6px 0 #515151;
  -moz-box-shadow: 0 6px 0 0 #80123C,0 8px 6px 0 #515151;
  box-shadow: 0 6px 0 0 #80123C,0 8px 6px 0 #515151;
  [...]
}
 </code></pre>
<p>Y después hemos declarado el estado activo de esta manera:</p>
<pre><code>
button:active{
  position: relative;
  top: 3px;
  -webkit-box-shadow: 0 3px 0 0 #80123C,0 4px 3px 0 #515151;
  -moz-box-shadow: 0 3px 0 0 #80123C,0 4px 3px 0 #515151;
  box-shadow: 0 3px 0 0 #80123C,0 4px 3px 0 #515151;
}
 </code></pre>
<p>Como variamos la posición relativa del botón en 3 píxeles, modificamos los tamaños correspondientes de las sombras.</p>
<p>Así de sencillo.</p>
]]></content:encoded>
			<wfw:commentRss>http://digitalicon.es/blog/comportamiento-natural-boton/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Un ejemplo de cómo no emplear la geolocalización</title>
		<link>http://digitalicon.es/blog/ejemplo-como-no-emplear-geolocalizacion/</link>
		<comments>http://digitalicon.es/blog/ejemplo-como-no-emplear-geolocalizacion/#comments</comments>
		<pubDate>Tue, 10 Jan 2012 10:43:14 +0000</pubDate>
		<dc:creator>Saúl González Fernández</dc:creator>
				<category><![CDATA[Usabilidad]]></category>
		<category><![CDATA[geolocalización]]></category>
		<category><![CDATA[google+]]></category>

		<guid isPermaLink="false">http://s396559901.mialojamiento.es/?p=2995</guid>
		<description><![CDATA[Comentamos un empleo erróneo de la geolocalización por parte de Google+.]]></description>
			<content:encoded><![CDATA[<p id="intro">Por medio de la sencilla <a href="http://www.w3.org/TR/2010/CR-geolocation-API-20100907/" hreflang="en"><abbr title="Application Programming Interface">API</abbr> del estándar de geolocalización</a> &mdash;que <a href="http://digitalicon.es/blog/pruebas-futuro-inmediato-geolocalizacion/">explicamos hace tiempo</a>&mdash;, se puede mejorar la experiencia de un usuario ofreciendole contenidos dependientes de su ubicación. O, si se emplea como lo hace Google+, dar una pobre impresión.</p>
<p>Hasta este fin de semana no había accedido a mi cuenta de Google+ a través del móvil, y me sorprendió encontrar un ejemplo tan claro de mala usabilidad. Esto es lo que aparece tras el formulario de acceso:</p>
<dl class="ilustracion">
<dt><img src="http://digitalicon.es/ejemplos/ejemplo-no-geolocalizacion/foto.jpg" alt="" /></dt>
<dd>La interfaz de Google+ en iPhone 4, que me permite aceptar las condiciones de uso &mdash;y compartir mi ubicación&mdash; o cancelar</dd>
</dl>
<p>Tengo un botón para cancelar y una escueta nota en la que se me informa de que al aceptar permito que Google acceda a mi localización y que acepto los términos de su servicio móvil.</p>
<p>No dudo de que mi experiencia de usuario habría mejorado si hubiera aceptado, pero obviamente tengo derecho a <strong>no</strong> compartir mi ubicación si quiero preservar mi privacidad &mdash;es por ello que <a href="http://www.w3.org/TR/2010/CR-geolocation-API-20100907/#privacy_for_uas" hreflang="en">la especificación insiste en que el usuario debe permitir expresamente compartir tal dato</a>&mdash;. No obstante, al cancelar me encontré con que Google me devolvía a la página inicial, sin permitirme acceder a mi cuenta.</p>
<p>Si hay algo en lo que coincidirá cualquiera que sepa algo de usabilidad es que emplear nuevas tecnologías <strong>debe significar que se ofrece al usuario una funcionalidad adicional, y no que se le niegue la posibilidad de acceder a un servicio</strong>.</p>
]]></content:encoded>
			<wfw:commentRss>http://digitalicon.es/blog/ejemplo-como-no-emplear-geolocalizacion/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Comenzamos el año con una aplicación móvil</title>
		<link>http://digitalicon.es/blog/comenzamos-ano-aplicacion-movil/</link>
		<comments>http://digitalicon.es/blog/comenzamos-ano-aplicacion-movil/#comments</comments>
		<pubDate>Tue, 03 Jan 2012 08:44:09 +0000</pubDate>
		<dc:creator>Saúl González Fernández</dc:creator>
				<category><![CDATA[Miscelánea]]></category>
		<category><![CDATA[aplicación móvil]]></category>

		<guid isPermaLink="false">http://s396559901.mialojamiento.es/?p=2970</guid>
		<description><![CDATA[Comenzamos el año programando una aplicación web móvil... gratis.]]></description>
			<content:encoded><![CDATA[<p id="intro">Como desarrolladores, a veces tenemos la necesidad de comprobar el código de las webs para móviles que creamos en <a href="http://www.movilizaweb.com/" class="dv">MovilizaWeb</a>, y aunque las consolas de depuración de los navegadores en iOS y Android nos indican los fallos, echamos de menos poder ver todo el marcado de una página. Por eso hemos creado esta aplicación.</p>
<dl class="ilustracion">
<dt><a href="http://movil.vc/"><img src="http://www.digitalicon.es/ejemplos/mvc/captura.jpg" alt="" /></a></dt>
<dd><a href="http://movil.vc/">Móvil &rsaquo; Ver Código</a></dd>
</dl>
<p>A decir verdad, la lanzamos hace un par de meses, pero estas Navidades hemos aprovechado para actualizarla, añadiendo la posibilidad de guardar en el dispositivo &mdash;gracias a <a href="http://www.w3.org/TR/2011/CR-webstorage-20111208/#the-localstorage-attribute" hreflang="en"><code>localStorage</code></a>&mdash; las páginas en las que estamos trabajando.</p>
<p>¿Lo mejor? Que como es una <i lang="en" xml:lang="en">webapp</i>, no hace falta instalarla. Y es gratis.</p>
]]></content:encoded>
			<wfw:commentRss>http://digitalicon.es/blog/comenzamos-ano-aplicacion-movil/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>El iframe de YouTube y la desaparición de contenidos en iPhone: cómo evitarlo</title>
		<link>http://digitalicon.es/blog/iframe-youtube-desaparicion-contenidos-iphone/</link>
		<comments>http://digitalicon.es/blog/iframe-youtube-desaparicion-contenidos-iphone/#comments</comments>
		<pubDate>Fri, 02 Dec 2011 08:48:21 +0000</pubDate>
		<dc:creator>Saúl González Fernández</dc:creator>
				<category><![CDATA[(X)HTML]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[web móvil]]></category>

		<guid isPermaLink="false">http://s396559901.mialojamiento.es/?p=2983</guid>
		<description><![CDATA[Solventamos el problema de la desaparición de contenidos en iPhone cuando se emplea el <code>iframe</code> de YouTube para inscrustar vídeos.]]></description>
			<content:encoded><![CDATA[<p>El día 16 del pasado mes se anunció la X edición del concurso de cortos de <a href="http://www.notodofilmfest.com/#/Home/">Notodofilmfest</a>, y para la ocasión <a href="http://www.lafabrica.com/es/">La Fábrica</a> nos encargó la versión web para <i lang="en" xml:lang="en">smartphones</i> de su sitio.</p>
<p>La web móvil la desarrollamos en <abbr title="HyperText Markup Language">HTML</abbr>5, y para incrustar los vídeos de su canal de YouTube, decidimos emplear <a href="http://apiblog.youtube.com/2010/07/new-way-to-embed-youtube-videos.html" hreflang="en">la opción del <code>iframe</code></a> para, en la medida de lo posible, no depender del <i lang="en" xml:lang="en">plugin</i> de Flash &mdash;en Android; en iOS es la aplicación nativa de YouTube la que se encarga de la reproducción del vídeo.</p>
<p>Como se ve en la página indicada, incluir el <code>iframe</code> tan sencillo como esto:</p>
<pre><code>
&lt;iframe class=&quot;youtube-player&quot; type=&quot;text/html&quot; width=&quot;640&quot; height=&quot;385&quot; src=&quot;http://www.youtube.com/embed/VIDEO_ID&quot; frameborder=&quot;0&quot;&gt;&nbsp;
&lt;/iframe&gt;
 </code></pre>
<p>No obstante, el resultado no era el esperado: por algún motivo, los contenidos bajo el <code>iframe</code> desaparecían:</p>
<dl class="ilustracion">
<dt><img src="http://www.digitalicon.es/ejemplos/ntff/captura.jpg" alt="" /></dt>
<dd>A la izquierda, la interfaz como debería aparecer; a la derecha, como aparecía [iPhone 4]</dd>
</dl>
<p>Tras muchas pruebas, hallamos la solución, y ya de paso revisamos <a href="http://www.w3.org/TR/2011/WD-html5-20110525/the-iframe-element.html#the-iframe-element" hreflang="en">la especificación de <code>iframe</code> de <abbr>HTML</abbr>5</a> para emplear un código válido &mdash;tanto el atributo <code>type</code> como <code>frameborder</code> se han descartado:</p>
<pre><code>
&lt;iframe width=&quot;640&quot; height=&quot;385&quot; src=&quot;http://www.youtube.com/embed/VIDEO_ID&quot;&gt;<i>&lt;br&gt;</i>&lt;/iframe&gt;&nbsp;
 </code></pre>
<p>Como hemos indicado, con el salto de línea incluido entre las etiquetas se solventa el problema. ¿Por qué? Bueno, eso no lo hemos hemos llegado a entender; pero funciona.</p>
]]></content:encoded>
			<wfw:commentRss>http://digitalicon.es/blog/iframe-youtube-desaparicion-contenidos-iphone/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Replicando el comportamiento de la barra de navegación de Apple.com</title>
		<link>http://digitalicon.es/blog/replicando-comportamiento-barra-navegacion-apple/</link>
		<comments>http://digitalicon.es/blog/replicando-comportamiento-barra-navegacion-apple/#comments</comments>
		<pubDate>Fri, 25 Nov 2011 13:18:13 +0000</pubDate>
		<dc:creator>Saúl González Fernández</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[css3]]></category>
		<category><![CDATA[javascript no obstrusivo]]></category>

		<guid isPermaLink="false">http://www.digitalicon.es/blog/?p=2932</guid>
		<description><![CDATA[Explicamos cómo lograr que una barra de navegación se comporte como la de la actual página de Apple.]]></description>
			<content:encoded><![CDATA[<p id="intro">Hace unos días mi socio Jorge Fernández me preguntó si podría replicar el comportamiento de la barra de <a href="http://www.apple.com/">la página de Apple</a> empleando la menor cantidad posible de JavaScript. Imagino que se esperaba alguno de <a href="http://www.digitalicon.es/blog/tag/en-menos-de-2kb/">mis <i lang="en" xml:lang="en">scripts</i> en menos de 2<abbr title="kilobytes">Kb</abbr></a>, pero el resultado no ha ido por ahí&hellip;</p>
<p>En la barra de navegación de Apple, cuando un usuario hace clic sobre el buscador, la caja del mismo se expande para ofrecer un poco más de espacio al texto de búsqueda, lo cual es un detalle de usabilidad muy de agradecer. Al ampliar el tamaño del buscador, los vínculos de la navegación, en consecuencia, disminuyen su anchura. Visto así, el <i lang="en" xml:lang="en">script</i> debería:</p>
<ol>
<li>Asignar dos eventos en el <code>input</code>, uno en el estado <i lang="en" xml:lang="en">focus</i> y otro en el estado <i lang="en" xml:lang="en">blur</i>, para activar la animación que amplie o reduzca el campo.</li>
<li>Lanzar una función encargada de la animación, la cual debe tener en cuenta el tamaño inicial y final de cada vínculo y del formulario de búsqueda, y aumentar o reducir los mismos de manera progresiva.</li>
</ol>
<p>En principio no es demasiado complejo, pero <a href="http://www.digitalicon.es/blog/menus-desplegables-animados-css3/#css-o-js">como dije en una entrada anterior, para este tipo de efectos son mucho más eficientes las animaciones de <abbr title="Cascading Style Sheets">CSS</abbr>3</a>. Así que <a href="http://www.digitalicon.es/ejemplos/barra-apple/index.htm">el resultado</a> se basa en ellas, lo que ha reducido considerablemente la cantidad de JavaScript necesario.</p>
<h2>La parte de <abbr>CSS</abbr></h2>
<p>Para crear la barra de navegación, en lugar de flotar los ítems de la lista, hemos aplicado <a href="http://www.w3.org/TR/2011/REC-CSS2-20110607/tables.html#table-display">los valores de tablas de la propiedad <code>display</code></a>, porque tienen la ventaja de que podemos asignarles inicialmente un ancho, pero posteriormente el navegador tiene la capacidad de adaptar los tamaños de las celdas en función de sus contenidos, como hace con las tablas de <abbr title="HyperText Markup Language">HTML</abbr>.</p>
<p>La idea era que a medida que el <code>input</code> del formulario se fuera extendiendo, la falsa celda crecería con él&hellip; pero no. El comportamiento real cuando sólo aplicábamos las reglas&hellip;</p>
<pre><code>
input{
  [&hellip;]
  -webkit-transition:.5s;
  -moz-transition:.5s;
  -o-transition:.5s;
  -ms-transition:.5s;
  transition:.5s;
}

input:focus{
  width:250px;
  [&hellip;]
}
 </code></pre>
<p>&hellip;no era el deseado: los navegadores esperaban a que la transición hubiese finalizado para redibujar el elemento padre. Es decir, la caja del formulario se expandía superponiéndose progresivamente al vinculo de su izquierda, para que después sin transición el resto de elementos de la barra se cuadraran ajustándose al nuevo tamaño.</p>
<p>Después de unas cuantas pruebas comprobé que lo que necesitaba era el formulario que contenía el <code>input</code> tuviese la misma transición asociada, para que se expandiera de manera sincronizada. Y en este punto es cuando necesité añadir JavaScript, porque el elemento <code>form</code> no acepta el evento <i lang="en" xml:lang="en">focus</i>.</</p>
<h2>La parte de JavaScript</h2>
<p>El <i lang="en" xml:lang="en">script</i>, visto lo anterior, sólo tenía que asignar al formulario el ancho final cuando el usuario activa el <code>input</code>. Además, sólo debía activar las propiedades de transición de <abbr>CSS</abbr> para el campo del formulario en caso de tener JavaScript activado, por evitar el efecto indicado anteriormente; es decir, esto:</p>
<pre><code>
var n = {
  $: function(x){
    return document.getElementById(x);
  },
  soporte: function(){
    var pre = ['css','Moz','webkit','o','ms'];
    for(var i in pre){
      if(eval('n.$('b').style.'+pre[i]+'Transition')!==undefined){
        var s = true;
      }
    }
    return s;
  },
  ini: function(){
    if(n.soporte){
      n.$('b').className='trans';
      n.$('b').onfocus = function(){
        n.$('f').className='activo';
      }
      n.$('b').onblur = function(){
        n.$('f').className='';
      }
    }
  }
}
window.onload = n.ini;
 </code></pre>
<p>Como se ve, el <i lang="en" xml:lang="en">script</i> sólo comprueba las condiciones para sincronizar el comportamiento del formulario y su <code>input</code>: la animación queda a cargo de <abbr>CSS</abbr>.</p>
<p>Como nota final, indicar que hay una limitación: como siempre que se quiere que el navegador aplique una transición de una propiedad de longitud, hay que indicar la medida en unidades absolutas, por lo que sería difícil emplearlo con una composición fluida.</p>
]]></content:encoded>
			<wfw:commentRss>http://digitalicon.es/blog/replicando-comportamiento-barra-navegacion-apple/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

