<?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>marcis / blog &#187; desarrollo web</title>
	<atom:link href="http://blog.marcis.es/tema/desarrollo-web/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.marcis.es</link>
	<description>Desarrollo Web</description>
	<lastBuildDate>Fri, 08 Jul 2011 19:04:04 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Detectar el bloqueo de los popups</title>
		<link>http://blog.marcis.es/detectar-el-bloqueo-de-los-popups/</link>
		<comments>http://blog.marcis.es/detectar-el-bloqueo-de-los-popups/#comments</comments>
		<pubDate>Sun, 20 Feb 2011 14:47:28 +0000</pubDate>
		<dc:creator>marcis</dc:creator>
				<category><![CDATA[desarrollo web]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[popup]]></category>

		<guid isPermaLink="false">http://blog.marcis.es/?p=237</guid>
		<description><![CDATA[Cómo detectar desde Javascript si una ventana (o popup) ha sido bloqueada por el navegador]]></description>
			<content:encoded><![CDATA[<div style="height:33px;" class="really_simple_share robots-nocontent snap_nopreview"><div class="really_simple_share_facebook_like" style="width:100px;">
				<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.marcis.es%2Fdetectar-el-bloqueo-de-los-popups%2F&amp;layout=button_count&amp;show_faces=false&amp;width=&amp;action=like&amp;colorscheme=light&amp;send=false&amp;height=27" 
						scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:px; height:27px;" allowTransparency="true"></iframe>
				</div><div class="really_simple_share_twitter" style="width:110px;">
					<a href="http://twitter.com/share" class="twitter-share-button" data-count="horizontal" 
						data-text="Detectar el bloqueo de los popups" data-url="http://blog.marcis.es/detectar-el-bloqueo-de-los-popups/" 
						data-via="" ></a> 
				</div></div>
		<div style="clear:both;"></div><p>Hace poco tuve que implementar una API en PHP que pretendía <strong>integrar funcionalidades</strong> de terceros en un sitio web. Uno de los métodos que se necesitaban debía devolver la URL a la que se redirige inicialmente al usuario para que nos dé permisos de acceso a su cuenta, en principio mediante <a title="OAuth - Wikipedia" href="http://en.wikipedia.org/wiki/OAuth" target="_blank">OAuth</a>.</p>
<p>No hubo problema para los dos primeros casos (Gmail y Facebook), pero al empezar con <strong>Hotmail</strong>, que utiliza una <a title="JavaScript Library Reference for Windows Live Messenger Connect" href="http://msdn.microsoft.com/es-es/library/ff750246.aspx" target="_blank">librería en Javascript</a>, era <em>preferible</em> abrir el popup estándar que provee <em>Windows Live</em> antes que mandar al usuario a una página en la que el 95% del contenido está en blanco.</p>
<p><span id="more-237"></span>Las complicaciones empezaron al <strong>intentar abrir una ventana nueva</strong> de forma &#8220;indirecta&#8221;, es decir, sin especificar el código directamente en el HTML original, sino a través de una función asignada de forma dinámica:</p>
<pre>function wlConsent(connect_url) {
  window.open(connect_url, 'wl', 'width=...');
}</pre>
<p>Dicha ventana se abría correctamente en la mayoría de los navegadores, pero algunos, los más modernos, no lo permitían debido a su <strong>bloqueador de popups</strong>.</p>
<p>La solución parecía sencilla, recoger el valor devuelto por el método &#8220;open&#8221; del objeto &#8220;window&#8221; y comprobar si estaba vacío:</p>
<pre>var popup = window.open(...)
if (!popup || popup.closed || typeof popup == 'undefined' || typeof popup.closed=='undefined') {
  // popup bloqueado
}</pre>
<p>Pero <strong>Chrome no se comporta como el resto de sus competidores</strong>. El navegador de Google requiere de una comprobación &#8220;extra&#8221; realizada desde un popup a través de la función:</p>
<pre>function chrome_popups_permitted() {
  if(window.innerHeight != 0) {
    return true;
  } else return false;
}</pre>
<p>Basta pues con detectar si el navegador del usuario es Chrome y, en tal caso, abrir una ventana con el código Javascript indicado y realizar la llamada a dicha función. <strong>Si los popups están bloqueados</strong>, se redirige al usuario a la URL solicitada en vez de abrirla en una nueva ventana/pestaña.</p>
<p>El resultado final, encapsulado en una clase sencilla, es el siguiente:</p>
<pre>var PopupTester = {
  popup : Object,
  url : "",
  name : "popup_tester",
  options : "width=1,height=1,left=0,top=0",
  open : function(url, name, options) {
    this.url = url
    if (name) this.name = name
    if (options) this.options = options
    if(this.popups_are_disabled() == true) {
      this.redirect_to_instruction_page();
    }
  },

  redirect_to_instruction_page : function() {
    document.location.href = this.url;
  },

  popups_are_disabled : function() {
    this.popup = window.open("/chrome_popup_test.html", this.name, this.options);

    if (!this.popup || this.popup.closed || typeof this.popup == 'undefined' || typeof this.popup.closed=='undefined') {
      return true;
    }

    //
    // Chrome popup detection requires that the popup validates itself
    // - so we need to give
    // the popup time to load, then call js on the popup itself
    //
    if (navigator &amp;&amp; (navigator.userAgent.toLowerCase()).indexOf("chrome") &gt; -1) {
      var on_load_test = function(){PopupTester.test_chrome_popups();};
      var timer = setTimeout(on_load_test, 200);
      return;
    }

    this.popup.location.href = this.url;
    return false;
  },

  test_chrome_popups : function() {
    if (this.popup &amp;&amp; this.popup.chrome_popups_permitted &amp;&amp; this.popup.chrome_popups_permitted() == true) {
      this.popup.location.href = this.url;
      return true;
    }

    this.popup.close();
    //
    // If the popup js fails - popups are blocked
    //
    this.redirect_to_instruction_page();
  }
};</pre>
<p>Y un ejemplo de uso, idéntico al método original:</p>
<pre>PopupTester.open(url, window_name, options)</pre>
<p>Esta solución se basa en la propuesta de <a title="Detect Popup Blocker: Popup Blocker Detection for Chrome + all browsers" href="http://thecodeabode.blogspot.com/2010/11/window-open-popup-blocker-detect-for.html" target="_blank">The Code Abode</a> con algunas modificaciones, que permiten abrir el popup &#8220;de prueba&#8221; bajo demanda, es decir sólo en caso de necesitarlo.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcis.es/detectar-el-bloqueo-de-los-popups/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Extensiones para desarrollo web</title>
		<link>http://blog.marcis.es/extensiones-para-desarrollo-web/</link>
		<comments>http://blog.marcis.es/extensiones-para-desarrollo-web/#comments</comments>
		<pubDate>Tue, 08 Jun 2010 11:18:38 +0000</pubDate>
		<dc:creator>marcis</dc:creator>
				<category><![CDATA[desarrollo web]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[herramientas]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[plugins]]></category>

		<guid isPermaLink="false">http://blog.marcis.es/?p=191</guid>
		<description><![CDATA[A raíz de un par de artículos sobre el tema, os dejo unas cuantas extensiones de Chrome y Firefox para desarrolladores web. Para Firefox: Firebug: no necesita presentación. FireQuery: compatibilidad entre jQuery y Firebug. FirePHP: añade soporte para PHP y Ajax. Web Developer: herramienta que permite activar/desactivar las hojas de estilos, los plugins, el código [...]]]></description>
			<content:encoded><![CDATA[<div style="height:33px;" class="really_simple_share robots-nocontent snap_nopreview"><div class="really_simple_share_facebook_like" style="width:100px;">
				<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.marcis.es%2Fextensiones-para-desarrollo-web%2F&amp;layout=button_count&amp;show_faces=false&amp;width=&amp;action=like&amp;colorscheme=light&amp;send=false&amp;height=27" 
						scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:px; height:27px;" allowTransparency="true"></iframe>
				</div><div class="really_simple_share_twitter" style="width:110px;">
					<a href="http://twitter.com/share" class="twitter-share-button" data-count="horizontal" 
						data-text="Extensiones para desarrollo web" data-url="http://blog.marcis.es/extensiones-para-desarrollo-web/" 
						data-via="" ></a> 
				</div></div>
		<div style="clear:both;"></div><p>A raíz de un par de artículos sobre el tema, os dejo unas cuantas <strong>extensiones</strong> de <a title="Extensiones de Google Chrome para el desarrollo Web" href="http://www.megadual.com/2010/05/31/extensiones-de-google-chrome-para-el-desarrollo-web/" target="_blank">Chrome</a> y <a title="EXTENSIONES DE FIREFOX RECOMENDADAS PARA EL DESARROLLO WEB" href="http://skatox.com/blog/2010/05/27/mis-extensiones-recomendadas-desarrollo-web-firefox/" target="_blank">Firefox</a> para <strong>desarrolladores web</strong>.</p>
<p><span id="more-191"></span>Para <strong>Firefox</strong>:</p>
<ul>
<li><a title="Firebug" href="https://addons.mozilla.org/es-ES/firefox/addon/1843/" target="_blank">Firebug</a>: no necesita presentación.</li>
<li><a title="FireQuery" href="https://addons.mozilla.org/es-ES/firefox/addon/12632/" target="_blank">FireQuery</a>: compatibilidad entre jQuery y Firebug.</li>
<li><a title="FirePHP" href="https://addons.mozilla.org/es-ES/firefox/addon/6149/" target="_blank">FirePHP</a>: añade soporte para PHP y Ajax.</li>
<li><a title="Web Developer" href="https://addons.mozilla.org/es-ES/firefox/addon/60/" target="_blank">Web Developer</a>: herramienta que permite activar/desactivar las hojas de estilos, los plugins, el código javascript, las tablas, las imágenes,&#8230;</li>
<li><a title="HTML Validator" href="https://addons.mozilla.org/firefox/addon/249" target="_blank">Html Validator</a>: evidentemente, ayuda a comprobar si una página cumplen el estándar.</li>
</ul>
<p>Para <strong>Chrome</strong>:</p>
<ul>
<li><a title="Resolution Test" href="https://chrome.google.com/extensions/detail/idhfcdbheobinplaamokffboaccidbal" target="_blank">Resolution Test</a>: permite redimensionar el navegador para visualizar la página en distintas resoluciones y comprobar que &#8220;todo funciona&#8221;.</li>
<li><a title="Speed Tracer" href="http://www.omeyasweb.com/extensiones-de-google-chrome-para-el-desarrollo-web/Speed%20Tracer" target="_blank">Speed Tracer</a>: <a title="Speed Tracer de Google | marcis / blog" href="http://blog.marcis.es/speed-tracer-de-google/" target="_self">ya hablamos de él</a> en este blog.</li>
<li><a title="Pendule" href="https://chrome.google.com/extensions/detail/gbkffbkamcejhkcaocmkdeiiccpmjfdi" target="_blank">Pendule</a>: permite hacer <em>probatinas</em> con los colorer, hojas de estilo, javascript,&#8230;</li>
</ul>
<p>¿Cuáles son vuestras preferidas?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcis.es/extensiones-para-desarrollo-web/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>La velocidad de carga, nuevo factor para Google</title>
		<link>http://blog.marcis.es/la-velocidad-de-carga-nuevo-factor-para-google/</link>
		<comments>http://blog.marcis.es/la-velocidad-de-carga-nuevo-factor-para-google/#comments</comments>
		<pubDate>Tue, 13 Apr 2010 14:19:48 +0000</pubDate>
		<dc:creator>marcis</dc:creator>
				<category><![CDATA[desarrollo web]]></category>
		<category><![CDATA[algoritmo]]></category>
		<category><![CDATA[búsquedas]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[optimización]]></category>
		<category><![CDATA[SEO]]></category>
		<category><![CDATA[velocidad]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.marcis.es/?p=172</guid>
		<description><![CDATA[Tal y como se rumoreaba no hace mucho, la velocidad de carga de una página ha empezado a ser uno de los factores que utiliza Google en su algoritmo de búsqueda. Leemos en Chica Seo que Matt Cutts confirmó el otro día una noticia que se veía venir. Para quitarle importancia al asunto, o quizás para [...]]]></description>
			<content:encoded><![CDATA[<div style="height:33px;" class="really_simple_share robots-nocontent snap_nopreview"><div class="really_simple_share_facebook_like" style="width:100px;">
				<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.marcis.es%2Fla-velocidad-de-carga-nuevo-factor-para-google%2F&amp;layout=button_count&amp;show_faces=false&amp;width=&amp;action=like&amp;colorscheme=light&amp;send=false&amp;height=27" 
						scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:px; height:27px;" allowTransparency="true"></iframe>
				</div><div class="really_simple_share_twitter" style="width:110px;">
					<a href="http://twitter.com/share" class="twitter-share-button" data-count="horizontal" 
						data-text="La velocidad de carga, nuevo factor para Google" data-url="http://blog.marcis.es/la-velocidad-de-carga-nuevo-factor-para-google/" 
						data-via="" ></a> 
				</div></div>
		<div style="clear:both;"></div><p>Tal y como <a title="Google y la velocidad de carga" href="http://blog.marcis.es/google-y-la-velocidad-de-carga/">se rumoreaba no hace mucho</a>, <strong>la velocidad de carga de una página</strong> ha empezado a ser <strong>uno de los factores que utiliza Google en su algoritmo</strong> de búsqueda.</p>
<p><span id="more-172"></span>Leemos en <a title="La velocidad de un sitio, nuevo factor del algoritmo" href="http://www.chicaseo.com/la-velocidad-de-un-sitio-nuevo-factor-del-algoritmo/" target="_blank">Chica Seo</a> que Matt Cutts confirmó el otro día una noticia que se veía venir. Para quitarle importancia al asunto, o quizás para evitarse polémicas, el ingeniero jefe de Google aseguró que el cambio afectará a <strong>menos del 1% de las posiciones</strong> en los resultados.</p>
<p>También aprovecharon para comentar que próximamente se podría tener en cuenta la <strong>reputación</strong> o la <strong>frecuencia de actualización</strong>. Este último factor resultaría bastante interesante ya que, desde mi humilde opinión, los buscadores suelen dar demasiado peso a páginas antiguas (y que pueden estar desfasadas) por el mero hecho de ser más viejas.</p>
<p>Hasta ahora, aumentar la velocidad de carga de nuestra web &#8220;sólo&#8221; <strong>mejoraba la experiencia del usuario</strong>. A partir de este anuncio, las optimizaciones están justificadas también desde el punto de vista del <a title="marcis es SEO" href="http://marcis.es/seo/">SEO</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcis.es/la-velocidad-de-carga-nuevo-factor-para-google/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Cómo instalar WordPress en varios idiomas</title>
		<link>http://blog.marcis.es/como-instalar-wordpress-en-varios-idiomas/</link>
		<comments>http://blog.marcis.es/como-instalar-wordpress-en-varios-idiomas/#comments</comments>
		<pubDate>Thu, 25 Mar 2010 18:42:15 +0000</pubDate>
		<dc:creator>marcis</dc:creator>
				<category><![CDATA[desarrollo web]]></category>
		<category><![CDATA[idioma]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://blog.marcis.es/?p=163</guid>
		<description><![CDATA[A la hora de implementar Safari blog me planteé la opción de utilizar algún plugin para WordPress que me permitiera publicar en dos idiomas (español e inglés) con una sola instalación y, a ser posible, en un solo dominio (el mismo post en cada idioma tendría un título diferente y, por tanto, una URL distinta). [...]]]></description>
			<content:encoded><![CDATA[<div style="height:33px;" class="really_simple_share robots-nocontent snap_nopreview"><div class="really_simple_share_facebook_like" style="width:100px;">
				<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.marcis.es%2Fcomo-instalar-wordpress-en-varios-idiomas%2F&amp;layout=button_count&amp;show_faces=false&amp;width=&amp;action=like&amp;colorscheme=light&amp;send=false&amp;height=27" 
						scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:px; height:27px;" allowTransparency="true"></iframe>
				</div><div class="really_simple_share_twitter" style="width:110px;">
					<a href="http://twitter.com/share" class="twitter-share-button" data-count="horizontal" 
						data-text="Cómo instalar WordPress en varios idiomas" data-url="http://blog.marcis.es/como-instalar-wordpress-en-varios-idiomas/" 
						data-via="" ></a> 
				</div></div>
		<div style="clear:both;"></div><p>A la hora de implementar <a title="Blog de safaris | marcis / blog" href="http://blog.marcis.es/blog-de-safaris/">Safari blog</a> me planteé la opción de utilizar algún <strong>plugin para WordPress que me permitiera publicar en dos idiomas</strong> (español e inglés) con una sola instalación y, a ser posible, en un solo dominio (el mismo post en cada idioma tendría un título diferente y, por tanto, una URL distinta).</p>
<p><span id="more-163"></span>Comencé a investigar/buscar en Google y al final seleccioné estas 3 opciones:</p>
<ul>
<li><a title="Multilingual wordpress" href="http://geoland.org/2007/01/multilingual-wordpress/" target="_blank">Multilingual wordpress</a>: propone un plugin llamado <strong>polyglot</strong>, no demasiado potente y que se debe configurar a mano.</li>
<li><a title="Plugin para cambiar de idioma en WordPress" href="http://www.mediavilla.name/index.php/jr/post/plugin_para_cambiar_de_idioma_en_wordpress/es" target="_blank">Plugin para cambiar de idioma en WordPress</a>: Juan Mediavilla nos explica cómo instalar y configurar <strong>Language Switcher</strong>, para cambiar de idioma. Es más potente que el anterior, pero además del largo proceso inicial requiere que toquemos el código fuente.</li>
<li><a title="Publish Your Blog In Multiple Languages With WPML Plugin For WordPress" href="http://www.bloggingpro.com/archives/2009/12/14/publish-your-blog-in-multiple-languages-with-wpml-plugin-for-wordpress/" target="_blank">WPML Plugin For WordPress</a>: sencillo de instalar y configurar, realiza los cambios necesarios en la base de datos y modifica el código para, por ejemplo, poder publicar el mismo post en dos idiomas, enlazando entre las distintas versiones.</li>
</ul>
<p>Esta última opción parecía adecuada a mis necesidades, pero descubrí un par de características que no me terminaron de convencer:</p>
<ol>
<li>Obliga a elegir una de las siguientes opciones para <strong>distinguir los idiomas</strong>: distintos directorios, diferentes dominios o subdominios o un parámetro adicional.</li>
<li><strong>Problemas</strong> a la hora de traducir el resto de contenidos, por ejemplo los enlaces.</li>
</ol>
<p>Así que finalmente opté por<strong> implementar mi propia solución</strong>, consistente en:</p>
<ul>
<li><strong>Dos (sub)dominios distintos</strong> para las versiones en inglés y español. No era del todo de mi agrado, pero simplificaba el código y evitaba problemas con la indexación de contenidos.</li>
<li><strong>Una sola copia del código</strong> que, en función del dominio, ataca a una u otra base de datos, configura el idioma adecuado y establece el formato de fecha. Se puede implementar con una simple comprobación de la variable $_SERVER['SERVER_NAME'] en el archivo &#8220;wp-config.php&#8221;.</li>
<li>En algunos ficheros, <strong>se modifican los contenidos en función del idioma</strong> de la aplicación. Por ejemplo, el botón para cambiar de idioma o los enlaces a twitter y Facebook en la cabecera.</li>
</ul>
<p>La mejor <strong>solución</strong> depende de los requerimientos de cada caso, espero que las distintas opciones comentadas os puedan servir de inspiración.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcis.es/como-instalar-wordpress-en-varios-idiomas/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Speed Tracer de Google</title>
		<link>http://blog.marcis.es/speed-tracer-de-google/</link>
		<comments>http://blog.marcis.es/speed-tracer-de-google/#comments</comments>
		<pubDate>Fri, 11 Dec 2009 17:01:31 +0000</pubDate>
		<dc:creator>marcis</dc:creator>
				<category><![CDATA[desarrollo web]]></category>
		<category><![CDATA[aplicaciones]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[herramientas]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://blog.marcis.es/?p=73</guid>
		<description><![CDATA[Speed Tracer es una herramienta, lanzada por Google recientemente, que sirve para &#8220;identificar y solucionar problemas de rendimiento en las aplicaciones web&#8220;. Fundamentalmente, su funcionamiento se basa en el tiempo de carga de la página desde que realizas la petición hasta que ésta termina por completo. Speed Tracer te muestra una gráfica de los tiempos [...]]]></description>
			<content:encoded><![CDATA[<div style="height:33px;" class="really_simple_share robots-nocontent snap_nopreview"><div class="really_simple_share_facebook_like" style="width:100px;">
				<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.marcis.es%2Fspeed-tracer-de-google%2F&amp;layout=button_count&amp;show_faces=false&amp;width=&amp;action=like&amp;colorscheme=light&amp;send=false&amp;height=27" 
						scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:px; height:27px;" allowTransparency="true"></iframe>
				</div><div class="really_simple_share_twitter" style="width:110px;">
					<a href="http://twitter.com/share" class="twitter-share-button" data-count="horizontal" 
						data-text="Speed Tracer de Google" data-url="http://blog.marcis.es/speed-tracer-de-google/" 
						data-via="" ></a> 
				</div></div>
		<div style="clear:both;"></div><p><strong>Speed Tracer</strong> es una herramienta, lanzada por Google recientemente, que sirve para &#8220;identificar y solucionar <strong>problemas de rendimiento en las aplicaciones web</strong>&#8220;.</p>
<p><span><span id="more-73"></span>Fundamentalmente, su funcionamiento se basa en el <strong>tiempo de carga de la página</strong> desde que realizas la petición hasta que ésta termina por completo.</span></p>
<p><span>Speed Tracer te muestra una <strong>gráfica de los tiempos invertidos</strong> en el transporte por la red, la recepción de la página, su carga y <em>renderizado</em>, así como la petición y carga de otros archivos dependientes de la página (imágenes, javascript, códigos externos,&#8230;).</span></p>
<div id="attachment_75" class="wp-caption aligncenter" style="width: 458px"><strong><img class="size-full wp-image-75" title="Speed Tracer" src="http://blog.marcis.es/wp-content/uploads/2009/12/Speed-Tracer.jpg" alt="Captura de un ejemplo de uso de Speed Tracer" width="448" height="271" /></strong><p class="wp-caption-text">Captura de un ejemplo de uso de Speed Tracer</p></div>
<p><span>De esa forma puedes detectar cuáles son los <strong>puntos críticos</strong> de tu aplicación web, es decir aquellos que merece la pena optimizar. La información, que se muestra de una manera muy visual, es bastante completa y te permite ampliar los detalles de cada una de las fases y sus componentes.</span></p>
<p><span>Speed Tracer está diponible como una <strong>extensión de Chrome para desarrolladores web</strong> en sus versiones para Windows y Linux.</span></p>
<p>Más detalles en <a title="Speed Tracer - Google Web Toolkit - Google Code" href="http://code.google.com/intl/es-ES/webtoolkit/speedtracer/" target="_blank">Speed Tracer &#8211; Google Web Toolkit &#8211; Google Code</a> y en <a title="Speed Tracer" href="http://code.google.com/p/speedtracer/" target="_blank">la página del proyecto</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcis.es/speed-tracer-de-google/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Servicios de captura de pantalla</title>
		<link>http://blog.marcis.es/servicios-de-captura-de-pantalla/</link>
		<comments>http://blog.marcis.es/servicios-de-captura-de-pantalla/#comments</comments>
		<pubDate>Fri, 20 Nov 2009 13:52:15 +0000</pubDate>
		<dc:creator>marcis</dc:creator>
				<category><![CDATA[desarrollo web]]></category>
		<category><![CDATA[capturas]]></category>
		<category><![CDATA[miniaturas]]></category>
		<category><![CDATA[pantalla]]></category>
		<category><![CDATA[previsualizar]]></category>

		<guid isPermaLink="false">http://blog.marcis.es/servicios-de-captura-de-pantalla/</guid>
		<description><![CDATA[Seguro que alguna vez, navegando en Internet, has visto una miniatura con la captura de pantalla de un sitio web. Esta imagen puede ser útil para tus usuarios, puesto que les permite previsualizar la web antes de visitarla. Incluir esta funcionalidad en tu aplicación es muy sencillo. Existen librerías gráficas (al menos en PHP) que [...]]]></description>
			<content:encoded><![CDATA[<div style="height:33px;" class="really_simple_share robots-nocontent snap_nopreview"><div class="really_simple_share_facebook_like" style="width:100px;">
				<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.marcis.es%2Fservicios-de-captura-de-pantalla%2F&amp;layout=button_count&amp;show_faces=false&amp;width=&amp;action=like&amp;colorscheme=light&amp;send=false&amp;height=27" 
						scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:px; height:27px;" allowTransparency="true"></iframe>
				</div><div class="really_simple_share_twitter" style="width:110px;">
					<a href="http://twitter.com/share" class="twitter-share-button" data-count="horizontal" 
						data-text="Servicios de captura de pantalla" data-url="http://blog.marcis.es/servicios-de-captura-de-pantalla/" 
						data-via="" ></a> 
				</div></div>
		<div style="clear:both;"></div><p><img alt="thumbshots vs websnapr" align="right" src="http://blog.marcis.es/wp-content/uploads/2009/11/thumbshotsvswebsnapr.jpg" width="316" height="100" />Seguro que alguna vez, navegando en Internet, has visto una <strong>miniatura con la captura de pantalla</strong> de un sitio web. Esta imagen puede ser útil para tus usuarios, puesto que les permite <strong>previsualizar la web</strong> antes de visitarla. Incluir esta funcionalidad en tu aplicación es muy sencillo.</p>
<p><span id="more-61"></span>
<p>Existen <strong>librerías gráficas</strong> (al menos en PHP) que te permiten generar esas capturas desde tu propio servidor. Pero si no quieres sobrecargarlo es mejor utilizar un <strong>servicio de captura de pantallas</strong> (<em>preview, thumbshot o snap,</em> en inglés).</p>
<p>Investigando, para utilizarlo en un proyecto, descubrí un par de opciones interesantes: <strong>thumbshots.com</strong> y <strong>websnapr.com</strong>.</p>
<p><a title="Thumbshots.com" href="http://www.thumbshots.com/" target="_blank">Thumbshots</a> te permite mostrar una captura de pantalla en miniatura insertando un sencillo código HTML que consiste en una imagen (qué menos!?) en la que tan solo debes incluir la <strong>URL del sitio que deseas capturar</strong>:</p>
<blockquote>
<p>&lt;img src=&#8221;<a href="http://open.thumbshots.org/image.aspx?url=[LINK">http://open.thumbshots.org/image.aspx?url=[LINK</a>]&#8221; border=&#8221;1&#8243; /&gt;</p>
</blockquote>
<p>Su versión gratuita sólo incluye URLs de primer nivel (es decir, nombres de dominio), un tamaño de 120&#215;90 pixels y requiere un enlace recíproco.</p>
<p>En cambio <a title="websnapr - pre visualizaciones para su sitio web" href="http://www.websnapr.com/es/" target="_blank">websnapr 2.0</a> te ofrece hasta 100.000 impresiones gratuitas al mes, con un tamaño algo mayor (202&#215;152) y está disponible en español.</p>
<p>Otra de las ventajas de este sistema son los <strong>plugins</strong> que han desarrollado alrededor de la herramienta principal y que te permiten, por ejemplo, mostrar la imagen previa del sitio web cuando el ratón pasa por encima de un enlace.</p>
<p>Para usar ambas opciones necesitas registrarte previamente. En el caso de websnapr recibes una &#8220;clave de desarrollador&#8221; que debes incluir en todas tus peticiones:</p>
<blockquote>
<p><a href="http://images.websnapr.com/?size=size&amp;key=key&amp;url=url">http://images.websnapr.com/?size=size&amp;key=key&amp;url=url</a></p>
</blockquote>
<p>El resultado final sería este:</p>
<p align="center"><img alt="captura previa del blog de marcis" src="http://images.websnapr.com/?size=S&amp;key=q1GnlJxCt25T&amp;url=blog.marcis.es" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcis.es/servicios-de-captura-de-pantalla/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Surviving The Deep End, introducción a Zend Framework</title>
		<link>http://blog.marcis.es/surviving-the-deep-end-introduccion-a-zend-framework/</link>
		<comments>http://blog.marcis.es/surviving-the-deep-end-introduccion-a-zend-framework/#comments</comments>
		<pubDate>Thu, 05 Nov 2009 12:24:19 +0000</pubDate>
		<dc:creator>marcis</dc:creator>
				<category><![CDATA[desarrollo web]]></category>
		<category><![CDATA[documentacion]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[libros]]></category>
		<category><![CDATA[manuales]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Zend]]></category>

		<guid isPermaLink="false">http://blog.marcis.es/surviving-the-deep-end-introduccion-a-zend-framework/</guid>
		<description><![CDATA[Empezar a utilizar el framework de Zend puede ser como un dolor de muelas. La documentación del portal es buena, pero se echa de menos una mejor explicación del entorno, cómo funciona, su instalación y cómo empezar a desarrollar una aplicación de verdad. Surviving The Deep End es un libro online gratuito sobre el framework [...]]]></description>
			<content:encoded><![CDATA[<div style="height:33px;" class="really_simple_share robots-nocontent snap_nopreview"><div class="really_simple_share_facebook_like" style="width:100px;">
				<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.marcis.es%2Fsurviving-the-deep-end-introduccion-a-zend-framework%2F&amp;layout=button_count&amp;show_faces=false&amp;width=&amp;action=like&amp;colorscheme=light&amp;send=false&amp;height=27" 
						scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:px; height:27px;" allowTransparency="true"></iframe>
				</div><div class="really_simple_share_twitter" style="width:110px;">
					<a href="http://twitter.com/share" class="twitter-share-button" data-count="horizontal" 
						data-text="Surviving The Deep End, introducción a Zend Framework" data-url="http://blog.marcis.es/surviving-the-deep-end-introduccion-a-zend-framework/" 
						data-via="" ></a> 
				</div></div>
		<div style="clear:both;"></div><p>Empezar a utilizar el <strong>framework de Zend</strong> puede ser como un dolor de muelas. <a title="Zend Framework Documentation - Overview" href="http://framework.zend.com/docs/overview" target="_blank">La documentación del portal</a> es buena, pero se echa de menos una mejor explicación del entorno, cómo funciona, su instalación y <strong>cómo empezar a desarrollar una aplicación</strong> de verdad.</p>
<p><span id="more-54"></span>
<p><a title="Zend Framework Book: Surviving The Deep End" href="http://www.survivethedeepend.com/" target="_blank">Surviving The Deep End</a> es un <strong>libro online gratuito</strong> sobre el framework Zend, que sirve de introducción a este entorno de desarrollo basado en PHP y la arquitectura MVC.</p>
<p align="center"><img alt="Zend Framework: surviving the deep end" src="http://blog.marcis.es/wp-content/uploads/2009/11/zendframeworksurvivingthedeepend.jpg" width="568" height="100" /></p>
<p>Comienza explicando <strong>qué es Zend Framework</strong>, su filosofía y sus principales ventajas. Continúa con la arquitectura y cómo ha implementado las 3 capas: Modelo, Vista y Controlador.</p>
<p>Después de un capítulo dedicado a su instalación, encontramos el típico ejemplo de &#8220;Hello World&#8221;.</p>
<p>A partir de ahí entra en temas más &#8220;interesantes&#8221; si queremos desarrollar una aplicación real, como las clases más importantes, el manejo de errores, el diseño o la optimización.</p>
<p>Una lectura recomendable para quienes estén dando sus <strong>primeros pasos con Zend</strong>.</p>
<p>Nota: el manual, por supuesto, está implementado con Zend.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcis.es/surviving-the-deep-end-introduccion-a-zend-framework/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Desarrollar un plugin para WordPress</title>
		<link>http://blog.marcis.es/desarrollar-un-plugin-para-wordpress/</link>
		<comments>http://blog.marcis.es/desarrollar-un-plugin-para-wordpress/#comments</comments>
		<pubDate>Thu, 15 Oct 2009 14:09:41 +0000</pubDate>
		<dc:creator>marcis</dc:creator>
				<category><![CDATA[desarrollo web]]></category>
		<category><![CDATA[blog]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[proyectos]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://blog.marcis.es/desarrollar-un-plugin-para-wordpress/</guid>
		<description><![CDATA[Dentro del proyecto en el que trabajo surgió la necesidad de crear una serie de herramientas externas de apoyo al usuario. La primera, y seguramente la más importante, era un plugin para WordPress que integrara nuestra aplicación con una de las plataformas de blogs más usadas. Sólo conocía WP como usuario y administrador, sin tener [...]]]></description>
			<content:encoded><![CDATA[<div style="height:33px;" class="really_simple_share robots-nocontent snap_nopreview"><div class="really_simple_share_facebook_like" style="width:100px;">
				<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.marcis.es%2Fdesarrollar-un-plugin-para-wordpress%2F&amp;layout=button_count&amp;show_faces=false&amp;width=&amp;action=like&amp;colorscheme=light&amp;send=false&amp;height=27" 
						scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:px; height:27px;" allowTransparency="true"></iframe>
				</div><div class="really_simple_share_twitter" style="width:110px;">
					<a href="http://twitter.com/share" class="twitter-share-button" data-count="horizontal" 
						data-text="Desarrollar un plugin para WordPress" data-url="http://blog.marcis.es/desarrollar-un-plugin-para-wordpress/" 
						data-via="" ></a> 
				</div></div>
		<div style="clear:both;"></div><p><img alt="WordPress" align="right" src="http://blog.marcis.es/wp-content/uploads/2009/10/wordpress-logo-cristal1.jpg" width="128" height="128" />Dentro del proyecto en el que trabajo surgió la necesidad de crear una serie de herramientas externas de apoyo al usuario. La primera, y seguramente la más importante, era un <strong>plugin para WordPress</strong> que integrara nuestra aplicación con una de las plataformas de blogs más usadas.</p>
<p><span id="more-35"></span>
<p>Sólo conocía WP como usuario y administrador, sin tener apenas idea de su implementación. Empecé a buscar recursos y a leer.</p>
<p>He de reconocer que me gustó la estructura interna de WordPress y que <strong>resultó bastante sencillo</strong> implementar un plugin básico, tarea que seguramente habría sido más complicada sin conocimientos previos de PHP y MySQL.</p>
<p>Aunque opino que <strong>los desarrollos web nunca se terminan</strong>, disponemos de una versión bastante avanzada del plugin con las siguientes funcionalidades:</p>
<ul>
<li>Instalación/desinstalación, incluyendo la interacción con la base de datos.</li>
<li>Actualización de una tabla en función de los resultados de una llamada remota.</li>
<li>Gestión, por parte del usuario, de las opciones de configuración.</li>
<li>Modificación parcial de los contenidos del blog, a partir de la información de la base de datos.</li>
</ul>
<p>Como comentaba, el desarrollo no tuvo grandes complicaciones ya que <strong>WP facilita enormemente la tarea</strong> con los <em>hooks</em> (¿puntos de enganche?): métodos de instalación/desinstalación, gestión de menús, configuración, comunicación con la base de datos,&#8230;</p>
<p>Si hubiera que ponerle alguna pega, diría que <strong>la creación de páginas de opciones podría ser más ligera</strong>.</p>
<p>Había pensado publicar un breve manual sobre <strong>cómo crear un plugin para WordPress</strong> desde cero, pero hay un par de motivos que me han desanimado. Primero, hay bastante documentación disponible y de buena calidad. Segundo, dependiendo de lo que quieras hacer el número de posibilidades que ofrece WP es incontable y, lamentablemente, no tengo tiempo suficiente para abarcarlas todas. Así que me limitaré a compartir con vosotros los enlaces que más me ayudaron durante el proceso:</p>
<ul>
<li><a title="Plugin Resources &lt;&lt; WordPress Codex &gt; WordPress Codex" href="http://codex.wordpress.org/Plugin_Resources" target="_blank">Plugin Resources</a>: introducción &#8220;oficial&#8221; a los <em>plugins</em> de WordPress y recursos relacionados (en inglés).</li>
<li><a title="Writing a Plugin &lt;&lt; WordPress Codex" href="http://codex.wordpress.org/Writing_a_Plugin" target="_blank">Writing a Plugin</a>: otra página oficial sobre cómo crear un plugin, convenciones de nombres, archivos, opciones, sugerencias,&#8230; (en inglés).</li>
<li><a title="Crear un plugin para wordpress - aurea" href="http://aurea.es/2008/04/17/crear-un-plugin-para-wordpress/" target="_blank">Crear un plugin para wordpress</a>: tutorial muy básico pero sencillo de comprender.</li>
<li><a title="Estandarización en los plugins para WordPress, desde el usuario | Blog en Serio" href="http://blogenserio.com/2008/01/sugerencias-para-la-estandarizacion-de-plugins-de-wordpress/" target="_blank">Estandarización de los plugins para WordPress</a>: sugerencias para estandarizar tanto el código como el contenido de los plugins.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcis.es/desarrollar-un-plugin-para-wordpress/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Acceder al portapapeles desde Javascript</title>
		<link>http://blog.marcis.es/acceder-al-portapapeles-desde-javascript/</link>
		<comments>http://blog.marcis.es/acceder-al-portapapeles-desde-javascript/#comments</comments>
		<pubDate>Wed, 07 Oct 2009 19:23:44 +0000</pubDate>
		<dc:creator>marcis</dc:creator>
				<category><![CDATA[desarrollo web]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[internet explorer]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[usabilidad]]></category>

		<guid isPermaLink="false">http://blog.marcis.es/?p=17</guid>
		<description><![CDATA[Estoy trabajando en un proyecto en el que hemos decidido mostrarle al usuario, para facilitarle la tarea, un botón o enlace que le permita copiar un texto al portapapeles. De esa forma puede realizar dos acciones con un solo click: seleccionar y copiar. Empecé la investigación (léase búsqueda en Google) y obtuve resultados demasiado buenos [...]]]></description>
			<content:encoded><![CDATA[<div style="height:33px;" class="really_simple_share robots-nocontent snap_nopreview"><div class="really_simple_share_facebook_like" style="width:100px;">
				<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fblog.marcis.es%2Facceder-al-portapapeles-desde-javascript%2F&amp;layout=button_count&amp;show_faces=false&amp;width=&amp;action=like&amp;colorscheme=light&amp;send=false&amp;height=27" 
						scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:px; height:27px;" allowTransparency="true"></iframe>
				</div><div class="really_simple_share_twitter" style="width:110px;">
					<a href="http://twitter.com/share" class="twitter-share-button" data-count="horizontal" 
						data-text="Acceder al portapapeles desde Javascript" data-url="http://blog.marcis.es/acceder-al-portapapeles-desde-javascript/" 
						data-via="" ></a> 
				</div></div>
		<div style="clear:both;"></div><p>Estoy trabajando en un proyecto en el que hemos decidido mostrarle al usuario, para facilitarle la tarea, un botón o enlace que le permita <strong>copiar un texto al portapapeles</strong>. De esa forma puede realizar dos acciones con un solo <em>click</em>: seleccionar y copiar.</p>
<p><span id="more-17"></span>Empecé la investigación (léase búsqueda en Google) y obtuve resultados demasiado buenos para ser verdad. Gracias al método &#8220;setData&#8221; del objeto &#8220;clipboardData&#8221; era sencillo cumplir mi objetivo:</p>
<pre style="padding-left: 30px;">clipboardData.setData("Text", s)
// siendo "s" una variable que contiene el texto a copiar</pre>
<p>Pero no podía ser tan fácil. El código anterior sólo funciona en Internet Explorer, así que seguí buscando una solución <em>cross-browser</em> o, como mínimo, <strong>compatible</strong> con Firefox.</p>
<p>Después de <a title="Dynamic Tools - Javascript Copy To Clipboard" href="http://www.dynamic-tools.net/toolbox/copyToClipboard/" target="_blank">algún intento infructuoso</a>, encontré <a title="Javascript copy to Firefox and Mozilla clipboard" href="http://www.febooti.com/support/website-help/website-javascript-copy-clipboard.html" target="_blank">este ejemplo</a> que funcionaba&#8230; con ciertas <strong>restricciones</strong>.</p>
<p>Por lo visto, las <a title="Security Policies - MozillaZine Knowledge Base" href="http://kb.mozillazine.org/Security_Policies" target="_blank">políticas de seguridad de Mozilla</a> impiden la ejecución de dicho código. Y puede que con motivo, ya que de lo contrario <a title="Retrieve Clipboard Text To A Web Page With Javascript - Make Sure You Do Not Allow Someone To Gather This Information, It Is An Exploit In Many Eyes" href="http://www.friendlycanadian.com/applications/clipboard.htm" target="_blank">cualquier página podría tener acceso a tu portapapeles</a> y, por lo tanto, a <strong>información potencialmente delicada</strong> (direcciones de e-mail, teléfonos, números de tarjeta de crédito,&#8230; o cualquier otro dato que hayas copiado).</p>
<p>Llegados a este punto, existían dos opciones para <strong>poder copiar el texto en Firefox</strong>:</p>
<ul>
<li><a title="JavaScript Security: Signed Scripts" href="http://www.mozilla.org/projects/security/components/signed-scripts.html" target="_blank">Firmar el script</a>, demasiado costoso para lo que queremos hacer</li>
<li>Confiar en que el usuario tenga activada la opción &#8220;signed.applets.codebase_principal_support&#8221; en su configuración (<a title="About:config entries - MozillaZine Knowledge Base" href="http://kb.mozillazine.org/Firefox_:_FAQs_:_About:config_Entries" target="_blank">about:config</a>), o bien esté dispuesto a habilitarla</li>
</ul>
<p>Si estamos pensando en hacer la aplicación más fácil de usar, <strong>no podemos pedirle al usuario</strong> que configure su navegador de una forma especial, que además conlleva cierto riesgo.</p>
<p>A todo esto hay que unir por un lado un <a title="Febooti Software" href="http://www.febooti.com/scripts/febooti.js" target="_blank">código fuente</a> bastante &#8220;farragoso&#8221;, lleno de capturas de excepciones y avisos al usuario. Y por otro, las <strong>alertas de seguridad</strong> que tanto IE como FF muestran antes de permitir la copia de contenidos al portapapeles. Seguro, pero poco práctico.</p>
<p>Me estaba replanteando la decisión de incluir esta funcionalidad cuando encontré <strong>una solución algo más limpia</strong>. Inicialmente había descartado la opción de implementarla usando Flash, pero al ver <a title="AddThis - Get Your Button Code" href="http://www.addthis.com/web-button?type=bm&amp;where=website&amp;url=&amp;bm=bn3&amp;analytics=0" target="_blank">la alternativa de AddThis</a> volví a cambiar de opinión.</p>
<p>La propuesta se basa en 4 elementos:</p>
<ol>
<li>La <a title="jQuery: The Write Less, Do More, JavaScript Library" href="http://jquery.com/" target="_blank">librería jQuery</a>, versión 1.3.2 reducida, como apoyo.</li>
<li>Un archivo de Flash, <a title="ZeroClipboard.swf" href="http://www.addthis.com/lib/zeroclipboard/ZeroClipboard.swf" target="_blank">ZeroClipboard.swf</a>, que fundamentalmente consiste en una imagen transparente que &#8220;captura&#8221; los eventos del ratón y copia un texto predefinido al portapapeles. Si teneis curiosidad por saber cómo está implementado, os recomiendo <a title="SWF Decompiler, Flash Decompiler, SWF to Flex,  SWF To FLA Converter, Recover FLA" href="http://www.sothink.com/product/flashdecompiler/" target="_blank">Sothink SWF Decompiler</a>.</li>
<li>Una clase, <a title="Simple Set Clipboard System" href="http://cache.addthis.com/www/q0004/lib/zeroclipboard/ZeroClipboard.js" target="_blank">ZeroClipboard</a>, que sirve de enlace entre el Flash y el Javascript de la página.</li>
<li>El <a title="ZeroClipboard example" href="http://cache.addthis.com/www/q0004/js/web-button.js" target="_blank">código Javascript que se ejecuta en la página</a> y que analizaremos a continuación:</li>
</ol>
<pre style="padding-left: 30px;">// Inicializamos el objeto ZeroClipboard con la ruta del fichero Flash
ZeroClipboard.setMoviePath('/lib/zeroclipboard/ZeroClipboard.swf');
// Usaremos como "disparadores" los elementos con class="copybtn"
$('.copybtn').each(function(){
    // Para diferenciarlos deben llamarse copybtn[X], siendo [X] un entero
    c = this.id.substr(7);
    // Se crea un "cliente" para cada disparador
    clips[c] = new ZeroClipboard.Client();
    // El texto se tomará del elemento con id="txt[X]"
    clips[c].setText($('#txt'+c).val());
    // Al terminar de copiar, ejecutar la función "cplt" (más abajo)
    clips[c].addEventListener('onComplete', cplt);
    // Si no está oculto, "pegar" el Flash al elemento actual
    // (es decir, colocarlo justo encima ocupando toda su extensión)
    if (!$(this).hasClass('hidebtn')) clips[c].glue(this);
}).bind('toggle',function(e){
    // Comportamiento cuando se cambie de un elemento a otro
    ...
});

// Al terminar, selecciona el texto copiado
// y muestra un mensaje de confirmación durante unos segundos
var cplt = function(client, text)
{
    c = client.domElement.id.substr(7);
    // Selecciona el contenido del "textarea"
    // (si usamos otro elemento, habrá que modificar esta línea)
    $('#txt'+c).get(0).select();
    $('#copyfdbk'+c).html('&amp;nbsp;&lt;em&gt;Copied&lt;/em&gt;').show();
    setTimeout("$('#copyfdbk"+c+"').fadeOut()", 2500);
}</pre>
<p>En cuanto al HTML, destacar sólo un par de detalles:</p>
<pre style="padding-left: 30px;">&lt;!-- El contenedor del texto es un textarea con el id adecuado --&gt;
&lt;<span>textarea</span><span> rows</span>=<span>"5" </span><strong><span>id</span>=</strong><span><strong>"txt0"</strong> </span><span>wrap</span>=<span>"off"...</span>
&lt;!-- El disparador es un botón con el id y la clase indicados --&gt;
&lt;<span>input</span><span> <strong>id</strong></span><strong>=</strong><span><strong>"copybtn0"</strong> </span><span>type</span>=<span>"button" </span><span>value</span>=<span>"Copy Code" </span><span>class</span>=<span>"<strong>copybtn</strong> lgbtn" </span><span><span>/</span></span>&gt;
&lt;!-- El elemento donde se mostrará el "feedback" --&gt;
&lt;<span>span</span><span> <strong>id</strong></span><strong>=<span>"copyfdbk0"</span></strong>&gt;&lt;/<span>span</span>&gt;</pre>
<p>Lo único que falta es ejecutar el código Javascript al terminar de cargar la página.</p>
<p>Más información sobre <a title="zeroclipboard - Project Hosting on Google Code" href="http://code.google.com/p/zeroclipboard/" target="_blank">Zero Clipboard en Google Code</a>.</p>
<h3>Seleccionar el contenido de un <em>span</em></h3>
<p>Como comentaba más arriba, si queremos <strong>seleccionar el texto</strong> de un elemento que no sea un <em>textarea</em> tendremos que modificar la llamada:</p>
<pre style="padding-left: 30px;">// $('#txt'+c).get(0).select();
selectElement($('#text_to_copy_'+c).get(0))

// Siendo la función:
function selectElement (element)
{
    if (document.selection) {
        var range = document.body.createTextRange();
        range.moveToElementText(element);
        range.select();
    } else if (window.getSelection) {
        var range = document.createRange();
        range.selectNodeContents(element);
        var selection = window.getSelection();
        selection.removeAllRanges();
        selection.addRange(range);
    }
}</pre>
<p>Os dejo un <a title="FAQTs - Knowledge Base - View Entry - I want to select some span text dynamically using Javascipt. Is there any way to do that?" href="http://www.faqts.com/knowledge_base/view.phtml/aid/37741" target="_blank">enlace a la fuente original</a> con su correspondiente explicación.</p>
<h3>¿Y si el usuario no tiene instalado el plugin de Flash?</h3>
<p>Por último, si no queremos confiar el funcionamiento del <em>script</em> en la carga del Flash podemos hacer una pequeña modificación:</p>
<ul>
<li>Retomamos la función Javascript que <a title="Febooti Software" href="http://www.febooti.com/scripts/febooti.js" target="_blank">copia un texto al portapapeles</a>. Llamémosla &#8220;copyToClipboard&#8221;.</li>
<li>En el bucle que recorre los disparadores, le asignamos a cada uno de ellos un gestor del evento &#8220;click&#8221; que llame a &#8220;copyToClipboard&#8221;.</li>
<li>Hacemos un cambio en el método &#8220;glue&#8221; de la clase &#8220;ZeroClipboard.Client&#8221; para que coloque el Flash fuera de lugar:</li>
</ul>
<pre style="padding-left: 30px;">// style.left = '' + box.left + 'px';
style.left = '0px';
// style.top = '' + box.top + 'px';
style.top = '0px';</pre>
<ul>
<li>Y añadimos otro gestor de eventos al objeto cliente, para comprobar que se carga correctamente:</li>
</ul>
<pre style="padding-left: 30px;">clips[c].addEventListener('onLoad', loaded);</pre>
<pre style="padding-left: 30px;">// Colocar en su sitio si todo va bien
var loaded = function(client) {
    c = client.domElement.id.substr(12);
    clips[c].reposition();
}</pre>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 1667px; width: 1px; height: 1px;">
<pre style="padding-left: 30px;">style.top = '' + box.top + 'px';</pre>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcis.es/acceder-al-portapapeles-desde-javascript/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>

