<?xml version="1.0" encoding="UTF-8" ?>	<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"> 
	<channel>
		<title>Blog de Imaginanet S.L. Programacion web y marketing online.</title>
		<link>http://www.imaginanet.com/blog.html</link>
		<description>Blog de Imaginanet. Artículos especializados en soluciones y desarrollo Web.</description>
		<lastBuildDate>Sat, 25 May 2013 21:28:12 +0100</lastBuildDate> 
		<generator>imaginaCMS</generator>
		<language>es</language>
		<sy:updatePeriod>weekly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
		<image> 
		    <title>Blog de Imaginanet S.L. Programacion web y marketing online.</title> 
		    <url>http://www.imaginanet.com/logo.png</url> 
		    <link>http://www.imaginanet.com/blog.html</link> 
		    <width>144</width> 
		    <height>53</height> 
	    </image>
	    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://www.imaginanet.com/feeds.htm" />
	    <feedburner:browserFriendly>
	    	Este es un feed de contenido XML. Para visualizarlo es necesario un programa de lectura de noticias y desde feedburner, el feed está sujeto a los derechos de autor y a un uso responsable. 
	    	/
	    	This is an XML content feed. It is intended to be viewed in a newsreader or syndicated to another site, subject to copyright and fair use.
	    </feedburner:browserFriendly><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" />
			
		<item>
			<title>Universal Analytics. Google lo abre a todos sus clientes</title>
			<link>http://www.imaginanet.com/blog/universal-analytics-google-lo-abre-a-todos-sus-clientes.html</link>
			<guid>http://www.imaginanet.com/blog/universal-analytics-google-lo-abre-a-todos-sus-clientes.html</guid>
			<comments>http://www.imaginanet.com/blog/universal-analytics-google-lo-abre-a-todos-sus-clientes.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed, 22 May 2013 18:15:28 +0100</pubDate>
					<category><![CDATA[Google Analytics]]></category>
					<description><![CDATA[Destacando el potencial de Universal Analytics, Google ha anunciado que estar&aacute; disponible para todos sus usuarior de Analytics. Universal Analytics permite conocer cual es la interacci&oacute;n que tienen los usuarios con una web con independencia se si el acceso es a trav&eacute;s de varios dispositivos o aplicaciones para...]]></description>
			<content:encoded><![CDATA[><p>Destacando el potencial de <strong>Universal Analytics</strong>, Google ha anunciado que estar&aacute; disponible para todos sus usuarior de Analytics. Universal Analytics permite conocer cual es la interacci&oacute;n que tienen los usuarios con una web con independencia se si el acceso es a trav&eacute;s de varios dispositivos o aplicaciones para m&oacute;vil.</p>
<p>Despu&eacute;s de un periodo de pruebas en el que Universal Analytics estuvo disponible para un grupo controlado de clientes de Analytics, <strong>Google ha decidido abrirlo a todos los usuarios</strong>, pasando a ser una beta p&uacute;blica.</p>
<p>En el siguiente video se muestra un ejemplo de la utilizaci&oacute;n de Universal Analytics por parte de una empresa (EN)</p>
<p><br /><iframe src="http://www.youtube.com/embed/wWfWQzKBMTk" width="560" height="315"></iframe></p>
<p>Google intenta responder a la necesidad por parte de las empresas de monitorizar las interacciones de los usuarios con su p&aacute;gina web, teniendo en cuenta que hoy en d&iacute;a estos accesos se producen desde varios dispositivos. Adem&aacute;s esta herramienta destaca al ofrecer i<strong>nformes de accesos desde dispositivos m&oacute;viles</strong>, permitiendo obtener un retorno mejor de las inversiones de la empresa en esos dispositivos.</p>
<p>Un paso m&aacute;s en el interesante desarrollo de esta herramienta.</p>
<p><br /><strong><a href="http://analytics.blogspot.com.es/2013/03/expanding-universal-analytics-into.html" target="_blank">M&aacute;s informaci&oacute;n en el blog de Analytics</a></strong> (EN).</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=153</wfw:commentRss>
			<slash:comments>1</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/universal-analytics-google-lo-abre-a-todos-sus-clientes.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Responsive design, versión móvil de tu web o aplicación móvil. ¿Cómo elegir?</title>
			<link>http://www.imaginanet.com/blog/responsive-design-version-movil-de-tu-web-o-aplicacion-movil-como-elegir.html</link>
			<guid>http://www.imaginanet.com/blog/responsive-design-version-movil-de-tu-web-o-aplicacion-movil-como-elegir.html</guid>
			<comments>http://www.imaginanet.com/blog/responsive-design-version-movil-de-tu-web-o-aplicacion-movil-como-elegir.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed, 15 May 2013 21:03:36 +0100</pubDate>
					<category><![CDATA[Apps]]></category>
					<category><![CDATA[Google Apps]]></category>
					<category><![CDATA[HTML5]]></category>
					<category><![CDATA[SEO]]></category>
					<category><![CDATA[CSS]]></category>
					<description><![CDATA[Cada d&iacute;a crece el numero de usuarios que accede al contenido que se ofrece en Internet desde dispositivos m&oacute;viles. Es previsible que para el a&ntilde;o 2015 los&nbsp; usuarios de Internet m&oacute;viles sean m&aacute;s que los que acceden v&iacute;a ordenadores de escritorio.
Por eso es importante que la...]]></description>
			<content:encoded><![CDATA[><p>Cada d&iacute;a crece el numero de usuarios que accede al contenido que se ofrece en Internet desde dispositivos m&oacute;viles. Es previsible que para el a&ntilde;o 2015 los&nbsp; usuarios de Internet m&oacute;viles sean m&aacute;s que los que acceden v&iacute;a ordenadores de escritorio.</p>
<p>Por eso es importante que la informaci&oacute;n de tu empresa est&eacute; en Internet de la forma m&aacute;s optimizada y accesible posible. Sin embargo todav&iacute;a existe un debate sobre cu&aacute;l de los tres m&eacute;todos descritos a continuaci&oacute;n es mejor: dise&ntilde;o responsive, versi&oacute;n web espec&iacute;fica para m&oacute;viles o una aplicaci&oacute;n m&oacute;vil.</p>
<p><strong>Dise&ntilde;o web Responsive</strong></p>
<p>Se llama Responsive al dise&ntilde;o web que mediante la maquetaci&oacute;n HTML y CSS3 permite que el contenido de la p&aacute;gina web se adapte al dispositivo teniendo en cuenta factores como el tama&ntilde;o de pantalla, orientaci&oacute;n o plataforma. De esta manera el mismo documento HTML se utiliza para ver el contenido adaptado a dispositivos tan diferentes como Tabletas, M&oacute;viles, Ordenadores de escritorio o SmartTV.</p>
<p><em>Ventajas del dise&ntilde;o web Responsive</em></p>
<ul>
<li>Menores costos, s&oacute;lo se desarrolla y mantiene un sitio web</li>
<li>Consistencia. El contenido es com&uacute;n y &uacute;nico para todos los dispositivos</li>
<li>URL/Dominio &uacute;nicos, no son necesarios redireccionamientos</li>
</ul>
<p><em>Desventajas</em></p>
<ul>
<li>Contenidos no optimizados totalmente. A menos que se haga un trabajo espec&iacute;fico, los contenidos no suelen estar totalmente optimizados para m&oacute;viles</li>
<li>Rendimiento m&aacute;s lento. Las versiones m&oacute;viles responsive tienen el mismo tama&ntilde;o de archivos que las de escritorio</li>
<li>Problemas de usabilidad. Los usuarios suelen tender a realizar diferentes tareas como lo har&iacute;an en sus versiones escritorio</li>
</ul>
<p><strong>Versi&oacute;n para m&oacute;viles del Sitio Web</strong></p>
<p>Son versiones de la p&aacute;gina web, generalmente colocadas en un subdominio o redirecci&oacute;n a las que se accede cuando el&nbsp; usuario utiliza el dispositivo m&oacute;vil para visitar una web.</p>
<p><em>Ventajas de una versi&oacute;n separada para m&oacute;vil de un sitioweb</em></p>
<ul>
<li>Contenidos a medida. Se puede ofrecer contenido espec&iacute;fico para cada dispositivo.</li>
<li>Velocidad. Permite optimizar y racionalizar el sitio para los usuarios m&oacute;viles</li>
<li>R&aacute;pido desarrollo. Al existir una versi&oacute;n escritorio, el desarrollo de la versi&oacute;n m&oacute;vil generalmente es muy r&aacute;pido</li>
</ul>
<p><em>Desventajas</em></p>
<ul>
<li>SEO. Al tener m&uacute;ltiples dominios o URL puede generar problemas o dificultades en el trabajo del SEO</li>
<li>Trabajo duplicado. Al tener que mantener dos sitios diferenciados.</li>
</ul>
<p><strong>Aplicaci&oacute;n M&oacute;vil</strong></p>
<p>Las aplicaciones m&oacute;viles se instalan en los dispositivos m&oacute;viles y permiten acceder a todas las funcionalidades del dispositivo.</p>
<p><em>Ventajas de las aplicaciones m&oacute;viles</em></p>
<ul>
<li>Rapidez. Se cargan en segundos y son m&aacute;s r&aacute;pidas que las WebApps o los sitios web dedicados.</li>
<li>Disponibilidad off-line. No requieren estar conectado para acceder a su contenido</li>
<li>Caracter&iacute;sticas m&oacute;viles nativas. Las Mobile Apps permiten acceder a las funcionalidades del dispositivo m&oacute;vil como GPS o la c&aacute;mara de fotos</li>
</ul>
<p><em>Desventajas</em></p>
<ul>
<li>Descarga requerida. La descarga de las aplicaciones es necesaria</li>
<li>Mantenimiento. Requieren un mantenimiento para adaptarse a los cambios del sistema operativo</li>
<li>Versi&oacute;n para cada plataforma. Es necesario realizar un desarrollo para cada plataforma m&oacute;vil: iPhone, iPad, Android&hellip;</li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=152</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/responsive-design-version-movil-de-tu-web-o-aplicacion-movil-como-elegir.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Distribución de Apps avanzada en Apple Store: compra masiva y distribución limitada</title>
			<link>http://www.imaginanet.com/blog/distribucion-de-apps-avanzada-en-app-store-compra-masiva-y-distribucion-limitada.html</link>
			<guid>http://www.imaginanet.com/blog/distribucion-de-apps-avanzada-en-app-store-compra-masiva-y-distribucion-limitada.html</guid>
			<comments>http://www.imaginanet.com/blog/distribucion-de-apps-avanzada-en-app-store-compra-masiva-y-distribucion-limitada.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue, 14 May 2013 09:42:09 +0100</pubDate>
					<category><![CDATA[iOS]]></category>
					<category><![CDATA[Apps]]></category>
					<description><![CDATA[Adem&aacute;s de la distribuci&oacute;n cl&aacute;sica en el Apple Store de una app, tenemos la posibilidad para empresas de que:

Tener un canal propio con apps sugeridas
Realizar compras masivas para obtener descuentos
Limitar la distribuci&oacute;n de una determinada app de manera privada y limitada 

Estas funcionalidades se...]]></description>
			<content:encoded><![CDATA[><p dir="ltr">Adem&aacute;s de la distribuci&oacute;n cl&aacute;sica en el Apple Store de una app, tenemos la posibilidad para empresas de que:</p>
<ul>
<li dir="ltr">Tener un canal propio con apps sugeridas</li>
<li dir="ltr">Realizar compras masivas para obtener descuentos</li>
<li dir="ltr">Limitar la distribuci&oacute;n de una determinada app de manera privada y limitada </li>
</ul>
<p dir="ltr">Estas funcionalidades se pueden realizar desde Apple Store Volume Purchasing for Business <a href="http://www.apple.com/business/vpp/" target="_blank">http://www.apple.com/business/vpp/</a> donde deberemos asignarle a un Apple ID dicha funcionalidad teniendo disponibles algunas de las funcionalidades de un MDM (<em>Mobile Device Management</em> <a href="http://es.wikipedia.org/wiki/Mobile_device_management" target="_blank">http://es.wikipedia.org/wiki/Mobile_device_management</a>)</p>
<p dir="ltr">&nbsp;</p>
<h3>Canal propio con apps sugeridas</h3>
<p dir="ltr">En este lugar asignaremos las apps que sean sugeridas para el uso dentro de un entorno corporativo, hayan sido comprada su licencia en un gran volumen o sean de distribuci&oacute;n privada, para que dentro del Apple Store podamos descargarlas f&aacute;cilmente.</p>
<br />
<h3>Compras masivas de apps para obtener descuentos</h3>
<p dir="ltr">Si nuestra intenci&oacute;n es realizar una compra masiva de licencias de la misma app, los usuarios de nuestra empresa podr&aacute;n beneficiarse del descuento a trav&eacute;s de una serie de c&oacute;digos (<em>redemption codes</em>) que se distribuir&aacute;n por email o a trav&eacute;s de una Intranet corporativa.</p>
<br />
<h3>Distribuci&oacute;n privada de apps iOS</h3>
<p dir="ltr">Esta modalidad merece menci&oacute;n aparte ya que si una <a href="http://www.imaginanet.com/apps-iphone-ipad.html">empresa de programaci&oacute;n de apps</a> nos desarrolla una aplicaci&oacute;n que no debe ser p&uacute;blica, si no de uso interno B2B, tendremos varios m&eacute;todos para hacerlo:</p>
<ul>
<li>Ad Hoc: s&oacute;lo para test, certificado v&aacute;lido durante un a&ntilde;o</li>
<li>Enterprise program: las actualizaciones no son autom&aacute;ticas, si no que se distribuye a trav&eacute;s de un fichero descargable</li>
<li>Volume Purchasing for Business: la app se publicar&aacute; a trav&eacute;s de iTunes con normalidad, pero restringiendo su uso a una determinada cuenta que est&eacute; dentro de este programa.</li>
</ul>
<p dir="ltr">Esta modalidad nos permite que determinadas apps sean de uso interno para empresas, eventos o para un testing distribuido entre m&uacute;ltiples usuarios.</p>
<p><strong id="docs-internal-guid-39d3f9b8-a1f6-6dc8-4cb3-90b1ee914d3a">Entrada relacionadas:</strong></p>
<p><a href="http://www.imaginanet.com/blog/como-subir-apps-a-apple-store.html">Como subir un app al Apple Store</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=151</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/distribucion-de-apps-avanzada-en-app-store-compra-masiva-y-distribucion-limitada.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Open Data, o los 'datos sociales'</title>
			<link>http://www.imaginanet.com/blog/open-data-o-los-datos-sociales.html</link>
			<guid>http://www.imaginanet.com/blog/open-data-o-los-datos-sociales.html</guid>
			<comments>http://www.imaginanet.com/blog/open-data-o-los-datos-sociales.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Fri, 10 May 2013 10:13:59 +0100</pubDate>
					<category><![CDATA[Open Data]]></category>
					<category><![CDATA[Internet]]></category>
					<description><![CDATA[Open Data, o lo que es lo mismo Datos Abiertos, es una filosof&iacute;a cuyo objetivo es poner a disposici&oacute;n de la sociedad los datos que gestiona la administraci&oacute;n p&uacute;blica. Estos datos deben ofrecerse en formatos de f&aacute;cil manipulaci&oacute;n por parte de los usuarios. Est&aacute; basado en la...]]></description>
			<content:encoded><![CDATA[><p><strong>Open Data</strong>, o lo que es lo mismo Datos Abiertos, es una filosof&iacute;a cuyo objetivo es poner a disposici&oacute;n de la sociedad los datos que gestiona la administraci&oacute;n p&uacute;blica. Estos datos deben ofrecerse en formatos de f&aacute;cil manipulaci&oacute;n por parte de los usuarios. Est&aacute; basado en la reutilizaci&oacute;n de los datos, generando servicios y riqueza para toda la sociedad ya que las empresas y ciudadanos pueden analizar, gestionar y redistribuir estos datos. Adem&aacute;s, la adminstraci&oacute;n p&uacute;blica progresa en transparencia "gobierno abierto" y gestiona inteligentemente los recursos "gobierno inteligente".</p>
<p>Uno de los objetivos por tanto es que los ciudadanos y las empresas reaprovechen los datos para generar riqueza econ&oacute;mica que aporte beneficios a la socidad generando nuevos servicios. A las personas o empresas que lo hacen se les llama infomediarios o reutilizadores.</p>
<p>Un t&eacute;rmino similar al Open Data es <strong>RISP</strong> (Reutilizaci&oacute;n de la Informaci&oacute;n del Sector P&uacute;blico). La diferencia estriba en que mientras los datos ofrecidos mediante Open Data deben ser siempre gratuitos y en formatos f&aacute;cilmente manipulables, RISP contempla la posibilidad del pago por el uso de los datos y su publicaci&oacute;n admite cualquier formato.</p>
<p>Open Data implica una serie de principios de obligado cumplimiento, en otro caso no estar&iacute;amos hablando de Open Data:</p>
<ul>
<li>La &uacute;nica restricci&oacute;n para su publicaci&oacute;n deben ser los datos sujetos a restricciones de privacidad, seguridad o derechos de autor. No deben existir otras trabas por parte de la administraci&oacute;n p&uacute;blica para su publicaci&oacute;n</li>
<li>No se deben procesar los datos, hay que publicarlos como datos en bruto, tal y como est&aacute;n en origen.</li>
<li>Deben ser fieles a la actualidad y por lo tanto se deben ofrecer con la obligada frecuencia para que no pierdan valor.</li>
<li>No deber&iacute;an existir restricciones en cuanto a los usuarios que los van a recibir, ni por su prop&oacute;sito de uso.</li>
<li>La estructura de los datos debe permitir un proceso autom&aacute;tico por un ordenador.</li>
<li>La disposici&oacute;n de los datos no puede requerir un registro previo. Deben ser libres.</li>
<li>El formato de los datos puestos a disposici&oacute;n no puede depender de una entidad o herramienta propietaria de una entidad. El formato debe ser abierto como lo son CSV, XML...</li>
<li>No existir&aacute;n patentes, copyright, derechos sobre los datos, deben ser de uso 100% libre ni estar sujetos a derechos de privacidad, seguridad o privilegios.</li>
</ul>
<p><strong>Conjunto de datos o Dataset</strong>. &Eacute;ste t&eacute;rmino hace referencia a la categorizaci&oacute;n de los datos p&uacute;blicos mediante cat&aacute;logos de datos. Esto permite que se puedan indexar y localizar m&aacute;s f&aacute;cilmente.</p>
<p>Los <strong>principales formatos para los datos p&uacute;blicos</strong> son:</p>
<ul>
<li><strong>CSV</strong>, Valores separados por comas, es un documento de texto plano que presenta datos tabulados. Una hoja de c&aacute;lculo Excel es f&aacute;cilmente exportable a este formato.</li>
<li><strong>XML</strong>, Lenguaje etiquetado extensible, metalenguaje que permite la interpretaci&oacute;n de datos para otros lenguajes m&aacute;s complejos. Las bases de datos suelen permitr su exportaci&oacute;n a XML.</li>
<li><strong>RDF</strong>, Infraestructura para descripci&oacute;n de recursos, est&aacute; basado en XML y permite intercambiar y enlazar a trav&eacute;s de aplicaciones, datos y recursos. Facilita su reutilizaci&oacute;n y enriquecimiento.</li>
<li><strong>RSS</strong>, Sindicaci&oacute;n realmente sencilla, tambi&eacute;n basado en XML, se utiliza para la ordenaci&oacute;n de contenidos de sitios web que tienen una actualizaci&oacute;n frecuente.</li>
<li><strong>ODATA</strong>, Open data Protocol, protocolo abierto, permite consultar y seleccionar directamente sobre los datos y descargar el resultado.</li>
</ul>
<p>La sociedad en su conjunto se beneficia de la reutilizaci&oacute;n de los datos que el sector p&uacute;blico dispone. As&iacute;, la Ley 37/2007 dice "la informaci&oacute;n generada desde las instancias p&uacute;blicas, con la potencialidad que le otorga el desarrollo de la sociedad de la informaci&oacute;n, tiene un gran inter&eacute;s para las empresas a la hora de operar en sus &aacute;mbitos de actuaci&oacute;n, contribuir al crecimiento econ&oacute;mico y a la creaci&oacute;n de empleo, y para los ciudadanos como elemento de transparencia y gu&iacute;a para la participaci&oacute;n democr&aacute;tica".</p>
<p><span>El desarrollo del Open Data ofrece como <strong>principales beneficios</strong> los siguientes:</span></p>
<p><span><strong>Para el ciudadano</strong>: la utilizaci&oacute;n de los datos p&uacute;blicos puede dar lugar a nuevas aplicaciones y servicios que mejoren la vida de los ciudadanos, adem&aacute;s de la generaci&oacute;n de nuevos puestos de trabajo. Se mejora en gran medida la transparencia de la administraci&oacute;n p&uacute;blica con lo que se est&aacute; m&aacute;s cerca de conseguir el objetivo de gobierno abierto e inteligente que est&aacute; en permanente comunicaci&oacute;n con el ciudadano y facilita su participaci&oacute;n.</span></p>
<p><span><strong>Para las empresas</strong>: Pueden generar valor econ&oacute;mico derivado de la utilizaci&oacute;n de los datos p&uacute;blicos puestos a su disposici&oacute;n. Tambi&eacute;n se fomenta la competitividad entre empresas al ofrecer la posibilidad de traducir en beneficio econ&oacute;mico esa informaci&oacute;n.</span></p>
<p><span><strong>Para la administraci&oacute;n p&uacute;blica</strong>: Dinamiza la econom&iacute;a al permitir a las empresas infomediarias el desarrollo de aplicaciones que de otra manera ser&iacute;an bastante costosas. Tambi&eacute;n la colaboraci&oacute;n de los ciudadanos mediante la creaci&oacute;n de nuevas iniciativas y aplicaciones derivadas del uso de estos datos supone un beneficio para la administraci&oacute;n. Otro aspecto positivo es el intercambio de datos entre las administraciones local, auton&oacute;mica y central.</span></p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=150</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/open-data-o-los-datos-sociales.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Proteger nuestras páginas con htpasswd</title>
			<link>http://www.imaginanet.com/blog/proteger-nuestras-paginas-con-htpasswd.html</link>
			<guid>http://www.imaginanet.com/blog/proteger-nuestras-paginas-con-htpasswd.html</guid>
			<comments>http://www.imaginanet.com/blog/proteger-nuestras-paginas-con-htpasswd.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue,  7 May 2013 10:20:54 +0100</pubDate>
					<category><![CDATA[Internet]]></category>
					<description><![CDATA[Hay ocasiones en las que queremos que ninguna persona o robot (google...) acceda a una p&aacute;gina, dominio o subdominio. Donde el motivo m&aacute;s com&uacute;n suele ser porque se trata de una p&aacute;gina o sitio de desarrollo y no nos interesa que se indexe el contenido, o que personas ajenas al equipo de desarrollo...]]></description>
			<content:encoded><![CDATA[><p>Hay ocasiones en las que queremos que ninguna persona o robot (google...) acceda a una p&aacute;gina, dominio o subdominio. Donde el motivo m&aacute;s com&uacute;n suele ser porque se trata de una p&aacute;gina o sitio de desarrollo y no nos interesa que se indexe el contenido, o que personas ajenas al equipo de desarrollo accedan.</p>
<p>Para llevar a cabo este cometido, vamos a configurar el servidor de Apache mediante el htaccess de nuestro sitio principal. La idea es denegar todas las peticiones al sitio que queremos mantener en privado y permitir el acceso a este mediante autorizaci&oacute;n. Vamos a ver un ejemplo donde tenemos el subdominio desarrollo del dominio imaginanet.com</p>
<pre class="code">SetEnvIfNoCase Host ^(www.)imaginanet.com$ imaginanet
SetEnvIfNoCase Host ^(desarrollo.)imaginanet.com$ desarrollo

AuthType basic
AuthName "Desarrollo"
AuthUserFile /home/imaginanet/.htpasswd

Order deny,allow
Deny from all
Allow from env=imaginanet
Require valid-user
Satisfy any</pre>
<p>En las primeras l&iacute;neas estamos inicializando variables de entorno para poder realizar las reglas. En este caso la regla imaginanet para nuestro dominio principal y la regla desarrollo para el subdominio de desarrollo.</p>
<p>Lo siguiente es solicitar autorizaci&oacute;n b&aacute;sica pidiendo el usuario y contrase&ntilde;a que tenemos almacenados en el archivo .htpasswd. Este archivo conviene almacenarlo fuera de la carpeta p&uacute;blica, y se debe poner la ruta absoluta. El contenido del archivo tiene que ser un usuario y contrase&ntilde;a, o m&aacute;s. Y la contrase&ntilde;a debe ir encriptada. Podemos encontrar conversores online para hacerlo, o si disponemos de acceso ssh al servidor entonces podemos ejecutar el siguiente comando:</p>
<pre class="code">htpasswd -nb usuario contrase&ntilde;a</pre>
<p>Este comando nos devuelve lo que debemos incluir en el fichero .htpasswd</p>
<p>Finalmente denegamos todas las peticiones y requerimos validaci&oacute;n, con la excepci&oacute;n de imaginanet que permitimos su acceso sin autorizaci&oacute;n.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=149</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/proteger-nuestras-paginas-con-htpasswd.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Preferencias en la paginación de las páginas web y el botón Ver todos</title>
			<link>http://www.imaginanet.com/blog/preferencias-en-la-paginacion-de-las-paginas-web-y-el-boton-ver-todos.html</link>
			<guid>http://www.imaginanet.com/blog/preferencias-en-la-paginacion-de-las-paginas-web-y-el-boton-ver-todos.html</guid>
			<comments>http://www.imaginanet.com/blog/preferencias-en-la-paginacion-de-las-paginas-web-y-el-boton-ver-todos.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue, 30 Apr 2013 13:43:27 +0100</pubDate>
					<category><![CDATA[Internet]]></category>
					<category><![CDATA[Accesibilidad]]></category>
					<category><![CDATA[Web 2.0]]></category>
					<description><![CDATA[Cuando una p&aacute;gina web contiene un listado con un n&uacute;mero grande de elementos que mostrar es necesario establecer una paginaci&oacute;n que ayude a la correcta visualizaci&oacute;n y accesibilidad de dichos elementos. Por otra parte, hay p&aacute;ginas que aunque ocupen gran espacio en sentido vertical, no pueden...]]></description>
			<content:encoded><![CDATA[><p>Cuando una p&aacute;gina web contiene un listado con un n&uacute;mero grande de elementos que mostrar es necesario establecer una <strong>paginaci&oacute;n</strong> que ayude a la correcta visualizaci&oacute;n y <strong>accesibilidad</strong> de dichos elementos. Por otra parte, hay p&aacute;ginas que aunque ocupen gran espacio en sentido vertical, no pueden dividirse en varias p&aacute;ginas al ser <strong>art&iacute;culos de informaci&oacute;n</strong> o consulta.</p>
<p>La <strong>paginaci&oacute;n</strong> es un mal necesario y a la vez muy &uacute;til en p&aacute;ginas donde se muestran productos o art&iacute;culos para el <strong>comercio electr&oacute;nico</strong> y tambi&eacute;n para las p&aacute;ginas de resultados de una b&uacute;squeda. El objetivo de estas p&aacute;ginas para el usuario es encontrar un art&iacute;culo espec&iacute;fico, no leer la lista completa. Por ello se suele priorizar los elementos de la lista colocando los m&aacute;s vistos o interesantes en la parte superior. A partir de aqu&iacute; se suele establecer la paginaci&oacute;n para no tener listados demasiado largos.</p>
<p>Un factor a tener muy en cuenta es el bot&oacute;n <em>Ver todos</em>. En diversas pruebas se ha observado que el poner a disposici&oacute;n de los usuarios este bot&oacute;n permite a muchos ver el listado completo sin la a veces engorrosa tarea de ir hacia adelante y hacia atr&aacute;s en las p&aacute;ginas. Est&aacute; demostrado que la disponibilidad de este bot&oacute;n como una opci&oacute;n m&aacute;s del listado no molesta en la <strong>experiencia del usuario </strong>(<strong>usabilidad</strong>), y sin embargo si no se ofrece esta opci&oacute;n, hay usuarios que la echar&aacute;n en falta.</p>
<p>Adem&aacute;s el bot&oacute;n <em>Ver todos</em> es muy &uacute;til para listados dif&iacute;cilmente clasificables en cuanto al rango de importancia de sus art&iacute;culos, ya que listados paginados tienden a ocultar verdaderas joyas en las &uacute;ltimas p&aacute;ginas.</p>
<p>Por otra parte hay que tener en cuenta que a pesar de este bot&oacute;n conviene no ir a listados de m&aacute;s de 100 art&iacute;culos, tanto por la cacpacidad de retener del propio usuario como del tiempo de carga de la p&aacute;gina.</p>
<p>Existe tambi&eacute;n la opci&oacute;n de ofrecer al usuario la cantidad de art&iacute;culos que desea ver por listado (acotado entre varias posibilidades), aspecto que ofrece una mayor sensaci&oacute;n de control de lo que est&aacute; viendo al propio usuario, aunque suele ser mejor ofrecer algo m&aacute;s acotado complementado con el bot&oacute;n <em>Ver todos</em>.</p>
<p>En estos casos en que se permite una cierta personalizaci&oacute;n, ser&iacute;a importante que el propio sitio web fuera capaz de "recordar" la elecci&oacute;n del usuario para que la siguiente vez que nos visite no tenga que volver a elegir.</p>
<p>Finalmente, las investigaciones sobre este particular han demostrado lo siguiente:</p>
<p>- La mayor parte de los usuarios <strong>no desean personalizar</strong> y prefieren utilizar la configuraci&oacute;n determinada por el sitio web.<br />- Abrir las opciones de personalizaci&oacute;n pueden f&aacute;cilmente generar <strong>problemas de usabilidad</strong>.</p>
<p><br /><em>Fuente:&nbsp;<a href="http://www.nngroup.com/articles/item-list-view-all/" target="_blank">http://www.nngroup.com/articles/item-list-view-all/</a></em></p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=148</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/preferencias-en-la-paginacion-de-las-paginas-web-y-el-boton-ver-todos.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Solicitud de reconsideración a Google. Consejos previos</title>
			<link>http://www.imaginanet.com/blog/solicitud-de-reconsideracion-a-google-consejos-previos.html</link>
			<guid>http://www.imaginanet.com/blog/solicitud-de-reconsideracion-a-google-consejos-previos.html</guid>
			<comments>http://www.imaginanet.com/blog/solicitud-de-reconsideracion-a-google-consejos-previos.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue, 30 Apr 2013 12:17:16 +0100</pubDate>
					<category><![CDATA[Google]]></category>
					<category><![CDATA[SEO]]></category>
					<category><![CDATA[Buscadores]]></category>
					<description><![CDATA[Si has recibido una notificaci&oacute;n de penalizaci&oacute;n en los ranking por parte del equipo de Google conviene hacer una solicitud para que reconsideren su decisi&oacute;n. Lo ponen dif&iacute;cil ya que no incluyen en su notificaci&oacute;n los puntos concretos por los que te penalizan. Hay que revisar el sitio completo...]]></description>
			<content:encoded><![CDATA[><p>Si has recibido una notificaci&oacute;n de penalizaci&oacute;n en los ranking por parte del equipo de Google conviene hacer una solicitud para que reconsideren su decisi&oacute;n. Lo ponen dif&iacute;cil ya que no incluyen en su notificaci&oacute;n los puntos concretos por los que te penalizan. Hay que revisar el sitio completo siguiendo, eso s&iacute;, unos consejos b&aacute;sicos para adecuar la p&aacute;gina a sus requisitos antes de enviar dicha notificaci&oacute;n.</p>
<p><strong>Search Engine Watch</strong> (SEW) ha puesto a disposici&oacute;n de las empresas una <strong><a href="http://searchenginewatch.com/article/2262933/Google-Reconsideration-Request-Guidelines-Example" target="_blank">peque&ntilde;a gu&iacute;a y ejemplos</a></strong> para proceder a la "limpieza" de su sitio web.</p>
<ul>
<li>En primer lugar, <strong>limpia tu sitio web de enlaces no naturales</strong>, virus, spam y elementos dudosos.</li>
<li>Notifica a Google que dispones de un <strong><a href="http://googlewebmastercentral.blogspot.com.es/2012/10/a-new-tool-to-disavow-links.html" target="_blank">disavow.txt</a></strong>.</li>
<li>S&eacute; sincero, <strong>indica a Google que has utilizado una empresa de SEO</strong>&nbsp;externa para el posicionamiento de tu web y que &eacute;sta ha utilizado Spam, enlaces no naturales y dem&aacute;s. No trates de quitarte culpas por ello, t&uacute; eres el responsable, pero cu&eacute;ntaselo a Google.</li>
<li><strong>Sigue sus recomendaciones</strong> para realizar la reconsideraci&oacute;n, mira este video donde lo explica:</li>
</ul>
<iframe src="http://www.youtube.com/embed/8MfPe1NbsoA" width="560" height="315"></iframe><br /> 
<ul>
<li><strong>No te enfades demasiado</strong>, aunque creas que Google tiene la culpa en parte, s&eacute; cordial y respetuoso, las formas tambi&eacute;n importan.</li>
<li><strong>Promete que ser&aacute;s bueno a partir de ahora</strong> y que no volver&aacute;s a realizar "actos impuros".</li>
</ul>
<p>Despu&eacute;s de todo esto, supongo que querr&aacute;s saber <strong>cu&aacute;nto tiempo tarda Google en responder a tu solicitud de reconsideraci&oacute;n</strong>. Aqu&iacute; tienes &nbsp;otro video donde lo explica:</p>
<iframe src="http://www.youtube.com/embed/5rsWc78dits" width="560" height="315"></iframe>
<p><br /><strong>Por &uacute;ltimo</strong>, este es un buen ejemplo de una carta de reconsideraci&oacute;n, ejemplo ofrecido por el equipo de Google:</p>
<p style="padding-left: 30px;">Dear Google Webspam team member,</p>
<p style="padding-left: 30px;">Thank you for taking the time to read our request. Our site was recently given a penalty for unnatural links. In reviewing our links, we now see that we have tried to manipulate the search results by using links containing anchor text from syndicated articles. We also purchased links from [company name]. Although these actions were taken by our SEO Company, [insert name], we take full responsibility for their work. We no longer employ this company.</p>
<p style="padding-left: 30px;">We have worked hard over the last few months to remove as many of these links as possible. We have contacted webmasters using their email address available on the site, their whois address and also via contact forms where available. This spreadsheet shows all of our links and what efforts we have taken for removal:</p>
<p style="padding-left: 30px;">[link to Google Spreadsheet. IMPORTANT - Make sure you change the privacy settings on the Google Doc so that anyone with the link can see it]</p>
<p style="padding-left: 30px;">This document shows the original source code of each of the emails that we have sent to webmasters:</p>
<p style="padding-left: 30px;">[insert link to Google Doc]</p>
<p style="padding-left: 30px;">And this document shows screenshots of contact forms that we have filled out.</p>
<p style="padding-left: 30px;">[insert link to Google Doc]</p>
<p style="padding-left: 30px;">We have submitted a disavow.txt file to ask Google to disavow the unnatural links that we were unable to remove.</p>
<p style="padding-left: 30px;">Thank you again for reading this request. We have worked hard to resolve the quality issues on our site and are completely committed to following the Quality Guidelines from this point on.</p>
<p style="padding-left: 30px;">Sincerely,<br />[your name]</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=147</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/solicitud-de-reconsideracion-a-google-consejos-previos.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Funcionamiento de Google, cómo valora las páginas y cual es la variación de la colocación de éstas a lo largo del tiempo.</title>
			<link>http://www.imaginanet.com/blog/funcionamiento-de-google-como-valora-las-paginas-y-cual-es-la-variacion-de-la-colocacion-de-estas-a-lo-largo-del-tiempo.html</link>
			<guid>http://www.imaginanet.com/blog/funcionamiento-de-google-como-valora-las-paginas-y-cual-es-la-variacion-de-la-colocacion-de-estas-a-lo-largo-del-tiempo.html</guid>
			<comments>http://www.imaginanet.com/blog/funcionamiento-de-google-como-valora-las-paginas-y-cual-es-la-variacion-de-la-colocacion-de-estas-a-lo-largo-del-tiempo.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 15 Apr 2013 16:28:46 +0100</pubDate>
					<category><![CDATA[Google]]></category>
					<category><![CDATA[SEO]]></category>
					<category><![CDATA[Buscadores]]></category>
					<description><![CDATA[Google a trav&eacute;s de un nuevo video de Matt Cuts trata de explicar de manera sencilla algo tan complejo como el funcionamiento de un buscador.
La informaci&oacute;n y los datos son b&aacute;sicos para saber cual de los resultados obtenidos en una b&uacute;squeda es el mejor, y esto es lo que determina que una nueva...]]></description>
			<content:encoded><![CDATA[><p>Google a trav&eacute;s de un nuevo video de Matt Cuts trata de explicar de manera sencilla algo tan complejo como el funcionamiento de un buscador.</p>
<p>La informaci&oacute;n y los datos son b&aacute;sicos para saber cual de los resultados obtenidos en una b&uacute;squeda es el mejor, y esto es lo que determina que una nueva informaci&oacute;n vaya variando su posici&oacute;n en funci&oacute;n de que Google vaya recompilando m&aacute;s datos para saber cu&aacute;l de los resultados es m&aacute;s completo, de calidad y original. A partir de aqu&iacute; y una vez que han pasado unos d&iacute;as y Google lo va teniendo m&aacute;s claro los rankings se estabilizan.</p>
<p>Esta es la explicaci&oacute;n de que los rankings vayan cambiando con el tiempo, de ah&iacute; la importancia de un trabajo constante sobre los contenidos m&aacute;s relevantes de tu p&aacute;gina web e ir ofreciendo a Google contenido interesante y original que indexar.</p>
<p>&nbsp;</p>
<iframe src="http://www.youtube.com/embed/BzfK6isC7CA" width="560" height="315"></iframe>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=146</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/funcionamiento-de-google-como-valora-las-paginas-y-cual-es-la-variacion-de-la-colocacion-de-estas-a-lo-largo-del-tiempo.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Guía básica para la optimización de tu web dirigida a Google</title>
			<link>http://www.imaginanet.com/blog/guia-basica-para-la-optimizacion-de-tu-web-dirigida-a-google.html</link>
			<guid>http://www.imaginanet.com/blog/guia-basica-para-la-optimizacion-de-tu-web-dirigida-a-google.html</guid>
			<comments>http://www.imaginanet.com/blog/guia-basica-para-la-optimizacion-de-tu-web-dirigida-a-google.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed, 20 Mar 2013 17:37:14 +0100</pubDate>
					<category><![CDATA[Google]]></category>
					<category><![CDATA[SEO]]></category>
					<category><![CDATA[Buscadores]]></category>
					<description><![CDATA[Desde Google nos invitan a difundir una gu&iacute;a b&aacute;sica para principiantes en esto del posicionamiento (SEO) de una p&aacute;gina web, blog, wordpress...
Se compone de una sencilla infograf&iacute;a que anima a realizar las tareas de creaci&oacute;n de la p&aacute;gina web teniendo en cuenta tres premisas...]]></description>
			<content:encoded><![CDATA[><p>Desde Google nos invitan a difundir una <strong><a href="https://storage.googleapis.com/support-kms-prod/SNP_3027140_en_v0?utm_source=EN_IntBlog&amp;utm_medium=bp&amp;utm_campaign=q113os" target="_blank">gu&iacute;a b&aacute;sica para principiantes</a></strong> en esto del posicionamiento (SEO) de una p&aacute;gina web, blog, wordpress...</p>
<p>Se compone de una sencilla infograf&iacute;a que anima a realizar las tareas de creaci&oacute;n de la p&aacute;gina web teniendo en cuenta tres premisas b&aacute;sicas:</p>
<p><br /><strong>1- Describe de manera concisa, clara e informativa tu p&aacute;gina</strong> dentro del t&iacute;tulo de la p&aacute;gina. Aseg&uacute;rate de que tanto las URL del dominio como de las subsecciones se pueden leer correctamente y son informativas. Y adem&aacute;s escribe descripciones &uacute;nicas para cada p&aacute;gina del sitioweb, como mucho en 160 caracteres.</p>
<p><strong>2- Ayuda a Google a entender tus im&aacute;genes</strong>. D&oacute;talas de un texto alt descriptivo, haz que el nombre de archivo sea corto pero tambi&eacute;n descriptivo, y por &uacute;ltimo pon un pie de foto que tambi&eacute;n la defina.</p>
<p><strong>3- Mant&eacute;n tu sitioweb vivo</strong>, es tu escaparate informativo, aporta informaci&oacute;n peri&oacute;dicamente, ponte en el lugar de tu visitante que tiene inter&eacute;s por conocer tus &uacute;ltimas novedades.</p>
<p>&nbsp;</p>
<p>Si despu&eacute;s de realizar todo esto te ha picado el gusanillo del posicionamiento en Google, entonces est&aacute;s preparado para la <strong><a href="http://static.googleusercontent.com/external_content/untrusted_dlcp/www.google.com/es//webmasters/docs/search-engine-optimization-starter-guide.pdf" target="_blank">Gu&iacute;a de Google SEO Starter</a></strong>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=145</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/guia-basica-para-la-optimizacion-de-tu-web-dirigida-a-google.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Como subir apps a Apple Store</title>
			<link>http://www.imaginanet.com/blog/como-subir-apps-a-apple-store.html</link>
			<guid>http://www.imaginanet.com/blog/como-subir-apps-a-apple-store.html</guid>
			<comments>http://www.imaginanet.com/blog/como-subir-apps-a-apple-store.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed, 13 Mar 2013 09:14:22 +0100</pubDate>
					<category><![CDATA[Apps]]></category>
					<category><![CDATA[iOS]]></category>
					<description><![CDATA[El App Store se perfila junto al de Google Play como los dos m&aacute;s importantes mercados actuales de software. Pr&aacute;cticamente se podr&iacute;a decir que si no est&aacute; en el AppStore o no es accesible como una WebApp, no es un software que llegue al gran p&uacute;blico.
La publicaci&oacute;n en el AppStore puede ser...]]></description>
			<content:encoded><![CDATA[><p>El App Store se perfila junto al de Google Play como los dos m&aacute;s importantes mercados actuales de software. Pr&aacute;cticamente se podr&iacute;a decir que si no est&aacute; en el AppStore o no es accesible como una WebApp, no es un software que llegue al gran p&uacute;blico.</p>
<p>La publicaci&oacute;n en el AppStore puede ser un tanto complicada, ya que implica varios pasos por parte del desarrollador. A continuaci&oacute;n explicamos una perspectiva general de todo el proceso.</p>
<h3>Registrarse como Apple Developer</h3>
<p>El primer paso es registrarse como desarrollador de Apple desde <a href="http://developer.apple.com/devcenter/ios/index.action" target="_blank">http://developer.apple.com/devcenter/ios/index.action</a> pudiendo enlazar nuestro Apple ID existente a una cuenta de desarrollador o crear una nueva.</p>
<p>Una vez rellenados nuestros datos y verificada la cuenta, deberemos entrar dentro de ella.</p>
<h3>Entrando en el programa iOS Developer Program</h3>
<p>Cuando estemos dentro de nuestra cuenta de Apple Developer, entraremos en nuestra cuenta y veremos en el panel de control la opci&oacute;n <strong><em>Join the Developer Program</em></strong> que nos dar&aacute; acceso a programar apps para iOS (hay que prestar atenci&oacute;n a &eacute;sto ya que cada tipo de app/aplicaci&oacute;n Apple es diferente y no es el mismo este programa que el de aplicaciones de MacOS X)</p>
<p>Durante este proceso deberemos prestar atenci&oacute;n a varios puntos:</p>
<ul>
<li>En el resgistro, nuestro nombre, apellidos o cualquier otro dato no deber&aacute; contener tildes o si no recibiremos una llamada desde Apple diciendo que nuestra cuenta no puede ser completada hasta que los eliminemos del proceso de registro.</li>
<li>Deberemos pagar la cuota anual de desarrollador de Apple, existen varios planes seg&uacute;n si por ejemplo queremos que nuestras apps se distribuyan s&oacute;lo a trav&eacute;s del Apple Store o tambi&eacute;n queremos que puedan ser instaladas directamente en el dispositivo sin pasar por &eacute;l. En nuestro caso vamos a elegir la cuota b&aacute;sica que ronda unos 99$.</li>
<li>Deberemos aportar los datos acreditativos de empresa en el proceso o como individual, esto var&iacute;a seg&uacute;n el pa&iacute;s</li>
</ul>
<p>Tras realizar el pago, el proceso de registro quedar&aacute; en espera para que Apple valide el nuevo usuario. Esta espera puede ser de unos pocos d&iacute;as, durante los cuales Apple puede ponerse en contacto con nosotros por tel&eacute;fono para verificar o pedir aclaraciones sobre alg&uacute;n dato.</p>
<h3>Instalando Xcode: entorno de desarrollo</h3>
<p>En estos momentos de espera es un buen momento para instalar el entorno de desarrollo Xcode (tipo Eclipse, Netbeans, Visual Studio, ...) desde&nbsp;<a href="https://developer.apple.com/xcode/" target="_blank">https://developer.apple.com/xcode/</a>&nbsp;que depender&aacute; de las &uacute;ltimas versiones de MacOS X (no se hab&iacute;a dicho antes, pero s&iacute;, para programar apps de iOS necesitamos un MacOS X).</p>
<p>Es importante que mantengamos Xcode actualizado a su &uacute;ltima versi&oacute;n si queremos que nuestras aplicaciones sean v&aacute;lidas en las &uacute;ltimas versiones de iOS.</p>
<h3>iOS Provisioning portal: certificados</h3>
<p>Cuando tengamos la verificaci&oacute;n por parte de Apple, volveremos a entrar en el portal Apple Developer y veremos que nuestro usuario tiene nuevas opciones que antes no ten&iacute;a. Si exploramos un poco veremos que existen multitud de gu&iacute;as de programaci&oacute;n, descargas, documentaci&oacute;n v&iacute;deos, etc. (tanta que nos pueda hacernos sentir un poco perdidos).</p>
<p>El &aacute;rea iOS Provisioning portal nos permite correr apps en entorno de pruebas en dispositivos reales (iPhone, iPad, iPod, ...) que todav&iacute;a no han sido publicadas. Este proceso se hace a trav&eacute;s de software firmado con certificados digitales, que existen de dos tipos:</p>
<ul>
<li><strong>Development profiles:</strong> s&oacute;lo v&aacute;lidos para desarrollo</li>
<li><strong>Distribution profiles:</strong> para distribuci&oacute;n</li>
</ul>
<p>Para que podamos empezar a probar, entraremos en el enlace de iOS Provisioning portal y en su men&uacute; principal en <em>Certificates</em> donde veremos las pesta&ntilde;as de Development y Distribution. Haremos una petici&oacute;n de certificado mediante el bot&oacute;n de <em>Request Certificate.</em></p>
<p>Antes de seguir, dejaremos la p&aacute;gina web un momento y prepararemos el certificado de desarrollo/distribuci&oacute;n. En Spotlight buscaremos el programa <em>Keychain access</em> y pulsaremos sobre el men&uacute;&nbsp;<em>Keychain Access -&gt; Certificate assistant -&gt; Request a Certificate from a Certificate Authority</em> y a continuaci&oacute;n rellenaremos con nuestros datos marcando la opci&oacute;n&nbsp;<em>Saved to disk</em> que nos generar&aacute; un certificado X.509 con nuestros datos.</p>
<p>Volveremos al navegador web y subiremos el nuevo archivo generado. Nos devolver&aacute; a la p&aacute;gina principal de certificados que el estado de nuestro certificado puede estar pendiente de aprobaci&oacute;n. Esta petici&oacute;n se resuelve autom&aacute;ticamente en poco tiempo (m&aacute;ximo en algunos minutos), y cuando est&eacute; lista nos aparecer&aacute; un bot&oacute;n que nos permitir&aacute; la descarga del certificado.</p>
<p>Una vez descargado, haremos doble click sobre el archivo y se importar&aacute; a nuestro Keychain.</p>
<h3>iOS Provisioning portal: dispositivos de entorno de pruebas</h3>
<p>En el paso anterior creamos los certificados necesarios para autenticarnos como desarrollador iOS, pero tambi&eacute;n deberemos especificar los dispositivos que pueden estar en el entorno de pruebas.</p>
<p>Para a&ntilde;adir nuevos, en <em>iOS Provisioning portal -&gt; Devices -&gt; Add devices</em> desde donde tendremos que a&ntilde;adir cada UDID de cada uno de los dispositivos del entorno de pruebas. El UDID es un identificador &uacute;nico para cada dispositivo. Una manera sencilla de verlo es desde iTunes, desde la pesta&ntilde;a de dispositivo se refleja una serie de caracteres alfanum&eacute;ricos.</p>
<h3>iOS Provisioning portal: App ID y Provisioning</h3>
<p>Por cada app, deberemos crear un App ID que identificar&aacute; exclusivamente a dicha app. Para ello en&nbsp;<em>iOS Provisioning portal -&gt; Devices -&gt; App ID </em>crearemos el identificador &uacute;nico de nuestra app.</p>
<p>A continuaci&oacute;n, en Provisioning haremos click en New profile donde crearemos un perfil para nuestro App ID. Entre las opciones deberemos prestar atenci&oacute;n al Distribution Method: App Store o Ad-Hoc.</p>
<p>Nos devolver&aacute; a la pantalla principal de Provisioning y veremos un bot&oacute;n de descarga del profile, lo descargaremos e instalaremos en nuestro PC.</p>
<p>Para ver que est&aacute; correctamente instalado en nuestro ordenador, abriremos Xcode y en Organizer, veremos que en sus Provisioning profiles tenemos ya preparado el perfil para nuestra App.</p>
<h3>Programar nuestra aplicaci&oacute;n en Objective C</h3>
<p>Este paso creo que est&aacute; claro, programaremos lo que queramos mediante Xcode y probaremos lo que hagamos en el simulador.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" title="Programar apps iOS" src="http://www.imaginanet.com/ftp/blog/xcode.png" alt="Programar apps iOS" width="80" height="80" /></p>
<h3>Probar en iPhone/iPad/iPod</h3>
<p>Conectaremos el dispositivo que hemos introducido el UDID y nos aparecer&aacute; la ventana de Organizer. Si es la primera vez que lo conectamos deberemos hacer click en el bot&oacute;n <em>Use for development</em>. Podemos echarle un vistazo a los Provisioning profiles, si esos perfiles est&aacute;n asignados al dispositivo actual, si no tuviera ninguno seleccionaremos iOS Team Provisioning Profile.</p>
<p>Ahora iremos a la pantalla principal de Xcode y seleccionaremos el primer icono de proyecto (de color azul) y en el submen&uacute; en Target. A continuaci&oacute;n especificaremos seg&uacute;n la pesta&ntilde;a:</p>
<ul>
<li><strong>Summary:</strong> dispositivos, identificadores y versiones.</li>
<li><strong>Info:</strong> Bundle identifier, como parte de nuestra App ID</li>
<li><strong>Build Settings:</strong> buscaremos el Code Signing Identity, eligiendo para cada perfil el certificado de desarrollo o distribuci&oacute;n, seg&uacute;n necesitemos.</li>
</ul>
<p>Esto nos permitir&aacute; a ejecutar a trav&eacute;s de Xcode la app en nuestro dispositivo.</p>
<h3>Subiendo nuestra App a App Store con iTunes Connect</h3>
<p>Este es el portal donde se suben las apps y se especifica su informaci&oacute;n: nombre, capturas de pantalla, precio, etc. Deberemos entrar en <a href="https://itunesconnect.apple.com/" target="_blank">https://itunesconnect.apple.com/</a> y con nuestras credenciales de desarrollador iOS. En este punto deberemos tener bien preparado lo siguiente:</p>
<ul>
<li>Nombre</li>
<li>Descripci&oacute;n</li>
<li>Icono 512x512px</li>
<li>Capturas de pantalla: al menos una para iPhone y otra para iPad en los siguientes formatos 320x460 (sin barra de estado); 320x480; 640x920 (retina, sin barra de estado); 640x960 (retina); para orientaci&oacute;n paisaje 480x300 (sin barra de estado); 480x320; 960x600 (retina, sin barra de estado); o 960&times;640 (retina).</li>
</ul>
<p>Antes de mandar la app, deberemos tener claro cuales son los App Review Guidelines, sobre el buen uso de las apps que van a ser publicadas en cuanto a funcionamiento y contenido. Es importante que revisemos la gu&iacute;a&nbsp;<a href="https://developer.apple.com/appstore/guidelines.html" target="_blank">https://developer.apple.com/appstore/guidelines.html</a> y estemos seguros para que la app no sea rechazada.</p>
<p>Dentro de iTunes Connect darle a <em>Manage your applications</em> y <em>Add new app</em> donde rellenaremos los datos de app, entre ellos seleccionaremos el App ID creado para el app.</p>
<p>Tras rellenar todos los datos, haremos click en <em>Ready to Upload Binary.</em></p>
<p>La subida de los archivos binarios se har&aacute; a trav&eacute;s de Xcode, como <em>Scheme</em> elegiremos <em>iOS Device</em> y despues <em>Product Archive</em>. Se abrir&aacute; una ventana de Organizer donde haremos click en<em> Submit</em> y tras subir la app, volveremos a iTunes connect viendo que la app ya est&aacute; recibida y pendiente de revisi&oacute;n.</p>
<p>&nbsp;</p>
<p><strong>Entradas relacionadas</strong></p>
<p><a href="http://www.imaginanet.com/blog/distribucion-de-apps-avanzada-en-app-store-compra-masiva-y-distribucion-limitada.html"><span>Distribuci&oacute;n de Apps avanzada en Apple Store: compra masiva y distribuci&oacute;n limitada</span><br /></a></p>
<p><br /><br /></p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=144</wfw:commentRss>
			<slash:comments>4</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/como-subir-apps-a-apple-store.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Como subir apps a Windows Store</title>
			<link>http://www.imaginanet.com/blog/como-subir-apps-a-windows-store.html</link>
			<guid>http://www.imaginanet.com/blog/como-subir-apps-a-windows-store.html</guid>
			<comments>http://www.imaginanet.com/blog/como-subir-apps-a-windows-store.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue, 12 Mar 2013 13:57:31 +0100</pubDate>
					<category><![CDATA[Apps]]></category>
					<category><![CDATA[Windows 8]]></category>
					<description><![CDATA[La plataforma Windows Store nos permite descargarnos aplicaciones para la plataforma de Windows 8, Windows Phone y Windows RT, pero para que sean accesibles deben cumplir una serie de est&aacute;ndar y ser aprobada.
A continuaci&oacute;n explicaremos brevemente el proceso para subir apps y aplicaciones al Windows Store
Registro...]]></description>
			<content:encoded><![CDATA[><p>La plataforma Windows Store nos permite descargarnos aplicaciones para la plataforma de Windows 8, Windows Phone y Windows RT, pero para que sean accesibles deben cumplir una serie de est&aacute;ndar y ser aprobada.</p>
<p>A continuaci&oacute;n explicaremos brevemente el proceso para subir apps y aplicaciones al Windows Store</p>
<h3>Registro como desarrollador</h3>
<p>Deberemos registrarnos como desarrolladores ya sea como empresa o como individuo desde una cuenta de Windows Live en el enlace&nbsp;<a href="http://go.microsoft.com/fwlink/p/?LinkID=245786" target="_blank">http://go.microsoft.com/fwlink/p/?LinkID=245786</a>&nbsp;</p>
<p>El registro se completar&aacute; con el pago de 37&euro; que garantizar&aacute; que somos personas reales y no tenemos prop&oacute;sitos de spam.</p>
<h3>Env&iacute;o del app</h3>
<p>Desde el dashboard de Windows Store, clickaremos en Submit an app donde especificaremos:</p>
<ul>
<li>Nombre</li>
<li>Detalles de venta</li>
<li>Opciones avanzadas</li>
<li>Restricciones de uso por edad del usuario seg&uacute;n el contenido</li>
<li>Uso de criptograf&iacute;a</li>
<li>Paquetes: en este punto seleccionaremos los paquetes de nuestro proyecto de Visual Studio</li>
<li>Descripci&oacute;n</li>
</ul>
<p>Una vez enviada, pasar&aacute; por distintas fases de certificaci&oacute;n por parte del equipo de Microsoft</p>
<h3>Fases de validaci&oacute;n</h3>
<p>Podemos comprobar el estado de nuestra app desde el dashboard de Windows Store. Los diferentes estados pueden ser:</p>
<ul>
<li>Upload</li>
<li>Preprocessing</li>
<li>Security test</li>
<li>Technical compliance tests</li>
<li>Content compliance</li>
<li>Release</li>
<li>Signing and publishing</li>
<li>Certification report: paso final cuando ha sido totalmente aceptada</li>
</ul>
<h4><a id="upload"></a></h4>
<p>durante los cu&aacute;les pueden ser rechazada si no cumple el proceso de validaci&oacute;n. Si no fuera aceptada, se crear&iacute;a un informe de los fallos detectados y consejos para solucionarlos.</p>
<p>&nbsp;</p>
<p><br /><br /></p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=143</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/como-subir-apps-a-windows-store.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Como subir aplicaciones a AppWorld de Blackberry</title>
			<link>http://www.imaginanet.com/blog/como-subir-aplicaciones-a-appworld-de-blackberry.html</link>
			<guid>http://www.imaginanet.com/blog/como-subir-aplicaciones-a-appworld-de-blackberry.html</guid>
			<comments>http://www.imaginanet.com/blog/como-subir-aplicaciones-a-appworld-de-blackberry.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue, 12 Mar 2013 13:38:12 +0100</pubDate>
					<category><![CDATA[Apps]]></category>
					<description><![CDATA[Ahora nos toca explicar el proceso de subida de apps con la plataforma de RIM.&nbsp;
Crear cuenta&nbsp;BlackBerry App World Vendor Account
Esta cuenta de desarrollador de BlackBerry la podemos crear desde&nbsp;https://appworld.blackberry.com/isvportal/login_input.do?pageId=0&nbsp;desde donde deberemos crear la cuenta.
Una vez...]]></description>
			<content:encoded><![CDATA[><p>Ahora nos toca explicar el proceso de subida de apps con la plataforma de RIM.&nbsp;</p>
<h3>Crear cuenta&nbsp;BlackBerry App World Vendor Account</h3>
<p>Esta cuenta de desarrollador de BlackBerry la podemos crear desde&nbsp;<a href="https://appworld.blackberry.com/isvportal/login_input.do?pageId=0" target="_blank">https://appworld.blackberry.com/isvportal/login_input.do?pageId=0</a>&nbsp;desde donde deberemos crear la cuenta.</p>
<p>Una vez registrados nos enviar&aacute;n un email con el proceso explicativo de como autenticarnos como empresa o como individuo, enviando los certificados necesarios por email. Una vez que as&iacute; lo hagamos, nos dar&aacute;n de alta como empresa.</p>
<h3>Subir la app</h3>
<p>Una vez que recibamos la respuesta por parte de RIM d&aacute;ndonos acceso, volveremos al Vendor Portal y autentic&aacute;ndonos entraremos en nuestro dashboard.</p>
<p>En el men&uacute; izquierdo, haremos click en <em>Manage products</em> y despu&eacute;s en <em>Add product</em> donde iniciaremos el proceso de datos de nuestra aplicaci&oacute;n, incluyendo iconos y capturas de pantalla.</p>
<p>Una vez que terminemos, haremos click en el icono "+" bajo <em>Add release</em> donde subiremos los ficheros, en el caso de una app BlackBerry subiremos el archivo .zip generado tras una build marcando la opci&oacute;n <em>Batch Import Files</em>, y si es para PlayBook el archivo .BAR marcando la opci&oacute;n <em>File Bundles</em>.</p>
<p>Para mayor compatibilidad, haremos click en&nbsp;<em>My product supports user generated content</em> dejando el resto de opciones por defecto.</p>
<p>Una vez que estemos seguros de que todo es correcto, haremos click en <em>Send for review</em> y esperaremos al resultado de la revisi&oacute;n.</p>
<h3>Fuentes</h3>
<ul>
<li><a href="https://developer.blackberry.com/blackberryworld/" target="_blank">Blacberry Developer</a></li>
</ul>
<ul>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=142</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/como-subir-aplicaciones-a-appworld-de-blackberry.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Como subir apps a Google Play</title>
			<link>http://www.imaginanet.com/blog/como-subir-apps-a-google-play.html</link>
			<guid>http://www.imaginanet.com/blog/como-subir-apps-a-google-play.html</guid>
			<comments>http://www.imaginanet.com/blog/como-subir-apps-a-google-play.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue, 12 Mar 2013 10:30:50 +0100</pubDate>
					<category><![CDATA[Apps]]></category>
					<category><![CDATA[Android]]></category>
					<description><![CDATA[Una vez creada nuestra app con Android Developer Tools y estemos seguros de que todo funciona como queremos, el siguiente paso es hacer un&nbsp;Hello World!&nbsp;al mundo. A continuaci&oacute;n vemos c&oacute;mo.
Crear cuenta de Google
Esta podr&aacute; ser una cuenta GMail, Youtube, Google Apps, etc. o cualquier de los servicios...]]></description>
			<content:encoded><![CDATA[><p>Una vez creada nuestra app con Android Developer Tools y estemos seguros de que todo funciona como queremos, el siguiente paso es hacer un&nbsp;<em>Hello World!</em>&nbsp;al mundo. A continuaci&oacute;n vemos c&oacute;mo.</p>
<h3>Crear cuenta de Google</h3>
<p>Esta podr&aacute; ser una cuenta GMail, Youtube, Google Apps, etc. o cualquier de los servicios que proporciona Google. Esta cuenta estar&aacute; asociada a la app y nos valdr&aacute; para realizar futuras modificaciones.</p>
<h3>Acceder a la consola Google Play para desarrolladores</h3>
<p>La consola de Google Play ser&aacute; el centro donde controlaremos todas las apps, su estado y estad&iacute;sticas. Se accede desde <a href="https://play.google.com/apps/publish/v2/" target="_blank">https://play.google.com/apps/publish/v2/</a> con la cuenta GMail que anteriormente hemos creado o queremos usar.</p>
<p>La primera vez que accedamos, deberemos registrar dicha cuenta como desarrollador pagando la cuota de alta, que en el momento de escribir esta gu&iacute;a son 25$ haciendo un cargo a la tarjeta de cr&eacute;dito especificada.</p>
<h3>Subir App</h3>
<p>Seguidamente, haremos click en <em>A&ntilde;adir nueva aplicaci&oacute;n</em> y subiremos los archivos:</p>
<ul>
<li>APK: archivo generado tras la compilaci&oacute;n del proyecto</li>
<li>Capturas de pantalla: al menos un par y se pueden hacer desde el simulador</li>
<li>Icono de alta resoluci&oacute;n, como emblema en Play Store</li>
</ul>
<p>A continuaci&oacute;n especificaremos los detalles de la app como nombre, descripci&oacute;n, tipo, idioma, categor&iacute;a opciones de publicaci&oacute;n, informaci&oacute;n de contacto.</p>
<p>Deberemos rellenar cuidadosamente esta informaci&oacute;n ya que ser&aacute; la que se ver&aacute; p&uacute;blicamente como informaci&oacute;n del app.</p>
<p>Una vez hecho el env&iacute;o, podremos crear traducciones para diferentes idiomas,&nbsp;capturas de pantalla, gr&aacute;ficos de funciones, iconos de alta resoluci&oacute;n, URL de v&iacute;deo de YouTube y gr&aacute;ficos promocionales localizados geogr&aacute;ficamente.</p>
<h3>Asignar un precio de venta por app o por contenido</h3>
<p>En el caso de que queramos asignar un precio de venta de nuestra app deberemos echarle un vistazo a la documentaci&oacute;n de Google&nbsp;<a href="http://support.google.com/googleplay/android-developer/topic/15867?hl=es">http://support.google.com/googleplay/android-developer/topic/15867?hl=es</a> para tener informaci&oacute;n completa sobre pagos, monedas, reembolso, etc. Por el contrario podemos utilizar el pago por contenido (libros, v&iacute;deos, revistas...) dentro de la propia app durante la programaci&oacute;n, podemos encontrar m&aacute;s informaci&oacute;n en&nbsp;<a href="http://developer.android.com/google/play/billing/index.html" target="_blank">http://developer.android.com/google/play/billing/index.html</a></p>
<h3>Referencias</h3>
<p>Android Developer: C&oacute;mo subir aplicaciones&nbsp;<a href="http://support.google.com/googleplay/android-developer/answer/113469?hl=es" target="_blank">http://support.google.com/googleplay/android-developer/answer/113469?hl=es</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=141</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/como-subir-apps-a-google-play.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Google publica su Search Quality Rating Guidelines</title>
			<link>http://www.imaginanet.com/blog/google-publica-su-search-quality-rating-guidelines.html</link>
			<guid>http://www.imaginanet.com/blog/google-publica-su-search-quality-rating-guidelines.html</guid>
			<comments>http://www.imaginanet.com/blog/google-publica-su-search-quality-rating-guidelines.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue,  5 Mar 2013 18:53:33 +0100</pubDate>
					<category><![CDATA[Google]]></category>
					<category><![CDATA[SEO]]></category>
					<category><![CDATA[Buscadores]]></category>
					<description><![CDATA[Esta gu&iacute;a publicada por primera vez por Google recoge la gu&iacute;a de clasificaci&oacute;n de la calidad de las b&uacute;squedas que utiliza el buscador. Est&aacute; dentro de un archivo pdf extenso y publicado en ingl&eacute;s.
En este otro enlace, tambi&eacute;n en ingl&eacute;s, se pueden ver los cambios realizados en...]]></description>
			<content:encoded><![CDATA[><p>Esta gu&iacute;a publicada por primera vez por Google recoge la gu&iacute;a de clasificaci&oacute;n de la calidad de las b&uacute;squedas que utiliza el buscador. Est&aacute; dentro de un <strong><a href="http://static.googleusercontent.com/external_content/untrusted_dlcp/www.google.com/en//insidesearch/howsearchworks/assets/searchqualityevaluatorguidelines.pdf" target="_blank">archivo pdf extenso</a></strong> y publicado en ingl&eacute;s.</p>
<p><br /><strong><a href="http://searchengineland.com/google-gutted-its-search-quality-rating-guidelines-for-public-release-150281" target="_blank">En este otro enlace</a></strong>, tambi&eacute;n en ingl&eacute;s, se pueden ver los cambios realizados en esta &uacute;ltima versi&oacute;n de noviembre de 2012 con respecto a versiones previas.</p>
<p><br />Y siguiendo con el mismo tema, tambi&eacute;n Google acaba de publicar una <strong><a href="http://www.google.com/insidesearch/howsearchworks/thestory/" target="_blank">infograf&iacute;a interactiva sobre el funcionamiento de las b&uacute;squedas</a></strong> en el buscador. Se divide en tres partes principales en las que ense&ntilde;a c&oacute;mo busca y encuentra el contenido, c&oacute;mo utiliza los algoritmos para clasificarlo y presentar el resultado de una b&uacute;squeda, y finalmente qu&eacute; hace con el spam.</p>
<p>Esta infograf&iacute;a no pasa de ser una introducci&oacute;n sobre los conceptos b&aacute;sicos de las b&uacute;squedas en Google.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=140</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/google-publica-su-search-quality-rating-guidelines.html</feedburner:origLink>
		</item>
				
		<item>
			<title>El 20% de todo el tráfico de buscadores lo condensan 5 páginas web</title>
			<link>http://www.imaginanet.com/blog/el-20-de-todo-el-trafico-de-buscadores-lo-condensan-5-paginas-web.html</link>
			<guid>http://www.imaginanet.com/blog/el-20-de-todo-el-trafico-de-buscadores-lo-condensan-5-paginas-web.html</guid>
			<comments>http://www.imaginanet.com/blog/el-20-de-todo-el-trafico-de-buscadores-lo-condensan-5-paginas-web.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon,  4 Mar 2013 18:59:53 +0100</pubDate>
					<category><![CDATA[Internet]]></category>
					<category><![CDATA[Buscadores]]></category>
					<description><![CDATA[Facebook, YouTube, Yahoo, Wikipedia y Amazon son las 5 p&aacute;ginas web que recogen el 20% del tr&aacute;fico generado desde los buscadores. Datos recogidos en un estudio realizado por Digital Marketer Report 2013. Coinciden estas 5 p&aacute;ginas con los 5 t&eacute;rminos m&aacute;s buscados en Google en 2012. Por lo tanto,...]]></description>
			<content:encoded><![CDATA[><p><strong>Facebook, YouTube, Yahoo, Wikipedia y Amazon son las 5 p&aacute;ginas web que recogen el 20% del tr&aacute;fico generado desde los buscadores</strong>. Datos recogidos en un estudio realizado por <a href="http://www.experian.com/blogs/marketing-forward/2013/02/19/understanding-the-search-landscape/?WT.srch=PR_EMS_DMReport_021913_blog" target="_blank">Digital Marketer Report 2013</a>. Coinciden estas 5 p&aacute;ginas con los 5 t&eacute;rminos m&aacute;s buscados en Google en 2012. Por lo tanto, estas 5 se llevan 1 de cada 5 clicks en los buscadores. El resto nos corresponde a los dem&aacute;s. Tambi&eacute;n est&aacute; el dato de que las 500 webs que primero aparecen copan el 50% del tr&aacute;fico global.</p>
<p>Los porcentajes se distribuyen de la siguiente manera: Facebook - 8,48%, Youtube - 5,55%, Yahoo - 2,63%, Wikipedia - 2,01% y Amazon - 1,40%.</p>
<p><br /><strong>Sobre el tr&aacute;fico pagado, m&aacute;s de lo mismo, las 10 primeras tienen el 16% del total</strong>.<br />Estos son los porcentajes para este tr&aacute;fico:</p>
<p>Amazon - 4,19%, eBay - 3,46%, eHow - 2,44%, BestBuy - 1,06% y Yahoo! Shopping - 0&acute;85%</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=139</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/el-20-de-todo-el-trafico-de-buscadores-lo-condensan-5-paginas-web.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Google advierte: no se pierde apenas PageRank extra con redirecciones 301</title>
			<link>http://www.imaginanet.com/blog/google-advierte-no-se-pierde-apenas-pagerank-extra-con-redirecciones-301.html</link>
			<guid>http://www.imaginanet.com/blog/google-advierte-no-se-pierde-apenas-pagerank-extra-con-redirecciones-301.html</guid>
			<comments>http://www.imaginanet.com/blog/google-advierte-no-se-pierde-apenas-pagerank-extra-con-redirecciones-301.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon,  4 Mar 2013 18:34:40 +0100</pubDate>
					<category><![CDATA[Internet]]></category>
					<category><![CDATA[Google]]></category>
					<category><![CDATA[SEO]]></category>
					<description><![CDATA[La recomendaci&oacute;n para los SEO era no cambiar las URL m&aacute;s que como una de las &uacute;ltimas opciones, ya que se pierde algo de PageRank, pero no demasiado. Ahora sabemos que cuando se enlacza una p&aacute;gina con PageRank X a otra, el PageRank traspasado ronda el 85%, con lo que la p&aacute;gina enlazada ser&aacute;...]]></description>
			<content:encoded><![CDATA[><p>La recomendaci&oacute;n para los SEO era no cambiar las URL m&aacute;s que como una de las &uacute;ltimas opciones, ya que se pierde algo de PageRank, pero no demasiado. Ahora sabemos que cuando se enlacza una p&aacute;gina con PageRank X a otra, el PageRank traspasado ronda el 85%, con lo que la p&aacute;gina enlazada ser&aacute; de PageRank 0,8X. Esto mismo ocurre con las redirecciones 301.</p>
<p><br />Puedes consultar este video donde Matt Cutts de Google Webmaster Help lo explica.</p>
<p><br /><br /></p>
<iframe src="http://www.youtube.com/embed/Filv4pP-1nw" width="560" height="315"></iframe>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=138</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/google-advierte-no-se-pierde-apenas-pagerank-extra-con-redirecciones-301.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Plantillas javascript para aplicaciones HTML5</title>
			<link>http://www.imaginanet.com/blog/plantillas-javascript-para-aplicaciones-html5.html</link>
			<guid>http://www.imaginanet.com/blog/plantillas-javascript-para-aplicaciones-html5.html</guid>
			<comments>http://www.imaginanet.com/blog/plantillas-javascript-para-aplicaciones-html5.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 25 Feb 2013 21:12:26 +0100</pubDate>
					<category><![CDATA[Apps]]></category>
					<category><![CDATA[HTML5]]></category>
					<category><![CDATA[JavaScript]]></category>
					<category><![CDATA[Ajax]]></category>
					<description><![CDATA[Cuando hacemos una aplicaci&oacute;n web, normalmente usamos javascript para modificar elementos html en la parte cliente, con librer&iacute;as como jquery se pueden hacer muchas cosas. Pero cada vez las aplicaciones web son m&aacute;s complejas, sobre todo en la parte del cliente y no s&oacute;lo necesitamos mofificar un...]]></description>
			<content:encoded><![CDATA[><p>Cuando hacemos una aplicaci&oacute;n web, normalmente usamos javascript para modificar elementos html en la parte cliente, con librer&iacute;as como jquery se pueden hacer muchas cosas. Pero cada vez las aplicaciones web son m&aacute;s complejas, sobre todo en la parte del cliente y no s&oacute;lo necesitamos mofificar un elemento, sino cargar datos con disposiciones complejas.</p>
<p>Para esto existen multitud de motores de plantillas javascript, como por ejemplo, <a href="http://embeddedjs.com/" target="_blank">EJS</a>, <a href="http://code.google.com/p/trimpath/wiki/JavaScriptTemplates" target="_blank">trimPath</a>, <a href="http://twitter.github.com/hogan.js/" target="_blank">Hogan.js</a>, ...</p>
<p>Estos motores de plantillas nos permiten separar la l&oacute;gica de la aplicaci&oacute;n de la vista, pero en el lado del cliente, del mismo modo que nos lo permiten otros lenguajes del lado del servidor como PHP, ASP, Java (JSP).</p>
<p>Quiz&aacute;s el escenario ideal para utilizar estas tecnolog&iacute;as es cuando utilizamos el lado del servidor para obtener los datos en formato XML o JSON por medio de WebServices o llamadas REST. Luego s&oacute;lo tenemos que separar las presentaciones de estos datos en plantillas para pasarle los datos desde nuestra aplicaci&oacute;n y mostrarlas d&oacute;nde deseemos.</p>
<p>Imaginemos que tenemos en el servidor una plantilla en un archivo de texto plano (templates/users.ejs). En esta plantilla mostraremos un listado de usuarios. Para nuestro ejemplo utilizaremos la librer&iacute;a EJS que tiene una sintaxis muy similar a ASP.</p>
<p>Si nuestra aplicaci&oacute;n llama a un servidor REST para obtener la lista de usuarios, por ejemplo a http://api.servidor.com/users.json y recibimos los datos en una variable llamada userData:</p>
<pre class="code javascript">var tpl = new EJS("templates/users.ejs");
var html = tpl.render({users: userData});
</pre>
<p>Con este c&oacute;digo tendr&iacute;amos la variable html con el c&oacute;digo html a insertar en nuestra aplicaci&oacute;n.</p>
<p>La plantilla users.ejs podr&iacute;a ser de la siguiente forma:</p>
<pre class="code html">&lt;ul&gt;
	&lt;% for (var i in users) { %&gt;
	&lt;i&gt;&lt;%= users[i].name %&gt;&gt;&lt;/li&gt;
	&lt;% } %&gt;
&lt;/ul&gt;
</pre>
<p>Con otros motores de plantillas como Hogan.js tendr&iacute;amos una sintaxis m&aacute;s limpia, ejemplo:</p>
<pre class="code html">&lt;ul&gt;
	{{#users}}
	&lt;li&gt; {{name}} &lt;/li&gt;
	{{/users}}
&lt;/ul&gt;
</pre>
<p>Cada uno tendr&aacute; sus preferencias a la hora de seleccionar uno de estos motores, habr&aacute; que tener en cuenta la limpieza en el html, la velocidad de proceso, etc ...</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=137</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/plantillas-javascript-para-aplicaciones-html5.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Pasador de imágenes html5</title>
			<link>http://www.imaginanet.com/blog/pasador-de-imagenes-html5.html</link>
			<guid>http://www.imaginanet.com/blog/pasador-de-imagenes-html5.html</guid>
			<comments>http://www.imaginanet.com/blog/pasador-de-imagenes-html5.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 25 Feb 2013 20:10:25 +0100</pubDate>
					<category><![CDATA[HTML5]]></category>
					<category><![CDATA[JavaScript]]></category>
					<category><![CDATA[CSS]]></category>
					<description><![CDATA[Vamos a ver una forma alternativa de definir un pasador de im&aacute;genes usando tecnolog&iacute;as de HTML5, en concreto, transiciones de CSS3.
Con este m&eacute;todo nos encontramos con algunas ventajas pero tambi&eacute;n con algunas desventajas:
Ventajas:

Las animaciones ser&aacute;n m&aacute;s suaves ya que es el navegador...]]></description>
			<content:encoded><![CDATA[><p>Vamos a ver una forma alternativa de definir un pasador de im&aacute;genes usando tecnolog&iacute;as de HTML5, en concreto, transiciones de CSS3.</p>
<p>Con este m&eacute;todo nos encontramos con algunas ventajas pero tambi&eacute;n con algunas desventajas:</p>
<p><strong>Ventajas:</strong></p>
<ul>
<li>Las animaciones ser&aacute;n m&aacute;s suaves ya que es el navegador el que se encarga de hacerlas de forma nativa.</li>
<li>Podemos cambiar el tipo de animaci&oacute;n simplemente modificando la hoja de estilos.</li>
<li>En los navegadores que no soporten transiciones el pasador seguir&aacute; funcionando, s&oacute;lo que no se ver&aacute;n las animaciones.</li>
<li>El c&oacute;digo javascript necesario se reduce.</li>
</ul>
<p><strong>Desventajas:</strong></p>
<ul>
<li>Con alg&uacute;n tipo de animaciones tendremos que bloquear el pasador mientras se realiza la animaci&oacute;n, para que no se desmonte nuestra maqueta y no se vea feo.</li>
<li>En navegadores antiguos (Explorer versi&oacute;n menor a la 10) no se ver&aacute;n las animaciones.</li>
</ul>
<p><strong>Funcionamiento</strong>:</p>
<p>Lo primero que tenemos que hacer es inicializar los elementos que queremos animar. En nuestro caso pondremos la clase "active" al elemento actual, y las clases "prev" y "next" al elemento anterior y siguiente respectivamente</p>
<p>Para las animaciones definiremos 3 clases "center", "prev" y "next". Estas clases ser&aacute;n las posiciones finales de los elementos. Por ejemplo, si le damos al bot&oacute;n siguiente. El elemento con clase "active" pasar&aacute; a tener la clase "prev" y el elemento con la clase "next" pasar&aacute; a tener la clase "center".</p>
<pre class="code css">.slider div.images div.next {
	left: 100%;
}
.slider div.images div.prev {
	left: -100%;
}
.slider div.images div.center {
	left: 0;
}
</pre>
<p>Para que funcionen las animaciones definiremos una clase "animate" a la cual le pondremos la transici&oacute;n a utilizar:</p>
<pre class="code css">.slider div.images div.animate {
	transition: left 400ms;
	-moz-transition: left 400ms;
	-webkit-transition: left 400ms;
	-ms-transition: left 400ms;
	-o-transition: left 400ms;
	z-index: 2;
}
</pre>
<p>Luego s&oacute;lo tendremos que ir a&ntilde;adiendo y quitando clases por medio de javascript.</p>
<p>El funcionamiento del pasador se puede ver aqu&iacute;:</p>
<iframe src="http://www.imaginanet.com/blog_files/html5slider/slider.htm" style="border: none; width: 100%; height: 233px; overflow: hidden; margin: 10px 0;"></iframe>
<p>El c&oacute;digo fuente se puede ver <a href="http://www.imaginanet.com/blog_files/html5slider/slider.htm" target="_blank">aqu&iacute;</a></p>
<p>Cambiando el css de las classes "next", "prev" y "center" y el tipo de transici&oacute;n podemos tener distintas animaciones para este pasador, en el ejemplo, las im&aacute;genes se mueven en horizontal, pero ser&iacute;a muy sencillo hacer que se moviesen en vertical, simplemente cambiando la propiedad <strong>left</strong> por <strong>top</strong>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=136</wfw:commentRss>
			<slash:comments>1</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/pasador-de-imagenes-html5.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Animaciones HTML 5 con SVG, CSS 3 y jQuery</title>
			<link>http://www.imaginanet.com/blog/animaciones-html-5-con-css-3-y-jquery.html</link>
			<guid>http://www.imaginanet.com/blog/animaciones-html-5-con-css-3-y-jquery.html</guid>
			<comments>http://www.imaginanet.com/blog/animaciones-html-5-con-css-3-y-jquery.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 25 Feb 2013 09:11:35 +0100</pubDate>
					<category><![CDATA[HTML5]]></category>
					<category><![CDATA[JavaScript]]></category>
					<category><![CDATA[CSS]]></category>
					<description><![CDATA[En anteriores entradas hemos hablado de como hacer animaciones HTML 5 con SVG de varias maneras: 

Para videojuegos, con requestAnimationFrame
Animaciones propias de SVG
Eventos en SVG

En la primera se habla de c&oacute;mo hacer animaciones avanzadas con Javascript para juegos mientras que en las dos &uacute;ltimas se habla de...]]></description>
			<content:encoded><![CDATA[>En anteriores entradas hemos hablado de como hacer animaciones HTML 5 con SVG de varias maneras:<br /> 
<ul>
<li><a href="http://www.imaginanet.com/blog/animaciones-en-html5.html">Para videojuegos, con requestAnimationFrame</a></li>
<li><a href="http://www.imaginanet.com/blog/introduccion-a-las-animaciones-de-svg.html">Animaciones propias de SVG</a></li>
<li><a href="http://www.imaginanet.com/blog/animaciones-css-y-eventos-en-svg.html">Eventos en SVG</a></li>
</ul>
<p>En la primera se habla de c&oacute;mo hacer animaciones avanzadas con Javascript para juegos mientras que en las dos &uacute;ltimas se habla de como hacer animaciones con SVG.<br /> <br /> &Eacute;sta entrada va a tratar de c&oacute;mo hacerlo con un enfoque diferente, ya que se va a centrar de <strong>como es accesible cualquier SVG a trav&eacute;s de los elementos DOM, y por tanto desde Javascript y CSS 3</strong>.<br /> <br /> Vamos a suponer un ejemplo sencillo de un elemento rect (rect&aacute;ngulo) de SVG que variamos su posici&oacute;n mediante animate de jQuery y modificar su color con animation de CSS 3 al hacer click en un bot&oacute;n, a&ntilde;adiendo otros eventos como un evento hover y el evento click en el recuadro. <br /> <br /> La diferencia con el resto de anteriores maneras descritas en otras entradas de blog, es el uso de jQuery para conseguir los efectos, ya que tenemos control total sobre el proceso de animaci&oacute;n &nbsp;otros elementos que est&eacute;n fuera del SVG.<br /> <br /> En primer lugar deberemos tener en cuenta el navegador a usar. El soporte total para SVG ocurre en Firefox, Google Chrome, Safari, Opera, pero no en Internet Explorer 9 (e inferiores), por lo que el siguiente ejemplo es muy probable que no funcione.<br /> <br /> A continuaci&oacute;n, el ejemplo:</p>
<style>
    #frame {
        width: 300px;
        height: 300px;
        border: 4px solid black;
        position: relative;
    }
    #svgtest {
        cursor: pointer;
        position: absolute;
        top: 0px;
        left: 0px;
    }
    #svgtest rect {
        stroke: blue;
        fill: red;
        stroke-width: 1px;
    }
    #svgtest rect:hover {
        fill: blue;
    }

    @keyframes animacionCambioColor {
    0%   {fill:red;}
    25%  {fill:yellow;}
    50%  {fill:orange;}
    100% {fill:red;}
    }

    /* Firefox */
    @-moz-keyframes animacionCambioColor {
    0%   {fill:red;}
    25%  {fill:yellow;}
    50%  {fill:orange;}
    100% {fill:red;}
    }

    /* Safari y Chrome */
    @-webkit-keyframes animacionCambioColor {
    0%   {fill:red;}
    25%  {fill:yellow;}
    50%  {fill:orange;}
    100% {fill:red;}
    }

    /* Opera */
    @-o-keyframes animacionCambioColor {
    0%   {fill:red;}
    25%  {fill:yellow;}
    50%  {fill:orange;}
    100% {fill:red;}
    }
</style>
<script type="text/javascript">
$(document).ready(function() {
    $("#svgtest rect").click(function() {
        alert("Elemento rect");
    });
    $("#animar_rect").click(function(e) {
        e.preventDefault();
        var frame_height = $("#frame").css("height").replace("px","");
        var frame_width = $("#frame").css("width").replace("px","");
        var rect_height =  $("#svgtest rect").attr("height").baseVal.value;
        var rect_width =  $("#svgtest rect").attr("width").baseVal.value;

        // Asignamos al rectángulo el cambio de color
        $('#svgtest rect').css("animation","animacionCambioColor 12s");

        // Movemos hasta la mitad inferior
        $('#svgtest').animate({
            left: (frame_width/2)-(rect_width/2),
            top: frame_height-rect_height-1
        }, 3000, function() {
            // Movemos hasta la mitad derecha
            $('#svgtest').animate({
                left: frame_width-rect_width-1,
                top: (frame_height/2)-(rect_height/2)
            }, 3000, function() {
                // Movemos hasta la mitad derecha
                $('#svgtest').animate({
                    left: 0,
                    top: 0
                }, 3000, function() {
                    // Quitamos la asignación de la animación para poder ejecutarla otra vez
                    $('#svgtest rect').css("animation","none");
                });
            });
        });
    });
});
</script>
<button id="animar_rect">Animar rect&aacute;ngulo</button>

<div id="frame">
<svg id="svgtest" xmlns="http://www.w3.org/2000/svg" version="1.1">
<rect x="1" y="1" height="50" width="50" rx="20" ry="20"/>
</svg>
</div>


<p>y ahora el c&oacute;digo fuente:</p>
<pre class="code">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;body&gt;
    &lt;script src="http://code.jquery.com/jquery-1.9.1.min.js"&gt;&lt;/script&gt;

    &lt;style&gt;
    #frame {
        width: 300px;
        height: 300px;
        border: 4px solid black;
        position: relative;
    }
    #svgtest {
        cursor: pointer;
        position: absolute;
        top: 0px;
        left: 0px;
    }
    #svgtest rect {
        stroke: blue;
        fill: red;
        stroke-width: 1px;
    }
    #svgtest rect:hover {
        fill: blue;
    }

    @keyframes animacionCambioColor {
    0%   {fill:red;}
    25%  {fill:yellow;}
    50%  {fill:orange;}
    100% {fill:red;}
    }

    /* Firefox */
    @-moz-keyframes animacionCambioColor {
    0%   {fill:red;}
    25%  {fill:yellow;}
    50%  {fill:orange;}
    100% {fill:red;}
    }

    /* Safari y Chrome */
    @-webkit-keyframes animacionCambioColor {
    0%   {fill:red;}
    25%  {fill:yellow;}
    50%  {fill:orange;}
    100% {fill:red;}
    }

    /* Opera */
    @-o-keyframes animacionCambioColor {
    0%   {fill:red;}
    25%  {fill:yellow;}
    50%  {fill:orange;}
    100% {fill:red;}
    }

    &lt;/style&gt;
&lt;script&gt;
$(document).ready(function() {
    $("#svgtest rect").click(function() {
        alert("Elemento rect");
    });
    $("#animar_rect").click(function(e) {
        e.preventDefault();
        var frame_height = $("#frame").css("height").replace("px","");
        var frame_width = $("#frame").css("width").replace("px","");
        var rect_height =  $("#svgtest rect").attr("height");
        var rect_width =  $("#svgtest rect").attr("width");

        // Asignamos al rect&aacute;ngulo el cambio de color
        $('#svgtest rect').css("animation","animacionCambioColor 12s");

        // Movemos hasta la mitad inferior
        $('#svgtest').animate({
            left: (frame_width/2)-(rect_width/2),
            top: frame_height-rect_height-1
        }, 3000, function() {
            // Movemos hasta la mitad derecha
            $('#svgtest').animate({
                left: frame_width-rect_width-1,
                top: (frame_height/2)-(rect_height/2)
            }, 3000, function() {
                // Movemos hasta la mitad derecha
                $('#svgtest').animate({
                    left: 0,
                    top: 0
                }, 3000, function() {
                    // Quitamos la asignaci&oacute;n de la animaci&oacute;n para poder ejecutarla otra vez
                    $('#svgtest rect').css("animation","none");
                });
            });
        });
    });
});
&lt;/script&gt;
    &lt;button id="animar_rect"&gt;Animar rect&aacute;ngulo&lt;/button&gt;
    &lt;div id="frame"&gt;
        &lt;svg id="svgtest" xmlns="http://www.w3.org/2000/svg" version="1.1"&gt;
            &lt;rect x="1" y="1" height="50" width="50" rx="20" ry="20"/&gt;
        &lt;/svg&gt;
    &lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;

</pre>
Como podemos ver, el ejemplo es muy sencillo y puede ser &uacute;til en animaciones sencillas que tengan un alto uso de Javascript para interactuar con otros elementos, como mapas, men&uacute;s o ciertos efectos que hasta ahora s&oacute;lo se hac&iacute;an en Flash.<br /> <br />
<h3>Adobe Edge como programa para crear animaciones HTML 5</h3>
Hasta ahora siempre hemos hablado de programar nosotros todas las animaciones, teniendo control total y haci&eacute;ndolo de la manera m&aacute;s optimizada (supuestamente). Desde no hace mucho, Adobe lanz&oacute; su aplicaci&oacute;n Edge que permite crear animaciones HTML 5 desde una interfaz similar a Flash.<br /> <br /> Podemos ver <a href="http://html.adobe.com/edge/animate/showcase.html" target="_blank">algunos ejemplos hechos en Adobe Edge</a> y valorar si realmente necesitamos un programa externo o podemos programarlo nosotros mismos.
<p>Aunque la opci&oacute;n de Adobe Edge es relativamente nueva y puede ser que todav&iacute;a est&eacute; mucho por hacer para ese software, <strong>es bastante significativo que Adobe saque una l&iacute;nea de productos que es cl&aacute;ramente competidora de Adobe Flash</strong>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=135</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/animaciones-html-5-con-css-3-y-jquery.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Cómo añadir un dominio a tus hosts</title>
			<link>http://www.imaginanet.com/blog/como-anadir-un-dominio-a-tus-hosts.html</link>
			<guid>http://www.imaginanet.com/blog/como-anadir-un-dominio-a-tus-hosts.html</guid>
			<comments>http://www.imaginanet.com/blog/como-anadir-un-dominio-a-tus-hosts.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 25 Feb 2013 08:55:08 +0100</pubDate>
					<category><![CDATA[Internet]]></category>
					<description><![CDATA[En ocasiones ocurre que registramos un dominio, o cambiamos los DNS de un dominio y este no es accesible durante un tiempo. O incluso queremos hacer pruebas con un dominio no registrado. Por tanto vamos a ver como hacer que dicho dominio sea accesible para nuestro equipo. Independientemente del sistema operativo que tengamos, lo...]]></description>
			<content:encoded><![CDATA[><p>En ocasiones ocurre que registramos un dominio, o cambiamos los DNS de un dominio y este no es accesible durante un tiempo. O incluso queremos hacer pruebas con un dominio no registrado. Por tanto vamos a ver como hacer que dicho dominio sea accesible para nuestro equipo. Independientemente del sistema operativo que tengamos, lo primero es tener claro el dominio que queremos a&ntilde;adir y la IP donde se encuentra dicho dominio o donde queramos que apunte el dominio en nuestro equipo.</p>
<p>Supongamos que queremos a&ntilde;adir el dominio prueba.com a la ip 192.168.1.2, para ello hay que realizar lo siguiente seg&uacute;n el sistema operativo (donde b&aacute;sicamente consiste en editar un archivo).</p>
<p><strong>Windows:</strong><br /> - Abrir el men&uacute; de inicio (CONTROL + ESCAPE, o tecla de windows a la izquierda del ALT), y hacer click sobre Equipo.<br /> - Entramos en C:/Windows (carpeta donde est&eacute; instalado el sistema operativo), y buscamos el archivo &ldquo;notepad&rdquo;. Lo seleccionamos y le damos al "bot&oacute;n derecho" del rat&oacute;n, y seleccionamos "Ejecutar como administrador".<br /> - Ahora en notepad le damos arriba a "Archivo" y "abrir", y entramos en la siguiente ruta: C:/Windows/System32/drivers/etc<br /> - Una vez en la ruta anterior, cambiamos el filtro (esquina inferior derecha) de "*.txt" a "todos los archivos", y abrimos el archivo &ldquo;hosts&rdquo;<br /> - Ahora nos posicionamos al final del archivo, y en una l&iacute;nea nueva escribimos lo siguiente:<br /> 192.168.1.2 prueba.com<br /> 192.168.1.2 www.prueba.com<br /> - Guardamos el archivo, y abrimos un navegador donde escribimos el dominio y comprobamos que efectivamente apunta a la ip indicada. Tambi&eacute;n se puede hacer un &ldquo;ping&rdquo; al dominio desde nuestro equipo para comprobar la redirecci&oacute;n.</p>
<p><strong>Linux:</strong><br /> - Accedemos a la l&iacute;nea de comandos.<br /> - Nos identificamos como usuario &ldquo;root&rdquo;.<br /> - Editamos el archivo /etc/hosts con nuestro editor favorito (nano, vi, &hellip;)<br /> - Y a&ntilde;adimos al final de dicho archivo las l&iacute;neas:<br /> 192.168.1.2 prueba.com<br /> 192.168.1.2 www.prueba.com<br /> - Ahora tan solo queda probar que funciona correctamente. Para ello hacemos un ping al dominio y vemos que se resuelve a la IP correspondiente.</p>
<p><strong>MAC:</strong><br /> - Accedemos a la l&iacute;nea de comandos.<br /> - Nos identificamos como usuario &ldquo;root&rdquo;.<br /> - Editamos el archivo /private/etc/hosts<br /> - Y a&ntilde;adimos al final de dicho archivo las l&iacute;neas:<br /> 192.168.1.2 prueba.com<br /> 192.168.1.2 www.prueba.com<br /> - Ahora tan solo queda probar que funciona correctamente.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=134</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/como-anadir-un-dominio-a-tus-hosts.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Cómo optimizar la carga de imágenes con cache (mod_expires Apache)</title>
			<link>http://www.imaginanet.com/blog/como-optimizar-la-carga-de-imagenes-con-cache-mod-expires-apache.html</link>
			<guid>http://www.imaginanet.com/blog/como-optimizar-la-carga-de-imagenes-con-cache-mod-expires-apache.html</guid>
			<comments>http://www.imaginanet.com/blog/como-optimizar-la-carga-de-imagenes-con-cache-mod-expires-apache.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 25 Feb 2013 08:29:06 +0100</pubDate>
					<category><![CDATA[Rendimiento]]></category>
					<description><![CDATA[Normalmente la carga de im&aacute;genes se suele optimizar de varias formas, donde en su mayor&iacute;a todas ellas tienen en particular o bien reducir el tama&ntilde;o de las im&aacute;genes, utilizando menos calidad u otro formato m&aacute;s eficiente (gif, jpg...), o reducir el n&uacute;mero de peticiones al servidor o servidor...]]></description>
			<content:encoded><![CDATA[><p>Normalmente la carga de im&aacute;genes se suele optimizar de varias formas, donde en su mayor&iacute;a todas ellas tienen en particular o bien reducir el tama&ntilde;o de las im&aacute;genes, utilizando menos calidad u otro formato m&aacute;s eficiente (gif, jpg...), o reducir el n&uacute;mero de peticiones al servidor o servidor de im&aacute;genes.</p>
<p>La primera opci&oacute;n no tienen ning&uacute;n secreto, cuanto menos ocupe la foto m&aacute;s r&aacute;pido llegar&aacute; al visitante. Por ello se recomienda exportar todas las im&aacute;genes para web (Photoshop u otros editores llevan ya opciones de optimizaci&oacute;n para ello), escogiendo una calidad razonable.</p>
<p>La segunda opci&oacute;n se puede abordar de varias formas pero la m&aacute;s utilizada es la creaci&oacute;n de hojas de sprites. Esta t&eacute;cnica consiste en juntar todas las im&aacute;genes de la web en una sola im&aacute;gen m&aacute;s grande. Por tanto se reduce dr&aacute;sticamente el n&uacute;mero de peticiones que se realizan al servidor.</p>
<p>Ahora bien una vez que el visitante tiene todas las fotos descargadas, es decir, en su cach&eacute; del navegador. Por qu&eacute; deber&iacute;a est&eacute; volver a descargar las fotos cada vez que vuelva a visitar la web. Puesto que si las fotos no han cambiado, entonces no se deber&iacute;an volver a bajar. Este es el caso que vamos a optimizar en este art&iacute;culo, para as&iacute; ahorrar ancho de banda en la red y a su vez el tiempo de carga de la p&aacute;gina.</p>
<p>Para habilitar la cach&eacute; de im&aacute;genes tan solo debemos indicarle al navegador que las fotos no han caducado todav&iacute;a, que est&aacute;n son todav&iacute;a v&aacute;lidas. Y esto se consigue indicando o bien la duraci&oacute;n de dichas fotos, o la fecha espec&iacute;fica de caducidad. Dicha fecha de caducidad o duraci&oacute;n debe ir en la cabecera de cada foto. Esto se puede hacer en PHP gracias a la funci&oacute;n &ldquo;header&rdquo;, pero es mucho m&aacute;s r&aacute;pido hacerlo v&iacute;a .htaccess utilizando el m&oacute;dulo de &ldquo;expires&rdquo; de Apache (mod_expires).</p>
<p>Por ejemplo podemos incluir en nuestro .htaccess el siguiente c&oacute;digo:</p>
<pre class="code">ExpiresActive On
ExpiresByType image/gif A2592000
ExpiresByType image/png A2592000
ExpiresByType image/jpg A2592000
</pre>
<p>De esta manera estamos indicando que todos los archivos gif, png y jpg ser&aacute;n v&aacute;lidos hasta 1 mes despu&eacute;s de tenerlo en la cache, es decir, desde que visitamos la web por primera vez. Ahora bien si indicamos en vez de &ldquo;A&rdquo; de &ldquo;access&rdquo;, una &ldquo;M&rdquo; de &ldquo;modification&rdquo; entonces los archivos ser&iacute;an v&aacute;lidos hasta 1 mes desde su fecha de modificaci&oacute;n, de esta manera caducar&aacute;n a la vez para todos los visitantes.</p>
<pre class="code">ExpiresByType image/gif M2592000
</pre>
<p>El tiempo en estos casos se indica en segundos. Pero esta directiva permite una forma m&aacute;s sencilla como:</p>
<pre class="code">ExpiresByType text/html "access plus 1 month"
ExpiresByType image/gif "modification plus 5 hours 3 minutes"
</pre>
<p>Esto no es solo aplicable para las im&aacute;genes, sino tambi&eacute;n para archivos css y javascript. Ahora bien supongamos que cambiamos una de las im&aacute;genes y la mantenemos con el mismo nombre. En este caso si la foto caduca un mes despu&eacute;s de la primera visita, entonces el visitante seguir&aacute; viendo la foto antigua, por ello una soluci&oacute;n consiste en ir a&ntilde;adiendo un sufijo a la imagen como un n&uacute;mero de versi&oacute;n, de esta forma al cambiar el nombre de la imagen, esta se volver&aacute; a descargar.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=133</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/como-optimizar-la-carga-de-imagenes-con-cache-mod-expires-apache.html</feedburner:origLink>
		</item>
				
		<item>
			<title>HTML5 Frameworks. HTML5 Boilerplate y Twitter Bootstrap</title>
			<link>http://www.imaginanet.com/blog/html5-frameworks-html5-boilerplate-y-twitter-bootstrap.html</link>
			<guid>http://www.imaginanet.com/blog/html5-frameworks-html5-boilerplate-y-twitter-bootstrap.html</guid>
			<comments>http://www.imaginanet.com/blog/html5-frameworks-html5-boilerplate-y-twitter-bootstrap.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Fri, 22 Feb 2013 09:44:42 +0100</pubDate>
					<category><![CDATA[HTML5]]></category>
					<category><![CDATA[Accesibilidad]]></category>
					<category><![CDATA[Google Analytics]]></category>
					<category><![CDATA[CSS]]></category>
					<category><![CDATA[Navegadores]]></category>
					<description><![CDATA[&iquest;Qu&eacute; es un framework HTML5?
En el &aacute;mbito web, normalmente estamos m&aacute;s acostumbrados a asociar la palabra framework con los lenguajes de servidor. Estos frameworks, tan populares como Symfony, Ruby On Rails,&hellip; han conseguido aumentar en&oacute;rmemente la calidad de los productos web.
Estos...]]></description>
			<content:encoded><![CDATA[><h2>&iquest;Qu&eacute; es un framework HTML5?</h2>
<p>En el &aacute;mbito web, normalmente estamos m&aacute;s acostumbrados a asociar la palabra <strong>framework</strong> con los lenguajes de servidor. Estos frameworks, tan populares como <strong>Symfony</strong>, <strong>Ruby On Rails</strong>,&hellip; han conseguido aumentar en&oacute;rmemente la calidad de los productos web.</p>
<p>Estos frameworks est&aacute;n m&aacute;s enfocados a una programaci&oacute;n eficiente, centr&aacute;ndose demasiado en el lenguaje de servidor. Existe tambi&eacute;n una tendencia creciente, gracias a las <a href="http://en.wikipedia.org/wiki/Representational_state_transfer" target="_blank">interfaces RESTfuls</a> a hacer webs que no tienen por qu&eacute; necesariamente utilizar programaci&oacute;n de servidor directamente.</p>
<p>Para cualquiera de estas dos formas, es interesante centrarnos en un framework que trabaje quiz&aacute;s a un nivel m&aacute;s importante que es el lenguaje HTML5</p>
<p>Vamos a numerar algunas de las mejores pr&aacute;cticas</p>
<ul>
<li>Preparar una hoja de estilos, resenteando, normalizando y ofreciendo herramientas pr&aacute;cticas (helpers) </li>
<li>Directivas de optimizaci&oacute;n del servidor </li>
<li>Metainformaci&oacute;n en el servidor (robots.txt, humans.txt, &hellip;) </li>
<li>Organizaci&oacute;n del layout HTML5 </li>
<li>Estructura de carpetas para organizar la informaci&oacute;n </li>
<li>Documentaci&oacute;n </li>
</ul>
<!-- Caracter&iacute;sticas -->
<h2>Caracter&iacute;sticas b&aacute;sicas. HTML5 Boilerplate</h2>
<p>Los dos frameworks comentados aqu&iacute; (HTML5 Boilerplate y Twitter Bootstrap) presentan una serie de caracter&iacute;sticas que son muy interesantes para el desarrollo web. Vamos a explicar un poco m&aacute;s detalladamente algunos de estos puntos:</p>
<h3>Normalizaci&oacute;n de hojas de estilo</h3>
<p>Desde hace mucho tiempo ha existido la tendencia de <em>resetear</em> las hojas de estilo para eliminar todas las diferencias que asigna cada navegador a las etiquetas y as&iacute; partir desde cero. Esta es una gran idea que ahora se ha llevado al siguiente paso: <strong>Normalizar</strong>. En lugar de resetear todos los estilos, vamos a darle uniformidad haciendo que todos los estilos sean coherentes en una &aacute;mplia gama de navegadores.</p>
<h3>Soporte a versiones antiguas</h3>
<p>Otro concepto interesante es el sistema que ofrecen para dar soporte a navegadores m&aacute;s antiguos. Esto lo hace de dos maneras:</p>
<ul>
<li><strong>Modernizr</strong>: Es una librer&iacute;a que facilita saber qu&eacute; <strong>capacidades HTML5</strong> soporta tu navegador para facilitar la carga de <a href="https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills" target="_blank"><strong>Polyfills</strong></a> en el caso de no soportarlo nativamente. </li>
<li><strong>Condicionales</strong>: Mediante el uso de condicionales HTML se asignan una serie de clases a la etiqueta &amp;t;html&gt; para poder cambiarla desde CSS. Adem&aacute;s, a&ntilde;aden una clase <em>no-js</em> que ser&aacute; reemplaza a posterior&iacute; por <em>js</em> de forma que podremos saber tambi&eacute;n desde CSS si el Javascript est&aacute; deshabilitado. </li>
</ul>
<p>Pero !OJO!. Ni a nosotros, ni a los frameworks, nos gustan los navegadores antiguos. Existen por la red una &aacute;mplia gama de iniciativas como <a href="http://browsehappy.com/?locale=es">Browse Happy</a> que anima a los usuarios a mantener actualizados sus navagadores, por temas de seguridad y rendimiento. HTML5 Boilerplate, por ejemplo, tiene un mensaje que enlaza con esta p&aacute;gina en el caso de tener una versi&oacute;n de navegador arcaica. Tambi&eacute;n menciona la posibilidad de <a href="http://www.google.com/chromeframe/?hl=es">Google Frame</a> y as&iacute; embeber un motor de renderizado moderno en nuestros antiguos navegadores.</p>
<h3>Orden de carga</h3>
<p>Para una mayor rapidez de carga de la p&aacute;gina <strong>sugieren inlcuir todos nuestros SCRIPTs al final de la p&aacute;gina</strong>, de forma que estos puedan cargarse a la vez que la p&aacute;gina empieza a renderizarse y que no bloqueen la carga en el caso de que uno no pueda ser cargado. Incluso el SCRIPT de <strong>Google Analytics</strong>, el cual Google recomienda a&ntilde;adirlo entre las etiquetas &lt;HEAD&gt;. (<em>Google lo recomienda para que la visita pueda contar incluso si el navegador no ha terminado de carga la p&aacute;gina</em>).</p>
<p>La excepci&oacute;n a esta regla es el caso de <strong>Modernizr</strong>. Es necesario que se cargue antes de que la p&aacute;gina comience a renderizarse para que los nuevos elementos HTML5 sean soportados sin problemas.</p>
<h3>Optimizando el servidor</h3>
<p>Existen directivas <strong>.HTACCESS</strong> que permiten especificar estrategias de cach&eacute; eficientes para las webs. En el caso de que nuestro servidor permita el uso de este archivo y tenga instalados una serie de m&oacute;dulos vamos a ser capaces de enviar nuestras p&aacute;ginas web comprimidas en GZIP, cachear nuestras im&aacute;genes y scripts e incrementar el rendimiento de nuestra aplicaci&oacute;n significativamente. En el caso de que no soporte este archivo, tendremos que modificar directamente nuestros archivos de configuraci&oacute;n en el servidor.</p>
<!-- Twitter boostrap -->
<h2>Twitter Bootstrap</h2>
<p>Todas las caracteristicas anteriormente mencionadas hacen referencia al framework HTML5 Boilerplate. El otro framework que destacamos hoy, Twitter Bootstrap da una vuelta de tuerca m&aacute;s y se ofrece como una manera sencilla de empezar a montar el prototipo de tu p&aacute;gina web de forma r&aacute;pida y c&oacute;moda.</p>
<blockquote>Twitter Bootstrap es una colecci&oacute;n de herramientas de software libre para la creaci&oacute;n de sitios y aplicaciones web. Contiene plantillas de dise&ntilde;o basadas en HTML y CSS con tipograf&iacute;as, formularios, botones, gr&aacute;ficos, barras de navegaci&oacute;n y dem&aacute;s componentes de interfaz, as&iacute; como extensiones opcionales de JavaScript.      Es el proyecto mas popular en GitHub y es usado por la NASA y la MSNBC junto a dem&aacute;s organizaciones.</blockquote>
<p>Adem&aacute;s de utilizar muchos conceptos anteriormente mencionados, Twitter BootStrap ofrece herramientas de andamiaje (scaffolding) para estructurar nuestro LAYOUT de manera est&aacute;tica o l&iacute;quida, componentes Javascript reusables tales como pasadores de im&aacute;genes, formularios, men&uacute;s, migas de pan, etc. Todos realizados adoptando las mejores pr&aacute;cticas y permitiendo a los programadores extenderlos</p>
<p>Tambi&eacute;n existen p&aacute;ginas que ofrecen plantillas (gratuitas y de pago) para utilizar estos componentes, tales como <a href="https://wrapbootstrap.com/" target="_blank">https://wrapbootstrap.com/</a></p>
<p>Una cosa muy intersante de este framework es que todos los componentes parten de hojas de estilo compiladas desde LESS. As&iacute; que, o bien cuando te descargas la &uacute;ltima versi&oacute;n puedes definir una serie de variables (fuentes, colores, interlineado, &hellip;) o bien recompilar tu mismo estas hojas de estilo con alg&uacute;n compilador de <a href="http://www.imaginanet.com/blog/preprocesar-hojas-de-estilo-con-less.html">LESS</a></p>
<h2>Resumen</h2>
<p>Gracias al uso de estos frameworks la comunidad de desarrolladores va a mejorar enormemente gracias a estandarizaci&oacute;n, uso de mejores pr&aacute;cticas y partir de una base s&oacute;lida, testable y apoyada por una gran comunidad. Adem&aacute;s de eso, vamos a ser capaces de montar prototipos r&aacute;pidos y funcionales para poder centr&aacute;rnos en lo realmente interesante que es la <strong>l&oacute;gica de negocio.</strong></p>
<h2>Referencias</h2>
<ul>
<li><a href="http://html5boilerplate.com/" target="_blank">http://html5boilerplate.com/</a> </li>
<li><a href="http://twitter.github.com/bootstrap/" target="_blank">http://twitter.github.com/bootstrap/</a> </li>
<li><a href="http://necolas.github.com/normalize.css/" target="_blank">http://necolas.github.com/normalize.css/</a> </li>
<li><a href="http://modernizr.com/" target="_blank">http://modernizr.com/</a> </li>
<li><a href="http://browsehappy.com/?locale=es" target="_blank">http://browsehappy.com/?locale=es</a> </li>
<li><a href="http://humanstxt.org/ES" target="_blank">http://humanstxt.org/ES</a> </li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=132</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/html5-frameworks-html5-boilerplate-y-twitter-bootstrap.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Apps para Windows 8 hechas con HTML 5, Javascript y Phonegap</title>
			<link>http://www.imaginanet.com/blog/apps-para-windows-8-hechas-con-html-5-javascript-y-phonegap.html</link>
			<guid>http://www.imaginanet.com/blog/apps-para-windows-8-hechas-con-html-5-javascript-y-phonegap.html</guid>
			<comments>http://www.imaginanet.com/blog/apps-para-windows-8-hechas-con-html-5-javascript-y-phonegap.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Thu, 21 Feb 2013 18:25:02 +0100</pubDate>
					<category><![CDATA[Apps]]></category>
					<category><![CDATA[Windows 8]]></category>
					<description><![CDATA[Tablets de Microsoft: Windows 8 / Windows RT
El sistema operativo de Microsoft con la est&eacute;tica Metro ofrece una nueva plataforma para la creaci&oacute;n de apps contando con la potencia que ofrece la plataforma .NET y Visual Studio para desarrollar aplicaciones.
Aunque es un mercado emergente respecto a sus competidores...]]></description>
			<content:encoded><![CDATA[><h3>Tablets de Microsoft: Windows 8 / Windows RT</h3>
El sistema operativo de Microsoft con la est&eacute;tica Metro ofrece una nueva plataforma para la creaci&oacute;n de apps contando con la potencia que ofrece la plataforma .NET y Visual Studio para desarrollar aplicaciones.
<p>Aunque es un mercado emergente respecto a sus competidores directos Android e iOS, los resultados que ofrecen son de una est&eacute;tica muy vistosa y c&oacute;moda para el usuario, de una manera cl&aacute;ramente diferenciadora.</p>
<p>Un aspecto que deberemos tener claro, es que Windows 8 y Windows RT son en esencia el mismo sistema operativo pero con caracter&iacute;sticas algo diferentes: Windows 8 es para sistemas operativos x86 y Windows RT para ARM, por lo que Windows 8 tiene una mayor cantidad de aplicaciones pero Windows RT est&aacute; m&aacute;s optimizado para tablets.</p>
<p>&nbsp;</p>
<h3>Preparando el entorno con Visual Studio 2012</h3>
<p>Lo primero que deberemos hacer es <a href="http://www.microsoft.com/visualstudio/esn/downloads" target="_blank">instalar Visual Studio 2012</a> en el PC que utilicemos para desarrollar (no se puede instalar en Windows RT), comprando una licencia de empresa o si s&oacute;lo queremos probarlo, con la edici&oacute;n Express.</p>
<p>Durante la instalaci&oacute;n, crearemos una licencia de desarrollador, que nos servir&aacute; para firmar nuestras aplicaciones.</p>
<p>El siguiente paso ser&aacute; preparar el dispositivo, en este caso una tablet con Windows 8. Un aspecto importante es que el ordenador que se desarrolle y el  dispositivos tengan conectividad directa, por ejemplo por WiFi aunque tambi&eacute;n se puede por USB, ambos  dispositivos deber&aacute;n poder verse a trav&eacute;s de la red estando en el mismo grupo de trabajo.</p>
<p>Ahora deberemos instalar en el tablet<strong> las herramientas remotas para Visual Studio 2012</strong>, arquitectura ARM, que son descargables desde la misma p&aacute;gina que el Visual Studio. Durante la instalaci&oacute;n dejaremos todas las opciones por defecto y deberemos tener nuestra tablet preparada con una cuenta de usuario con contrase&ntilde;a.</p>
<p>Cada vez que queramos probar apps en la tablet, deberemos poner en marcha la aplicaci&oacute;n Remote Debugging Tools, ya que abre un servidor que se queda a la escucha a espera de que Visual Studio se conecte.</p>
<p>&nbsp;</p>
<h3>HTML 5 + Javascript + Phonegap = App Windows 8</h3>
<p>Instalaremos Phonegap descargando en primer lugar la &uacute;ltima versi&oacute;n desde <a href="http://phonegap.com/download/" target="_blank">http://phonegap.com/download/</a> y tras descomprimirlo seguiremos la <a href="http://docs.phonegap.com/en/2.4.0/guide_getting-started_windows-8_index.md.html" target="_blank">siguiente gu&iacute;a oficial de Phonegap</a> aunque resumiremos aqu&iacute; los pasos:</p>
<ul>
<li>Descomprimir Phonegap</li>
<li>Crearemos un nuevo proyecto en Visual Studio del tipo Templates -&gt; Javascript -&gt; Blank project</li>
<li>Una vez abierto el proyecto, a&ntilde;adiremos el archivo Javascript al proyecto ubicado en la carpeta de <em>Phonegap/lib/windows-8/cordova.js </em>dentro de la carpeta js de nuestro proyecto<em><br /></em></li>
</ul>
<p>y listo, a diferencia de otras plataformas como iOS o Android, no debemos a&ntilde;adir archivos al proyecto.</p>
<p>Ahora a&ntilde;adiremos cualquier c&oacute;digo Phonegap, por ejemplo, en el tag &lt;body&gt;</p>
<pre class="code">    &lt;body&gt;    

    &lt;script src="/js/cordova.js"&gt;&lt;/script&gt;

    &lt;script type="text/javascript"&gt;

        document.addEventListener("deviceready", function () {
            navigator.notification.alert("Este alert es de Phonegap");
        });

    &lt;/script&gt;

    &lt;/body&gt;
    
</pre>
<p>Deberemos prestar atenci&oacute;n a que hemos puesto la referencia a <em>cordova.js</em> dentro del proyecto en la carpeta <em>js</em>.</p>
<p>Una vez que pongamos nuestro c&oacute;digo JS, deberemos probarlo en la tablet. En vez de ejecutarlo en la m&aacute;quina local, seleccionaremos <em>M&aacute;quina remota</em> en el men&uacute; de compilaci&oacute;n.</p>
<p>Nos aparecer&aacute; entonces una pantalla en la que nos permitir&aacute; seleccionar las m&aacute;quinas candidatas a ser dispositivos de prueba dentro de nuestra red y que est&eacute;n corriendo la aplicaci&oacute;n de depuraci&oacute;n remota que antes hemos descrito.</p>
<p>Si todo va bien, podremos ver<strong> nuestra primera aplicaci&oacute;n HTML 5 sobre Windows RT</strong>.</p>
<p>&nbsp;</p>
<h3>Referencias</h3>
<ul>
<li><a href="http://www.genbeta.com/windows/cinco-claves-para-elegir-entre-windows-8-y-windows-rt" target="_blank">Diferencias entre Windows 8 y Windows RT</a></li>
<li><a href="http://blogs.msdn.com/b/dsvc/archive/2012/10/26/windows-rt-windows-store-app-debugging.aspx" target="_blank">Windows RT Store app Debugging</a></li>
<li><a href="http://docs.phonegap.com/en/2.4.0/guide_getting-started_windows-8_index.md.html" target="_blank">Instalar Phonegap en Visual Studio 2012</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=131</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/apps-para-windows-8-hechas-con-html-5-javascript-y-phonegap.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Enlaces no naturales. ¿Cómo los encuentro?</title>
			<link>http://www.imaginanet.com/blog/enlaces-no-naturales-como-los-encuentro.html</link>
			<guid>http://www.imaginanet.com/blog/enlaces-no-naturales-como-los-encuentro.html</guid>
			<comments>http://www.imaginanet.com/blog/enlaces-no-naturales-como-los-encuentro.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue, 12 Feb 2013 18:56:44 +0100</pubDate>
					<category><![CDATA[Google]]></category>
					<category><![CDATA[SEO]]></category>
					<description><![CDATA[Sabido es que cuando Google encuentra enlaces llamados de 'mala calidad' env&iacute;a un email avisando. El problema es que no dice qu&eacute; enlaces son esos, nos deja la tarea a nosotros, administradores de la web. Todo esto se debe al intento por parte de Google de evitar el link-building no natural (compra de enlaces o...]]></description>
			<content:encoded><![CDATA[><p>Sabido es que cuando Google encuentra enlaces llamados de 'mala calidad' env&iacute;a un email avisando. El problema es que no dice qu&eacute; enlaces son esos, nos deja la tarea a nosotros, administradores de la web. Todo esto se debe al intento por parte de Google de evitar el link-building no natural (compra de enlaces o similar).</p>
<p>Existe una manera seg&uacute;n Google, en concreto seg&uacute;n Matt Cutts de encontrar &eacute;stos enlaces:</p>
<p>Por un lado ordenando por m&aacute;s recientes los enlaces del sitio en Webmaster Tools, y por otro aprendiendo de los ejemplos de enlaces no naturales que propone Google, y ver las similitudes con tus enlaces.</p>
<p>Para m&aacute;s informaci&oacute;n, consultar el siguiente video:</p>
<iframe src="http://www.youtube.com/embed/gEBJeqvJReg" width="560" height="315"></iframe>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=130</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/enlaces-no-naturales-como-los-encuentro.html</feedburner:origLink>
		</item>
				
		<item>
			<title>SEO, Google + y mejores rankings</title>
			<link>http://www.imaginanet.com/blog/seo-google-y-mejores-rankings.html</link>
			<guid>http://www.imaginanet.com/blog/seo-google-y-mejores-rankings.html</guid>
			<comments>http://www.imaginanet.com/blog/seo-google-y-mejores-rankings.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 11 Feb 2013 16:13:47 +0100</pubDate>
					<category><![CDATA[Redes Sociales]]></category>
					<category><![CDATA[Google]]></category>
					<category><![CDATA[SEO]]></category>
					<description><![CDATA[Si has verificado tu perfil, tu ranking ser&aacute; mejor. Esta parece ser una de las maneras que tiene Google de competir con otras redes sociales como Linkedin, Twitter o qui&eacute;n sabe si Facebook. Verifica tu perfil en Google + y los contenidos publicados bajo ese perfil mejorar&aacute;n su posicionamiento.
Este es uno de...]]></description>
			<content:encoded><![CDATA[><p>Si has verificado tu perfil, tu ranking ser&aacute; mejor. Esta parece ser una de las maneras que tiene Google de competir con otras redes sociales como Linkedin, Twitter o qui&eacute;n sabe si Facebook. <strong>Verifica tu perfil en Google +</strong> y los contenidos publicados bajo ese perfil mejorar&aacute;n su posicionamiento.</p>
<p><br />Este es uno de las temas sobre los que habla <strong>Eric Schmidt</strong>, Presidente Ejecutivo de Google, en su &uacute;ltimo libro 'La nueva era digital' escrito junto con <strong>Jared Cohen</strong>, Jefe de Ideas de Google.</p>
<p><br />Entre otros comentarios sobre el futuro que nos aguarda, parece recomendable para cualquier SEO tener una cuenta en Google + (&iquest;todav&iacute;a no la tienes?), verificarla y asociarla a tus contenidos. <strong>Conseguir&aacute;s mejor posicionamiento</strong>.</p>
<p><br />Para m&aacute;s informaci&oacute;n&nbsp;<a href="http://goo.gl/Q47nX" target="_blank">http://goo.gl/Q47nX</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=129</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/seo-google-y-mejores-rankings.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Responsive Design: ¿qué hacemos con AdSense?</title>
			<link>http://www.imaginanet.com/blog/responsive-design-que-hacemos-con-adsense.html</link>
			<guid>http://www.imaginanet.com/blog/responsive-design-que-hacemos-con-adsense.html</guid>
			<comments>http://www.imaginanet.com/blog/responsive-design-que-hacemos-con-adsense.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed,  6 Feb 2013 18:49:31 +0100</pubDate>
					<category><![CDATA[Marketing OnLine]]></category>
					<category><![CDATA[HTML5]]></category>
					<category><![CDATA[Google]]></category>
					<description><![CDATA[Sabiendo que una de las tendencias del dise&ntilde;o web en 2013 es el desarrollo de sitios web con Dise&ntilde;o Responsivo o Sensible, se nos crea un problema al plantearnos qu&eacute; ocurre con las inserciones AdSense de nuestras p&aacute;ginas.
Despu&eacute;s de cerca de un a&ntilde;o de espera, por parte de los...]]></description>
			<content:encoded><![CDATA[><p>Sabiendo que una de las tendencias del dise&ntilde;o web en 2013 es el desarrollo de sitios web con Dise&ntilde;o Responsivo o Sensible, se nos crea un problema al plantearnos <strong>qu&eacute; ocurre con las inserciones AdSense de nuestras p&aacute;ginas</strong>.</p>
<p>Despu&eacute;s de cerca de un a&ntilde;o de espera, por parte de los desarrolladores de AdSense, para que Google tome cartas en el asunto y d&eacute; una soluci&oacute;n en forma de <strong>unidades de anuncio que se adapten a los cambios de tama&ntilde;o</strong> junto a los contenidos.</p>
<p>Sorpresivamente, Google AdSense Alemania dio a conocer el c&oacute;digo que se debe utilizar para el cambio de tama&ntilde;o de los anuncios. Por supuesto cumpliendo todas las directrices de AdSense. El c&oacute;digo es:</p>
<table border="0" cellpadding="0">
<tbody>
<tr>
<td>
<p>&lt;script   type=&rdquo;text/javascript&rdquo;&gt;<br /> google_ad_client = &ldquo;ca-publisher-id&rdquo;;<br /> if &nbsp;(window. innerWidth &nbsp;&gt;= 800) {<br />google_ad_slot   = &ldquo;1234567890&ldquo;;<br />google_ad_width   = 728;<br />google_ad_height   = 90;<br />}   else if &nbsp;(window.innerWidth &lt; 400) {<br />google_ad_slot   = &ldquo;<a href="file://localhost/tel/2345678901">2345678901</a>&ldquo;;<br />google_ad_width   = 300;<br />google_ad_height   = 250;<br />}   else {<br />google_ad_slot   = &ldquo;3456789012&ldquo;;<br />google_ad_width   = 468;<br />google_ad_height   = 60;<br />}<br />&lt;/script&gt;<br />&lt;script type=&rdquo;text/javascript&rdquo;<br />&nbsp; &nbsp; src=&rdquo;<a href="http://pagead2.googlesyndication.com/pagead/show_ads.js">http://pagead2.googlesyndication.com/pagead/show_ads.js</a>&ldquo;&gt;<br />&lt;/script&gt;<strong><br /></strong>&nbsp;</p>
</td>
</tr>
</tbody>
</table>
El c&oacute;digo est&aacute; desarrollado por Labnol y aprobado por el equipo de AdSense en Alemania. No obstante, seguimos esperando&nbsp; una soluci&oacute;n oficial por parte de Google.]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=128</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/responsive-design-que-hacemos-con-adsense.html</feedburner:origLink>
		</item>
				
		<item>
			<title>El futuro en Link Building: Citas Externas</title>
			<link>http://www.imaginanet.com/blog/el-futuro-en-link-building-co-citations.html</link>
			<guid>http://www.imaginanet.com/blog/el-futuro-en-link-building-co-citations.html</guid>
			<comments>http://www.imaginanet.com/blog/el-futuro-en-link-building-co-citations.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed,  6 Feb 2013 17:12:36 +0100</pubDate>
					<category><![CDATA[Marketing OnLine]]></category>
					<category><![CDATA[HTML5]]></category>
					<category><![CDATA[SEO]]></category>
					<description><![CDATA[Para Google hace ya mucho tiempo que los enlaces son de f&aacute;cil manipulaci&oacute;n. Son m&aacute;s importante para Google los enlaces que los otros ponen hacia tu web. De ah&iacute; la importancia que le da al intento de&nbsp;variar la manera de valorar los enlaces.
Ya que &eacute;stos siguen siendo la parte fundamental del...]]></description>
			<content:encoded><![CDATA[><p>Para Google hace ya mucho tiempo que los enlaces son de f&aacute;cil manipulaci&oacute;n. Son m&aacute;s importante para Google los enlaces que los otros ponen hacia tu web. De ah&iacute; la importancia que le da al intento de&nbsp;<strong>variar la manera de valorar los enlaces</strong>.</p>
<p>Ya que &eacute;stos siguen siendo la parte fundamental del trabajo en SEO, otorgarles&nbsp; un menor valor y tener en cuenta otros factores en el mismo texto se ha convertido en una realidad para Google. Es suficiente con que en el art&iacute;culo se mencione el nombre de la web o la palabra clave en otra parte para que Google lo considere como enlace natural.</p>
<p>A esto se refiere Citas Externas.<strong>&nbsp;Se abre una &eacute;poca de oportunidades para los SEO</strong>&nbsp;ya que los factores que intervienen en este proceso todav&iacute;a no est&aacute;n del todo claros, y aqu&iacute; como en todo, el que se adelanta&hellip; Y la mayor&iacute;a de SEO opinan que esta es la tendencia del futuro.</p>
<p>No es tan sencillo analizar la estructura y composici&oacute;n de las&nbsp;<strong>Citas Externas</strong>. Por un lado est&aacute;n las menciones que te citan, en qu&eacute; lugares se producen y junto a qui&eacute;n lo hacen. Por otro, tampoco es f&aacute;cil acertar a medir la influencia que tienes, &iquest;eres original o mezclas contenido de otro sitios?</p>
<span>Interesante tem&aacute;tica para seguirla durante los pr&oacute;ximos meses y ver su importancia en el futuro.</span>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=127</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/el-futuro-en-link-building-co-citations.html</feedburner:origLink>
		</item>
				
		<item>
			<title>El patrón active record en PHP</title>
			<link>http://www.imaginanet.com/blog/el-patron-active-record-en-php.html</link>
			<guid>http://www.imaginanet.com/blog/el-patron-active-record-en-php.html</guid>
			<comments>http://www.imaginanet.com/blog/el-patron-active-record-en-php.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue,  8 Jan 2013 20:52:15 +0100</pubDate>
					<category><![CDATA[MySQL]]></category>
					<category><![CDATA[Web 2.0]]></category>
					<category><![CDATA[PHP]]></category>
					<description><![CDATA[El patr&oacute;n active record, conocido sobre todo por su uso en ruby on rails es un patr&oacute;n de dise&ntilde;o que define una forma de acceder a los datos de una base de datos relacional y convertir las filas de una tabla en objetos.
Cuando se modifican los datos de un objeto se actualiza la fila correspondiente en la BBDD,...]]></description>
			<content:encoded><![CDATA[><p>El patr&oacute;n active record, conocido sobre todo por su uso en <strong>ruby on rails</strong> es un patr&oacute;n de dise&ntilde;o que define una forma de acceder a los datos de una base de datos relacional y convertir las filas de una tabla en objetos.</p>
<p>Cuando se modifican los datos de un objeto se actualiza la fila correspondiente en la BBDD, cuando se crea un objeto se a&ntilde;ade una fila y cuando se borra el objecto tambi&eacute;n se borra de la BBDD.</p>
<p>Para php nos encontramos con una implementaci&oacute;n open source muy similar a c&oacute;mo podemos trabajar en ruby on rails, la podemos encontrar en <a href="http://www.phpactiverecord.org/">www.phpactiverecord.org</a></p>
<p>Su objetivo es simplificar enormemente la interacci&oacute;n con la base de datos y eliminar la tarea de escribir SQL a mano para operaciones comunes. A diferencia de otros ORM, no es necesario utilizar generadores de c&oacute;digo ni mantener archivos de configuraci&oacute;n para las tablas. Est&aacute; basado en convenciones en lugar de configuraciones.</p>
<p>Un sencillo ejemplo de uso:</p>
<pre class="code php">class Car extends ActiveRecordModel {

	static $belongs_to = array(
		array('driver'),
		array('trademark')
	);

}
</pre>
<p>Seg&uacute;n las convenciones que se siguen, la clase Car se relaciona con la tabla cars (la clase en singular y la tabla en plural), esto se hace autom&aacute;ticamente y no es necesario configurar nada. En la propiedad de clase $belongs_to le indicamos que un coche tiene un conductor (clase Driver y tabla drivers) y una marca (clase Trademark y tabla trademarks). Las tablas tienen que tener un campo id (que ser&aacute; la clave primaria) y tambi&eacute;n es conveniente que tengan los campos create_at y updated_at, que son las fechas de creaci&oacute;n y modificaci&oacute;n respectivamente y que se actualizan automaticamente en los inserts y los updates.</p>
<p>Autom&aacute;ticamente tambi&eacute;n tenemos m&eacute;todos sin tener que definir nada:</p>
<pre class="code php">	$cars = Car::all(); // nos devuelve un array de objetos con todos los coches de la BBDD.
	$car = Car::find(1); // nos devuelve el coche con id=1
	$driver_name = $car-&gt;driver-&gt;name; // nos devuelve el nombre del conductor del coche anterior
	$car-&gt;price = 10000; // actualizamos el precio del coche.
	$car-&gt;save(); // Hacemos los cambios persistentes.
	$car-&gt;delete(); // Borramos el coche anterior.
	$cheapest_cars = Car::all(array('conditions' =&gt; 'price &lt; 10000')); // Buscamos los coches con un precio menor a 10000.
</pre>
<p>Como vemos en este ejemplo es muy sencillo trabajar con ActiveRecord. Tambi&eacute;n podemos hacer validaciones y muchas otras cosas, de forma muy sencilla.</p>
<p>Para utilizar esta implementaci&oacute;n es necesario disponer de la versi&oacute;n de PHP 5.3 como m&iacute;nimo. Utiliza namespaces por lo que es sencillo integrarla en tu aplicaci&oacute;n.</p>
<p>Hay muchos frameworks para PHP que tienen sus propias implementaciones del patr&oacute;n ActiveRecord o variaciones del mismo como Symfony, CodeIgniter, FuelPHP, ... aunque esta implementaci&oacute;n quiz&aacute;s sea la m&aacute;s fiel al patr&oacute;n y m&aacute;s similar a ruby on rails que hemos visto.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=126</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/el-patron-active-record-en-php.html</feedburner:origLink>
		</item>
				
		<item>
			<title>API de historial en Javascript</title>
			<link>http://www.imaginanet.com/blog/api-de-historial-en-javascript.html</link>
			<guid>http://www.imaginanet.com/blog/api-de-historial-en-javascript.html</guid>
			<comments>http://www.imaginanet.com/blog/api-de-historial-en-javascript.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue,  8 Jan 2013 20:14:17 +0100</pubDate>
					<category><![CDATA[HTML5]]></category>
					<category><![CDATA[Web 2.0]]></category>
					<category><![CDATA[JavaScript]]></category>
					<description><![CDATA[Actualmente est&aacute; disponible en los navegadores el API history para tratar los cambios en la URL sin tener que usar el engorroso hash, adem&aacute;s de facilitar la agregaci&oacute;n a favoritos.
Antes se ten&iacute;a que guardar el estado de la aplicaci&oacute;n en la url a partir del car&aacute;cter #, o relacionar el...]]></description>
			<content:encoded><![CDATA[><p>Actualmente est&aacute; disponible en los navegadores el <strong>API history</strong> para tratar los cambios en la URL sin tener que usar el engorroso hash, adem&aacute;s de facilitar la agregaci&oacute;n a favoritos.</p>
<p>Antes se ten&iacute;a que guardar el estado de la aplicaci&oacute;n en la url a partir del car&aacute;cter #, o relacionar el estado con alguna clave. Por ejemplo, si nuestra url actual era /app#01 y cambiabamos a /app#02, tendr&iacute;amos un objeto javascript  que guardar&iacute;a los datos de la aplicaci&oacute;n {'01': state1, '02': state2}, mediante el evento window.onhashchange coger&iacute;amos el estado correspondiente de window.location.hash</p>
<p>Con la nueva API tenemos history.pushState, que recibe 3 par&aacute;metros:</p>
<ul>
<li><strong>data</strong>: Un objecto que contiene el estado de nuestra aplicaci&oacute;n.</li>
<li><strong>title</strong>: El t&iacute;tulo del item que se muestra en el historial.</li>
<li><strong>url</strong> (opcional): La nueva url que cargamos y que se muestra en la barra de direcciones.</li>
</ul>
<p>Para tratar el historial tenemos:</p>
<pre class="code javascript js">window.addEventListener('popstate', function(event) {
	updateContent(event.state);
});

</pre>
<p>Con este c&oacute;digo le pasamos a una funci&oacute;n llamada updateContent los datos del estado de la aplicaci&oacute;n a trav&eacute;s de la propiedad del evento <strong>state</strong></p>
<p>Si queremos reemplazar los datos del estado actual, por ejemplo, porque el usuario a actualizado un formulario, y no queremos que se a&ntilde;ada un nuevo estado al historial, disponemos de <strong>history.replaceState</strong></p>
<pre class="code js javascript">// Guardamos el estado inicial de la aplicaci&oacute;n
history.replaceState(
	newstate,
	document.title, 
	document.location.href
);
</pre>
<p>Donde newstate es un objeto con los datos iniciales para nuestra aplicaci&oacute;n.</p>
<p>Todo el proceso es transparente al usuario ya que podr&iacute;a parecer que se est&aacute; cargando una p&aacute;gina nueva, en vez de actualizar contenido por ajax.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=125</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/api-de-historial-en-javascript.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Buenas prácticas para la creación de html para emails</title>
			<link>http://www.imaginanet.com/blog/buenas-practicas-para-la-creacion-de-html-para-emails.html</link>
			<guid>http://www.imaginanet.com/blog/buenas-practicas-para-la-creacion-de-html-para-emails.html</guid>
			<comments>http://www.imaginanet.com/blog/buenas-practicas-para-la-creacion-de-html-para-emails.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Sun, 25 Nov 2012 12:58:19 +0100</pubDate>
					<category><![CDATA[Correo Electrónico]]></category>
					<category><![CDATA[HTML5]]></category>
					<description><![CDATA[&iquest;Has creado html alguna vez para enviar en un email? &iquest;te ha vuelto loco alg&uacute;n cliente de email en particular no mostrando correctamente lo que pon&iacute;as? dejame adivinar... &iquest;empezaba por &lsquo;o&rsquo; dicho cliente? Bien vamos a intentar dar unas gu&iacute;as para que la pr&oacute;xima vez no sea...]]></description>
			<content:encoded><![CDATA[><p>&iquest;Has creado html alguna vez para enviar en un email? &iquest;te ha vuelto loco alg&uacute;n cliente de email en particular no mostrando correctamente lo que pon&iacute;as? dejame adivinar... &iquest;empezaba por &lsquo;o&rsquo; dicho cliente? Bien vamos a intentar dar unas gu&iacute;as para que la pr&oacute;xima vez no sea una pesadilla crear algo que se vea bien en todos los clientes.</p>
<p><strong>1)</strong> El doctype del documento es lo primero y de lo m&aacute;s importante, mi consejo es que utilices este:</p>
<pre class="code">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
</pre>
<p><strong>2)</strong> Imag&iacute;nate que las capas (divs) no existen y que volvemos a los inicios de html donde las tablas campan a sus anchas. La primera regla es pensar en tablas, todo el layout se construye con tablas.</p>
<p><strong>3)</strong> Especifica siempre la anchura y altura, esta s&oacute;lo cuando tu contenido vaya en altura fija, de la tabla (table) y celda (td). Las tablas siempre se definen con borde 0, espacio entre celdas 0 y padding entre celdas 0.</p>
<pre class="code">&lt;table border="0" cellpadding="0" cellspacing="0" width="686"&gt;
</pre>
<p><strong>4)</strong> Utiliza el alineado vertical de la celda para colocar los elementos interiores, donde normalmente pondremos valign=&rdquo;top&rdquo;</p>
<p><strong>5)</strong> No hagas una gran tabla. Separa elemento colocando nuevas tablas dentro de celdas de otras, como si de divs se tratasen.</p>
<p>Ejemplo simplificado sin atributos en los elementos:</p>
<pre class="code">&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;
    &lt;table&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
</pre>
<p><strong>6)</strong> Utiliza estilos en l&iacute;nea con el atributo style.</p>
<p><strong>7)</strong> Las im&aacute;genes siempre llevan borde 0 (as&iacute; evitaremos el borde azul si le ponemos un enlace) y display: block para evitar espacios del inline al final de la im&aacute;gen.</p>
<p><strong>8)</strong> Para texto utiliza divs con los tama&ntilde;os de fuente y paddings que quieras dar en los estilos en l&iacute;nea, y no olvides darle la anchura de sus contenedor:</p>
<p>Ejemplo:</p>
<pre class="code">&lt;div style="width: 514px; color: #FFFFFF; font-size: 13px; line-height: 15px; font-family: Arial; margin: 0; padding: 24px 30px 4px 30px;"&gt;Texto de prueba&lt;/div&gt;
</pre>
<p><strong>9)</strong> Para crear espacios utiliza una im&aacute;gen, es decir si necesitas crear una l&iacute;nea negra de 10px de altura en el interior de la celda coloca un spacer.gif (im&aacute;gen transparente de 1x1).</p>
<p><strong>10)</strong> Para dar color de fondo utiliza el atributo bgcolor de la celda.</p>
<p><strong>11)</strong> No uses color negro ni background negro, pues gmail no lo pinta, para ello utiliza 000001.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=124</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/buenas-practicas-para-la-creacion-de-html-para-emails.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Usar inline-block en Internet explorer 7 sin caer en el intento</title>
			<link>http://www.imaginanet.com/blog/usar-inline-block-en-internet-explorer-7-sin-caer-en-el-intento.html</link>
			<guid>http://www.imaginanet.com/blog/usar-inline-block-en-internet-explorer-7-sin-caer-en-el-intento.html</guid>
			<comments>http://www.imaginanet.com/blog/usar-inline-block-en-internet-explorer-7-sin-caer-en-el-intento.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Sun, 25 Nov 2012 12:47:43 +0100</pubDate>
					<category><![CDATA[CSS]]></category>
					<category><![CDATA[Internet Explorer]]></category>
					<description><![CDATA[Inline-block es un valor de la propiedad display cuya finalidad es hacer que el elemento seleccionado se comporte como un bloque y un elemento en l&iacute;nea. Digamos que es combinar display: inline con display: block. De esta forma nuestro elemento tendr&aacute; propiedades de bloque pero no provocar&aacute; un salto de...]]></description>
			<content:encoded><![CDATA[><p>Inline-block es un valor de la propiedad display cuya finalidad es hacer que el elemento seleccionado se comporte como un bloque y un elemento en l&iacute;nea. Digamos que es combinar display: inline con display: block. De esta forma nuestro elemento tendr&aacute; propiedades de bloque pero no provocar&aacute; un salto de l&iacute;nea, siempre y cuando entre en el flujo de bloques a dibujar, no superando el ancho disponible.</p>
<p>Si pensamos casos en los que utilizamos float, muchos de ellos se pueden hacer tambi&eacute;n con inline-block, pero por ejemplo imaginemos este c&oacute;digo:</p>
<pre class="code">&lt;h1&gt;&lt;img src=&rdquo;icono.png&rdquo; /&gt; &lt;p&gt;T&iacute;tulo&lt;/p&gt;&lt;/h1&gt;
</pre>
<p>En el navegador ver&iacute;amos: [icono.png]<br /> T&iacute;tulo</p>
<p>Y lo que queremos es que salgan al lado, sin salto de l&iacute;nea. Esto lo podr&iacute;amos solucionar cambiando la etiqueta &ldquo;p&rdquo; por un span o poni&eacute;ndole la propiedad display: inline. Pero supongamos que queremos utilizar inline-block por los motivos que consideremos. Entonces una buena pr&aacute;ctica ser&iacute;a crearnos una clase para ello:</p>
<pre class="code">.valign {
    display: inline-block;
    vertical-align: middle;
}
</pre>
<p>Con esta clase indicamos adem&aacute;s del inline-block, que el elemento se centre en altura en el medio del contenedor padre.</p>
<p>Ahora nuestro c&oacute;digo html quedar&iacute;a de la siguiente manera:</p>
<pre class="code">&lt;h1&gt;&lt;img src=&rdquo;icono.png&rdquo; class=&rdquo;valign&rdquo; /&gt;&lt;p class=&rdquo;valign&rdquo;&gt;T&iacute;tulo&lt;/p&gt;&lt;/h1&gt;
</pre>
<p>Si ejecutamos nuestro c&oacute;digo en internet explorer 7 veremos que no funciona, pero existe un truco que consiste en el siguiente c&oacute;digo:</p>
<pre class="code">.valign {
    display: inline;
    zoom: 1;
}
</pre>
<p>Este c&oacute;digo css es solo para internet explorer 7, o bien lo montamos en una hoja de estilos aparte para que se requiera cuando sea necesario o le aplicamos hacks a las propiedades para que solo explorer 7 las reconozca.</p>
<p>La idea de esta clase, nos evita gran trabajo al probar la web en explorer 7, dado que no tendremos que crear un fix para cada elemento con inline-block, pues como hemos visto con una sola clase lo solucionamos todo de forma r&aacute;pida.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=123</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/usar-inline-block-en-internet-explorer-7-sin-caer-en-el-intento.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Antipatrones de diseño</title>
			<link>http://www.imaginanet.com/blog/antipatrones-de-diseno.html</link>
			<guid>http://www.imaginanet.com/blog/antipatrones-de-diseno.html</guid>
			<comments>http://www.imaginanet.com/blog/antipatrones-de-diseno.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Thu, 15 Nov 2012 09:53:27 +0100</pubDate>
					<category><![CDATA[Patrones]]></category>
					<description><![CDATA[&iquest;Qu&eacute; es un patr&oacute;n de dise&ntilde;o?
Antes de comenzar este art&iacute;culo tenemos que hacer una menci&oacute;n a los patrones de dise&ntilde;o. Estos son soluciones recurrentes a problemas conocidos, definidos mediante 3 partes

Contexto: Representa el cu&aacute;ndo se produce el problema
Problema: Representa...]]></description>
			<content:encoded><![CDATA[><h2>&iquest;Qu&eacute; es un patr&oacute;n de dise&ntilde;o?</h2>
<p>Antes de comenzar este art&iacute;culo tenemos que hacer una menci&oacute;n a los patrones de dise&ntilde;o. Estos son soluciones recurrentes a problemas conocidos, definidos mediante 3 partes</p>
<ul>
<li><strong>Contexto: </strong>Representa el <strong>cu&aacute;ndo</strong> se produce el problema</li>
<li><strong>Problema: </strong>Representa el <strong>qu&eacute;</strong>, es decir, el problema que soluciona</li>
<li><strong>Soluci&oacute;n: </strong>Representa el <strong>c&oacute;mo</strong> solucionar nuestro problema</li>
</ul>
<p>Los patrones de dise&ntilde;o se clasifican en distintos grupos. Tenemos patrones de arquitectura, de dise&ntilde;o y de dialecto, dependiendo el tipo de problema que queremos resolver</p>
<p>Estos patrones obtuvieron gran popularidad a partir de la publicaci&oacute;n del libro Design Patterns escrito por el grupo <a href="http://es.wikipedia.org/wiki/Gang_of_Four_(dise%C3%B1o)" target="_blank">Gang of Four</a> y bien utilizados aportan mucha calidad a nuestros productos.</p>
<p>Como no es objetivo de este art&iacute;culo profundizar mucho en el tema, os recomendamos si teneis curiosidad en consultar el siguiente documento<br /> <a href="http://msdn.microsoft.com/es-es/library/bb972242.aspx#XSLTsection124121120120" target="_blank"> http://msdn.microsoft.com/es-es/library/bb972242.aspx#XSLTsection124121120120 </a></p>
<h2>&iquest;Y un antripatr&oacute;n de dise&ntilde;o?</h2>
<p>Tenemos que tener claro que LOS PATRONES DE DISE&Ntilde;O NO SON PERFECTOS. Aunque realmente el problema est&aacute; en la gente que los usa, pues a veces tendemos a tratarlos como verdades universales.</p>
<p>El uso indiscriminado de los patrones de Software, a&uacute;n cuando el uso de ellos no aporta ning&uacute;n valor a su desarrollo, se conoce como Pattern Happy, que define a programadores que aprenden un patr&oacute;n y r&aacute;pidamente encuentran un lugar donde abusar de &eacute;l.</p>
<blockquote><em>&iquest;Has aprendido alguna vez alg&uacute;n patr&oacute;n de software y quisiste usarlo en ese mismo momento, porque te gust&oacute;? &iquest;Mucho? Entonces eres un amante de los patrones. Los patrones no son siempre la soluci&oacute;n adecuada o mejor para un problema.</em></blockquote>
<p>Los antipatrones son soluciones negativas que presentan m&aacute;s problemas que beneficios. Es importante comprender bien estos antipatrones para conseguir identificarlos y evitarlos cuanto antes.</p>
<p>Los antipatrones de dise&ntilde;o suelen tener nombres graciosos y son detallados  con mucho cinismo, lo cual es bueno porque los hace f&aacute;cil de recordar.</p>
<p>Los antipatrones de dise&ntilde;o se clasifican en tres grandes grupos</p>
<ul>
<li>Desarrollo de Software</li>
<li>Arquitectura de Software</li>
<li>Gesti&oacute;n de Proyectos de Software</li>
</ul>
<p>A continuaci&oacute;n mostramos una relaci&oacute;n de sus nombres originales</p>
<table>
<thead> 
<tr>
<th>Desarrollo de software</th> <th>Arquitectura</th> <th>Gesti&oacute;n</th>
</tr>
</thead> 
<tbody>
<tr>
<td>
<ul>
<li>The Blob</li>
<li>Lava Flow</li>
<li>Functional Decomposition</li>
<li>Poltergeists</li>
<li>Golden Hammer</li>
<li>Spaghetti Code</li>
<li>Cut and Paste Programming</li>
<li>Continuous Obsolescence</li>
<li>Ambiguous Viewpoint</li>
<li>Boat Anchor</li>
<li>Dead End</li>
<li>Input Kludge</li>
<li>Walking through a Minefield</li>
<li>Mushroom Management</li>
</ul>
</td>
<td>
<ul>
<li>Stovepipe Enterprise</li>
<li>Vendor Lock-in</li>
<li>Architecture by Implication</li>
<li>Design by Committee</li>
<li>Reinvent the Wheel</li>
<li>Autogenerated Stovepipe</li>
<li>Jumble</li>
<li>Cover your Assets</li>
<li>Wolf Ticket</li>
<li>Warm Bodies</li>
<li>Swiss Army Knife</li>
<li>The Grand Old Duke of York</li>
</ul>
</td>
<td>
<ul>
<li>Analysis Paralysis</li>
<li>Death by Planning</li>
<li>Corncob</li>
<li>Irrational Management</li>
<li>Project Missmanagement</li>
<li>Blowhard Jamboree</li>
<li>Viewgraph Engineering</li>
<li>Fear of Success</li>
<li>Intellectual Violence</li>
<li>Smoke and Mirrors</li>
<li>Throw it over the wall</li>
<li>Fire Drill</li>
<li>The Feud</li>
<li>E-Mail is Dangerous</li>
</ul>
</td>
</tr>
</tbody>
</table>
<h2>Caso concreto. The BLOB. El terror no tiene forma</h2>
<p>Este antipatr&oacute;n de dise&ntilde;o hace referencia a un <strong>objeto todopoderoso que tiene un exceso de responsabilidad y crece de manera descontrolada</strong>. Si nos basamos en el <a href="http://en.wikipedia.org/wiki/Single_responsibility_principle" target="_blank">principio de &uacute;nica responsabilidad</a> este objeto tiene el problema de que se encarga de muchas tareas distintas y el sistema depende completamente de &eacute;l.</p>
<p>Los problemas que aporta este objeto son</p>
<ul>
<li>El objeto es dificil de testear</li>
<li>El objeto no es reusable</li>
<li>El objeto no es f&aacute;cil de hacer cambios</li>
<li>No es un enfoque orientado a objeto, sino un falso enfoque prodedimental.</li>
</ul>
<p>Los objetos BLOG (tambi&eacute;n conocidos a veces GOD Object u objetos todopoderosos) se identifican cuando tienes objetos con muchos atributos y operaciones o cuando existen atributos que no tienen una conexi&oacute;n l&oacute;gica o falta de cohesi&oacute;n.</p>
<p>La soluci&oacute;n para eliminar estos objetos de nuestro sistema es la Refactorizaci&oacute;n localizando grupos de atributos y responsabilidades y agrup&aacute;ndolos en objetos distintos, estableciendo de forma correcta la relaci&oacute;n entre clases.</p>
<h2>Referencia</h2>
<ul>
<li><a href="http://es.wikipedia.org/wiki/Patr%C3%B3n_de_dise%C3%B1o" target="_blank">http://es.wikipedia.org/wiki/Patr%C3%B3n_de_dise%C3%B1o</a></li>
<li><a href="http://www.cristalab.com/tutoriales/antipatrones-god-object-en-patrones-de-diseno-orientado-a-objetos-c101018l/" target="_blank">http://www.cristalab.com/tutoriales/antipatrones-god-object-en-patrones-de-diseno-orientado-a-objetos-c101018l/</a></li>
<li><a href="http://santimacnet.wordpress.com/2010/05/29/patrones-y-antipatrones-de-diseno/" target="_blank">http://santimacnet.wordpress.com/2010/05/29/patrones-y-antipatrones-de-diseno/</a></li>
<li><a href="http://msdn.microsoft.com/es-es/library/bb972251.aspx#EDAA" target="_blank">http://msdn.microsoft.com/es-es/library/bb972251.aspx#EDAA</a></li>
<li><a href="http://en.wikipedia.org/wiki/Single_responsibility_principle" target="_blank">http://en.wikipedia.org/wiki/Single_responsibility_principle</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=122</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/antipatrones-de-diseno.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Videoconferencia en aplicaciones HTML5</title>
			<link>http://www.imaginanet.com/blog/videoconferencia-en-aplicaciones-html5.html</link>
			<guid>http://www.imaginanet.com/blog/videoconferencia-en-aplicaciones-html5.html</guid>
			<comments>http://www.imaginanet.com/blog/videoconferencia-en-aplicaciones-html5.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue,  6 Nov 2012 16:34:44 +0100</pubDate>
					<category><![CDATA[HTML5]]></category>
					<category><![CDATA[Flash]]></category>
					<category><![CDATA[PHP]]></category>
					<category><![CDATA[jQuery]]></category>
					<description><![CDATA[OpenTok es una librer&iacute;a Open Source con la que podemos integrar videoconferencia en nuestras aplicaciones web HTML 5 y apps para Android e iOS de una manera relativamente sencilla pudiendo crear salas con m&uacute;ltiples participantes simult&aacute;neamente con el requisito de tener conexi&oacute;n a Internet, una webcam y...]]></description>
			<content:encoded><![CDATA[><p>OpenTok es una librer&iacute;a Open Source con la que podemos integrar videoconferencia en nuestras aplicaciones web HTML 5 y apps para Android e iOS de una manera relativamente sencilla pudiendo crear salas con m&uacute;ltiples participantes simult&aacute;neamente con el requisito de tener conexi&oacute;n a Internet, una webcam y un micr&oacute;fono.</p>
<p>Los usos de estas aplicaciones HTML 5 de videoconferencia a medida son m&uacute;ltiples, algunos ejemplos ser&iacute;an:</p>
<ul>
<li><a href="http://www.imaginanet.com/aplicaciones-web-de-atencion-al-cliente.html">Integrar servicios de atenci&oacute;n al cliente / helpdesk</a></li>
<li><a href="http://www.imaginanet.com/aplicaciones-para-el-equipo-comercial.html">Venta de productos y demostraciones online</a></li>
<li>Aplicaciones de v&iacute;deochat</li>
<li>Consultas entre profesionales como abogados, arquitectos, m&eacute;dicos, investigadores, etc.</li>
<li>Impartici&oacute;n de cursos y material did&aacute;ctico en directo.</li>
<li>Streaming de v&iacute;deo en directo de eventos</li>
</ul>
<p>Seg&uacute;n vayamos a realizar uso del API de OpenTok, podr&aacute; ser de uso gratuito o tendr&aacute; limitaciones pudiendo llegar a ser de pago en caso de excesiva carga (<a href="http://www.tokbox.com/opentok/api/pricing" target="_blank">m&aacute;s informaci&oacute;n sobre las tarifas</a>).</p>
<p>En los siguientes ejemplos, nos basaremos en los ejemplos oficiales a&ntilde;adi&eacute;ndoles c&oacute;digo PHP y base de datos para que el intercambio de informaci&oacute;n entre cada cliente sea transparente</p>
<h3>Credenciales OpenTok como aplicaci&oacute;n de videoconferencia</h3>
<p>En primer lugar, deberemos registrarnos como &nbsp;desarrolladores de Open Tok. &Eacute;sto nos proporcionar&aacute; en nuestro correo electr&oacute;nico una clave secreta que controlar&aacute; el uso que hacemos del servicio de video conferencia.<br />Nos podemos registrar en Open Tok desde <a href="http://www.tokbox.com/opentok/api/documentation/gettingstarted" target="_blank">&eacute;ste enlace</a>.</p>
<h3>Videoconferencia en aplicaciones HTML 5, jQuery y PHP</h3>
<p>Para intercambiar informaci&oacute;n entre usuarios, haremos uso de PHP y base de datos. En primer lugar, PHP crear&aacute; una sesi&oacute;n y la guardaremos en base de datos (o cualquier otra manera que prefiramos).<br />En segundo lugar, todos los clientes que deban conectarse a dicha sesi&oacute;n, obtendr&aacute; la informaci&oacute;n para estar todos en la misma sala.<br /><br />1.- Descargaremos el <strong><a href="https://github.com/opentok/Opentok-PHP-SDK" target="_blank">API de desarrollo OpenTok para PHP</a></strong> descargando los archivos en una carpeta llamada OpenTok:</p>
<ul>
<li>OpenTok/API_Config.php</li>
<li>OpenTok/OpenTokArchive.php</li>
<li>OpenTok/OpenTokSDK.php</li>
<li>OpenTok/OpenTokSession.php</li>
</ul>
<p>2.- Configuraremos nuestras <strong>credenciales OpenTok</strong> en el archivo API_Config.php</p>
<pre class="code php">class API_Config { &nbsp; &nbsp;
   // Replace this value with your TokBox API Partner Key
   const API_KEY = "!!!!!!!!!!!!!!"; &nbsp; &nbsp;&nbsp;
   // Replace this value with your TokBox API Partner Secret
   const API_SECRET = "#############"; &nbsp; &nbsp;&nbsp;
   const API_SERVER = "https://api.opentok.com/hl";
}
</pre>
<p>3.-<strong> El primer usuario crear&aacute; la sesi&oacute;n de videoconferencia</strong> y su respectivo token, guard&aacute;ndolo en base de datos:</p>
<pre class="code php">&lt;?php

require("OpenTok/API_Config.php");
require("OpenTok/OpenTokArchive.php");
require("OpenTok/OpenTokSDK.php");
require("OpenTok/OpenTokSession.php");
$apiObj = new OpenTokSDK (API_Config::API_KEY, API_Config::API_SECRET) ;
// Configuramos el objeto
$session = $apiObj -&gt; create_session() ;
$sessionId = $session -&gt; getSessionId() ;
$token = $apiObj -&gt; generate_token($sessionId) ;

?&gt;
</pre>
<p>Insertaremos las variables <em>$sessionId</em> y <em>$token</em> en base de datos.&nbsp;&Eacute;sto nos servir&aacute; para que dos usuarios se intercambien entre ellos la informaci&oacute;n necesaria para que la videoconferencia sea totalmente transparente.</p>
<p>Lo m&aacute;s interesante, es crear una aplicaci&oacute;n web que ponga en contacto a varios usuarios entre s&iacute; de manera privada mediante alg&uacute;n mecanismo tipo sala de chat, citas, etc.</p>
<p>4.- Despu&eacute;s de que el primer usuario cree la sesi&oacute;n, <strong>se crear&aacute; la interfaz</strong>. De igual manera, los siguientes usuarios se conectar&aacute;n con los datos guardados en base de datos (el c&oacute;digo es com&uacute;n para todos los clientes):</p>
<pre class="code">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Videoconferencia en HTML 5&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;!-- jQuery --&gt;
&lt;script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"&gt;&lt;/script&gt;
&lt;!-- Opentok --&gt;
&lt;script src="http://static.opentok.com/v0.91/js/TB.min.js"&gt;&lt;/script&gt;
&lt;!-- Sesi&oacute;n --&gt;
&lt;script type="text/javascript"&gt;
   var apiKey = '&lt;?=API_Config::API_KEY?&gt;';
   var sessionId = '&lt;?=$sessionId?&gt;';
   var token = '&lt;?=$token?&gt;';
   TB.setLogLevel(TB.DEBUG);
   var session = TB.initSession(sessionId);
   session.addEventListener('sessionConnected', sessionConnectedHandler);
   session.addEventListener('streamCreated', streamCreatedHandler);
   session.connect(apiKey, token);
   var publisher;
   function sessionConnectedHandler(event) {
      var publishProps = {height:120, width:161};
      publisher = TB.initPublisher(apiKey, 'TokVideoStreamUsuario', publishProps);
      session.publish(publisher);
      subscribeToStreams(event.streams);
   }
   function streamCreatedHandler(event) {
      subscribeToStreams(event.streams);
   }
   function subscribeToStreams(streams) {
      for (var i = 0; i &lt; streams.length; i++) {
         if (streams[i].connection.connectionId == session.connection.connectionId) {
            return;
         }
         var divid = 'stream' + streams[i].streamId;
         $("#TokVideoStreamOtrosUsuarios").html("&lt;div id='stream"+streams[i].streamId+"'&gt;&lt;/div&gt;");
         var publishProps = {height:361, width:482};
         session.subscribe(streams[i], divid);
      }
   }
&lt;/script&gt;
&lt;!-- Como me ven a mi otros usuarios --&gt;
&lt;div id="TokVideoStreamUsuario"&gt;&lt;/div&gt;
&lt;br/&gt;&lt;br/&gt;
&lt;!-- Vista de otros usuarios --&gt;
&lt;div id="TokVideoStreamOtrosUsuarios"&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;html&gt;
</pre>
<p>El comportamiento ser&aacute; mostrar en un Flash peque&ntilde;o nuestra vista, y luego en grande los usuarios conectados. Conforme se conecten otros usuarios se ir&aacute;n a&ntilde;adiendo otros marcos Flash con los usuarios conectados.</p>
<h3>Videoconferencia en apps Android / iOS</h3>
<p>En este ejemplo se ha hecho uso de Flash, lo cu&aacute;l no es compatible con las apps, por lo que para dichas plataformas deberemos hacer uso de la versi&oacute;n nativa del SDK de OpenTok.</p>
<h3>P&aacute;ginas relacionadas</h3>
<ul>
<li><a href="http://www.imaginanet.com/blog/streaming-de-video-h264-desde-un-navegador-web-con-wowza.html">Streaming de v&iacute;deo en directo</a></li>
<li><a href="http://www.tokbox.com/opentok/api/tools/documentation/api/server_side_libraries.html" target="_blank">OpenTok Server Side libraries</a></li>
<li><a href="http://www.tokbox.com/opentok/api/documentation" target="_blank">OpenTok documentaci&oacute;n general</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=121</wfw:commentRss>
			<slash:comments>4</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/videoconferencia-en-aplicaciones-html5.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Gestionar las dependencias con Composer</title>
			<link>http://www.imaginanet.com/blog/gestionar-las-dependencias-con-composer.html</link>
			<guid>http://www.imaginanet.com/blog/gestionar-las-dependencias-con-composer.html</guid>
			<comments>http://www.imaginanet.com/blog/gestionar-las-dependencias-con-composer.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Thu, 25 Oct 2012 10:24:29 +0100</pubDate>
					<category><![CDATA[PHP]]></category>
					<description><![CDATA[Casi sin darnos cuenta ha habido una enorme revoluci&oacute;n en el uso de PHP, el cual ha sido posible gracias  a la incorporaci&oacute;n de los espacios de nombres. R&aacute;pidamente tras esto surgi&oacute; una herramienta de gesti&oacute;n de  dependencias llamada Composer para fomentar la interoperabilidad entre los...]]></description>
			<content:encoded><![CDATA[><p>Casi sin darnos cuenta ha habido una enorme revoluci&oacute;n en el uso de PHP, el cual ha sido posible gracias  a la incorporaci&oacute;n de los espacios de nombres. R&aacute;pidamente tras esto surgi&oacute; una herramienta de gesti&oacute;n de  dependencias llamada Composer para <strong>fomentar la interoperabilidad entre los desarrolles.</strong></p>
<p><strong>Composer es un gestor de dependencias. </strong>Esta idea no es nueva, pues est&aacute; inspirado en otras herramientas  de otros lenguajes como npm o bundler.</p>
<p>Gracias a esta herramienta <strong>vamos a ser capaces de establecer las dependencias y requerimientos de una  aplicaci&oacute;n</strong> o <strong>publicar paquetes generados por nosotros. </strong></p>
<p>Esto se hace necesario por los enormes problemas que hay ahora mismo para la interoperabilidad y cooperaci&oacute;n  entre frameworks, ya que cada uno nos ofrec&iacute;a soluciones para lo mismo. Gracias a <strong>interfaces comunes</strong> y a  <strong>gestionar las dependencias</strong> de forma sencilla se est&aacute; llegando a este consenso y est&aacute;n brotando grupos de  interoperabilidad.</p>
<h2>C&oacute;mo se usa</h2>
<p>Como desarrolladores tendremos un fichero en nuestros proyectos llamado <strong>composer.json</strong> donde estableceremos las  dependencias de una forma parecida a esta:</p>
<pre class="code">{
    "require": {
        "monolog/monolog": "1.0.0"
    }
}
</pre>
<p>De esta forma le estamos diciendo a nuestra aplicaci&oacute;n que requerimos la librer&iacute;a <a href="https://github.com/Seldaek/monolog" target="_blank">monolog</a>. M&aacute;s a&uacute;n,  le estamos diciendo que necesitamos exactamente la versi&oacute;n 1.0.0. por lo que aunque salgan versiones  m&aacute;s modernas de esta rama, no las necesito.</p>
<p>Aqu&iacute; tenemos la informaci&oacute;n de c&oacute;mo podemos realizar el proceso de instalar / actualizar nuestras dependencias <a href="http://getcomposer.org/doc/00-intro.md">http://getcomposer.org/doc/00-intro.md</a></p>
<h2>Reinventar la rueda</h2>
<p>Este es un problema muy grande que existe en el desarrollo de software actual, y una de las causas es de  no tener la facilidad de publicar nuestras librer&iacute;as y poder necesitar las publicadas por otros de  forma f&aacute;cil.</p>
<p><strong>Composer es la soluci&oacute;n a un problema que no consigui&oacute; resolver PEAR</strong>. En parte porque &eacute;ste no consegu&iacute;a  resolver el problema (o no de forma f&aacute;cil) de tener instalada en la misma m&aacute;quina diferentes  versiones de una librer&iacute;a, ya que pod&iacute;as tener proyectos que dependieran de ambas.</p>
<p>Tambi&eacute;n el problema es que las dependencias no se hac&iacute;an expl&iacute;citas de ninguna manera.</p>
<p>Otra diferencia notable, es que no es necesario un proceso de aprobaci&oacute;n para que te incluyan tu paquete en el repositorio de Packagist.</p>
<h2>Ventajas</h2>
<p>Este es un resumen de las ventajas de utilizar esta aplicaci&oacute;n</p>
<ul>
<li>Puedes indicar exactamente qu&eacute; necesitas y en qu&eacute; rama de desarrollo.</li>
<li>Fomentar el uso de est&aacute;ndares. </li>
<li>Puedes utilizar paquetes de PEAR</li>
<li>Existe un repositorio p&uacute;blico</li>
<li>Puedes instalar un repositorio privado</li>
<li>Podemos establecer procedimientos o llamadas de funciones que se ejecutar&aacute;n despu&eacute;s de realizar operaciones (actualizaci&oacute;n, borrado, &hellip;)</li>
</ul>
<h2>Referencias</h2>
<ul>
<li><a href="http://getcomposer.org/" target="_blank">http://getcomposer.org/</a></li>
<li><a href="https://packagist.org/" target="_blank">https://packagist.org/</a></li>
<li><a href="http://desymfony.com/ponencia/composer" target="_blank">http://desymfony.com/ponencia/composer</a></li>
<li><a href="http://nelm.io/blog/2011/12/composer-part-1-what-why/" target="_blank">http://nelm.io/blog/2011/12/composer-part-1-what-why/</a></li>
<li><a href="http://nelm.io/blog/2011/12/composer-part-2-impact/" target="_blank">http://nelm.io/blog/2011/12/composer-part-2-impact/</a></li>
<li><a href="http://symfony.com/doc/current/components/index.html" target="_blank">http://symfony.com/doc/current/components/index.html</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=120</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/gestionar-las-dependencias-con-composer.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Preprocesar hojas de estilo con LESS</title>
			<link>http://www.imaginanet.com/blog/preprocesar-hojas-de-estilo-con-less.html</link>
			<guid>http://www.imaginanet.com/blog/preprocesar-hojas-de-estilo-con-less.html</guid>
			<comments>http://www.imaginanet.com/blog/preprocesar-hojas-de-estilo-con-less.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 22 Oct 2012 13:55:43 +0100</pubDate>
					<category><![CDATA[CSS]]></category>
					<category><![CDATA[PHP]]></category>
					<category><![CDATA[Web 2.0]]></category>
					<category><![CDATA[JavaScript]]></category>
					<description><![CDATA[LESS es una extensi&oacute;n de CSS
&iquest;Qu&eacute; significa esto? Que un documento CSS es un documento LESS v&aacute;lido.    Esto nos va a permitir seguir trabajando con nuestras hojas de estilo de manera natural y    hacer que adaptarnos a LESS sea f&aacute;cil y ameno.
&iquest;C&oacute;mo extiende LESS a CSS?

Permite el...]]></description>
			<content:encoded><![CDATA[><h3>LESS es una extensi&oacute;n de CSS</h3>
<p>&iquest;Qu&eacute; significa esto? Que un documento CSS es un documento LESS v&aacute;lido.    Esto nos va a permitir seguir trabajando con nuestras hojas de estilo de manera natural y    hacer que adaptarnos a LESS sea f&aacute;cil y ameno.</p>
<p><strong>&iquest;C&oacute;mo extiende LESS a CSS?</strong></p>
<ul>
<li><a href="http://lesscss.org/#-variables">Permite el uso de variables</a>. As&iacute;, podemos reaprovechar conceptos de colores, rutas. Incluso podemos componer variables con informaci&oacute;n del proceso que se realiza en el servidor o el tama&ntilde;o de pantalla accediendo a Javascript (Esto depende un poco de c&oacute;mo utilicemos LESS, que se explicar&aacute; m&aacute;s adelante)</li>
<li><a href="http://lesscss.org/#-mixins">Mixin</a>. El concepto de MIXIN puede ser familiar al de las clases de objetos. Con los MIXINs podemos encapsular funcionalidad. La mayor importancia de esto es que podemos resumir las pesadas reglas de los distintos navegadores en una sola parametrizable. &iexcl;Nunca m&aacute;s habr&aacute; que poner -webkit-, -moz-, -ms-, -o, &hellip;!</li>
<li><a href="http://lesscss.org/#-operations">Funciones</a>. Con el uso de funciones podemos realizar operaciones sobre los colores, tama&ntilde;os, paddings, etc. Incluso LESS viene de serie con funciones para tratar colores, pudiendo saturar, cambiar la intensidad o incluso calcular el color contrario de uno dado.</li>
<li><a href="http://lesscss.org/#-importing">Importaciones</a>: Esto nos aporta mucha modularidad en nuestras hojas de estilo, ya que podemos empezar a funcionar como si tuvi&eacute;ramos paquetes independientes que podemos reutilizar en nuestros proyectos. </li>
<li><a href="http://lesscss.org/#-nested-rules">Reglas encadenadas</a>: &nbsp;Nos permite agrupar funcionalidad en la misma regla, evitando tener que ser tan &ldquo;verbosos&rdquo; en nuestras hojas de estilo cuando tratamos elementos que est&aacute;n dentro de otros.</li>
</ul>
<h1 dir="ltr">Maneras de implantarlo</h1>
<p>La versi&oacute;n de LESS incluye el compilador en versi&oacute;n Javascript. Esto tiene ventajas e    inconvenientes. Lo importante es que el procesado lo realiza el cliente: Evita al servidor de realizar una tarea tediosa pero por otra obliga al cliente,    haciendo que la p&aacute;gina tarde m&aacute;s en cargar y oblig&aacute;ndole a tener que tener Javascript para poder ver la hoja de estilos.</p>
<p>Existen otras alternativas de procesar estas hojas de estilo. Algunas de ellas es NODE, Ruby o PHP.</p>
<p>Con PHP, combinando la generaci&oacute;n de estas hojas de estilo con un simple sistema de CACHE podemos    aprovecharnos de todas estas ventajas.</p>
<p>Aqu&iacute; vamos a mostrar una idea b&aacute;sica de hacerlo desde PHP con la librer&iacute;a    <a href="http://leafo.net/lessphp/">LESSPHP</a></p>
<pre class="code">&lt;?php
// Incluimos las clases necesarias
require 'vendor/autoload.php' ;

// Plantillas que queremos procesar
$ficheros = array ('style/less/style.less', 'style/less/fondo.less') ;
$less = new lessc ();


// Para cada fichero
foreach ($ficheros as $fichero)
{
  // Carga la cache
  $cacheFile = $fichero . '.cache';
  $destFile = $fichero . '.css';

  if (file_exists ($cacheFile))
  {
    $cache = unserialize (file_get_contents ($cacheFile)) ;
  }
  else
  {
    $cache = $fichero ;
  }

  try
  {
    $newCache = $less -&gt; cachedCompile ($cache);
  }
  catch (Exception $e)
  {
    die ('Error ' . $e -&gt; getMessage ()) ;
  }
 

  if (! is_array ($cache) || $newCache['updated'] &gt; $cache['updated'])
  {
    file_put_contents ($cacheFile, serialize ($newCache));
    file_put_contents ($destFile, $newCache ['compiled']);
  }
}

// Plantilla
include ('test.html') ;
</pre>
<h2>Desventajas o pegas</h2>
<p>El uso de LESS dependiendo del cliente no me parece una idea correcta pues estamos forzando requerimientos. Con esto har&iacute;amos que un cliente sin soporte    javascript activado no cargara correctamente las hojas de estilo.</p>
<p>Tambi&eacute;n <strong>creo ue es mucho m&aacute;s versatil que podamos manejar nosotros mismos la cache</strong> ya que podemos dise&ntilde;ar estrategias de producci&oacute;n y desarrollo mejor adaptadas a    nuestras necesidades.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=119</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/preprocesar-hojas-de-estilo-con-less.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Inyección de dependencias</title>
			<link>http://www.imaginanet.com/blog/inyeccion-de-dependencias.html</link>
			<guid>http://www.imaginanet.com/blog/inyeccion-de-dependencias.html</guid>
			<comments>http://www.imaginanet.com/blog/inyeccion-de-dependencias.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue, 16 Oct 2012 10:01:20 +0100</pubDate>
					<category><![CDATA[Patrones]]></category>
					<category><![CDATA[PHP]]></category>
					<description><![CDATA[Inversi&oacute;n de Control
Para abordar este tema es necesario en primer lugar que hagamos referencia al t&eacute;rmino  de Inversi&oacute;n de Control.
Para entenderlo, hay un t&oacute;pico bastante famoso que nos indica que el funcionamiento    de esto es parecido a como se trabaja en Hollywood (Principio de Hollywood)    con...]]></description>
			<content:encoded><![CDATA[><h2 dir="ltr">Inversi&oacute;n de Control</h2>
<p>Para abordar este tema es necesario en primer lugar que hagamos referencia al t&eacute;rmino  de <strong>Inversi&oacute;n de Control</strong>.</p>
<p>Para entenderlo, hay un t&oacute;pico bastante famoso que nos indica que el funcionamiento    de esto es parecido a como se trabaja en Hollywood (<em>Principio de Hollywood</em>)    con los actores noveles. &ldquo;<em>No nos llames, nosotros te llamaremos</em>&rdquo;.    Es decir, ser&aacute;n las clases mismas las que se encargar&aacute;n de pedir los objetos    necesarios.</p>
<p>Teniendo esto en mente, podemos entender la <strong>inversi&oacute;n de control</strong> como    el proceso donde los objetos son suministrados a las clases que los necesitan, en lugar    de crearlos ellos mismos.</p>
<p>Imaginemos que tenemos una clase Newsletter que    necesita enviar correos.</p>
<p>Lo normal, como hasta ahora, podr&iacute;a ser algo como esto:</p>
<pre class="code">&lt;?php
class Newsletter {
  protected $mail ;
  function __construct() {
    $this -&gt; mail = New Mailer ('correo@gmail.com', ...) ;
  }
}
</pre>
<p>Pero esto encierra muchos m&aacute;s problemas de lo que parece a simple vista.  Estamos creando una dependencia muy fuerte entre la clase Newsletter y la clase Mail.</p>
<p>&iquest;Qu&eacute; ocurrir&iacute;a si necesitamos utilizar otro objeto Mailer? &iquest;Y si nos  cambia el usuario y la contrase&ntilde;a? &iquest;Tenemos que cambiarlo en cada sitio? &iquest;Y s&iacute;  en algunas clases tenemos que utilizar el objeto Mailer configurado de una forma y en otras  de otro?</p>
<p>Una posible soluci&oacute;n propuesta por la Inversi&oacute;n de Control es esta:</p>
<pre class="code">&lt;?php
class Newsletter {
  protected $mail ;
  function __construct() {
    $this -&gt; mail = $mail ;
  }
}
</pre>
<p>Lo que hemos hecho, es pasarle un objeto completamente configurado y  preparado para enviar correos eliminando esa fuerte dependencia que exist&iacute;a  entre las dos clases.</p>
<p>Ahora mismo estar&aacute;s pensando que el problema no est&aacute; solucionado    todav&iacute;a, que todav&iacute;a has tenido que crear ese objeto Mail,    configurarlo a mano y pas&aacute;rselo a cada objeto que lo requiera. &iexcl;Vamos paso a paso!</p>
<h2>Inyecci&oacute;n de dependencias</h2>
<p>La inyecci&oacute;n de dependencias es una forma de Inversi&oacute;n de Control.    En el ejemplo anterior hemos visto una posible forma de implementar este patr&oacute;n    de dise&ntilde;o. Vamos a ver ahora ahora una alternativa a esta:</p>
<pre class="code">&lt;?php
class Newsletter {
  protected $mail ;
  public function setMailer (Mailer $mail) {
    $this -&gt; mail = $mail ;
  }
  
  public function getMailer () {
    return $this -&gt; mail ;
  }
}
</pre>
<p>Vemos que la diferencia radica en la forma en que pasamos los objetos. En un  caso se los hemos pasado por el constructor y en otros casos se los hemos pasado  utilizando m&eacute;todos SET / GET.</p>
<p>El primer m&eacute;todo es el adecuado cuando tenemos que suministrar dependencias    que son obligatorias para la clase y el segundo m&eacute;todo es el correcto para    incluir dependencias opcionales.</p>
<h2>Uso de interfaces para definir las dependencias</h2>
<p>El siguiente paso para conseguir desacoplar nuestras clases lo conseguimos    definiendo interfaces.</p>
<p>Previamente, cuando necesitamos inyectar un objeto, lo hemos realizado indicando el    tipo de objeto necesario</p>
<pre class="code">public function setMailer (Mailer $mail)
</pre>
<p>De forma que tenemos la tranquilidad de saber que nos pasaran un objeto de esa    clase. Pero eso no es muy flexible tampoco, ya que estamos forzando a crear    una dependencia demasiado fuerte.</p>
<p>Lo que podemos hacer es crear una interfaz, que defina las operaciones que tienen    que tener nuestros objetos que sirva para enviar correos (Pongamos por ejemplo,    un m&eacute;todo llamado <em>send</em>)</p>
<pre class="code">  public function setMailer (MailInterface $mail)
</pre>
<p>De esta forma tenemos la dependencia fijada de forma mucho m&aacute;s desacoplada    pues nos permitir&aacute; de forma muy r&aacute;pida cambiar de un objeto a otro,    siempre que cumpla con esa interfaz.</p>
<h2>Contenedor de dependencias</h2>
<p>El problema que todav&iacute;a nos queda es que, fuera de los objetos, tenemos que ir construyendo    las dependencias a mano, e ir pas&aacute;ndoselas una a una. Necesitamos centralizar el proceso de    crear estas dependencias utilizando un contenedor de dependencias.</p>
<p>Una implementaci&oacute;n sencilla de este concepto tendr&iacute;a m&eacute;todos para    obtener objetos de tipo MAIL, sobre demanda.</p>
<pre class="code">&lt;?php
class ContenedorDeDependencias {
  public static function getMailer () {
    return new Mailer ('correo@gmail.com', ...) ;
  }
}
</pre>
<p>Partiendo de este concepto tan b&aacute;sico podemos construirnos un contenedor de    dependencias que lea los par&aacute;metros de configuraci&oacute;n de un fichero    externo, que ponga en cach&eacute; los objetos creados de forma que no tenga que    crear los objetos varias veces si son varios clientes los que se lo piden.</p>
<p>Existen componentes completamente terminados y desacoplados que ofrecen esta    funcionalidad y mucha m&aacute;s. Aqu&iacute; tenemos el componente de    <strong>Inyecci&oacute;n de Dependencias de Symfony.</strong> <a href="https://github.com/symfony/DependencyInjection">https://github.com/symfony/DependencyInjection</a></p>
<p>Ahora, para utilizar este u otro componente ya podremos hacer algo como:</p>
<pre class="code">  ContenedorDeDependencias::getMailer ()
</pre>
<h2>Bibliograf&iacute;a</h2>
<ul>
<li><a href="http://fabien.potencier.org/article/11/what-is-dependency-injection">http://fabien.potencier.org/article/11/what-is-dependency-injection</a></li>
<li><a href="http://en.wikipedia.org/wiki/Law_Of_Demeter">http://en.wikipedia.org/wiki/Law_Of_Demeter</a></li>
<li><a href="http://www.hasheado.com/dependecy-injection-en-php.html">http://www.hasheado.com/dependecy-injection-en-php.html</a></li>
<li><a href="https://github.com/symfony/DependencyInjection">https://github.com/symfony/DependencyInjection </a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=118</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/inyeccion-de-dependencias.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Animaciones css y eventos en SVG</title>
			<link>http://www.imaginanet.com/blog/animaciones-css-y-eventos-en-svg.html</link>
			<guid>http://www.imaginanet.com/blog/animaciones-css-y-eventos-en-svg.html</guid>
			<comments>http://www.imaginanet.com/blog/animaciones-css-y-eventos-en-svg.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon,  6 Aug 2012 11:10:24 +0100</pubDate>
					<category><![CDATA[HTML5]]></category>
					<category><![CDATA[Apps]]></category>
					<description><![CDATA[SVG no solo nos permite animar las transformaciones (utilizando animateTransform) sino que tambi&eacute;n podemos realizar animaciones sobre atributos CSS de los elementos. Concretamente con la etiqueta &lsquo;animate&rsquo; y el tipo &lsquo;CSS&rsquo;, es decir si tenemos un rect&aacute;ngulo de 200x100 de color azul:
&lt;rect...]]></description>
			<content:encoded><![CDATA[><p>SVG no solo nos permite animar las transformaciones (utilizando animateTransform) sino que tambi&eacute;n podemos realizar animaciones sobre atributos CSS de los elementos. Concretamente con la etiqueta &lsquo;animate&rsquo; y el tipo &lsquo;CSS&rsquo;, es decir si tenemos un rect&aacute;ngulo de 200x100 de color azul:</p>
<pre class="code">&lt;rect width="200" height="100" style="fill:rgb(0,0,255);"/&gt;
</pre>
<p>Podemos hacer que cambie su color a rojo, a&ntilde;adiendo:</p>
<pre class="code">&lt;rect width="200" height="100" style="fill:rgb(0,0,255);"&gt;
&lt;animate attributeType="CSS" attributeName="fill" to="rgb(255,0,0)" dur="3s" fill="freeze" /&gt;
&lt;/rect&gt;
</pre>
<p>O a&ntilde;adiendo:</p>
<pre class="code">&lt;animateColor attributeName="fill" to="red" dur="3s" fill="freeze" /&gt;
</pre>
<p>En el par&aacute;metro &lsquo;attributeName&rsquo; se indicar el atributo a animar. Por ejemplo podemos hacer que desaparezca realizando un fade o desvanecimiento pasandos 3 segundos:</p>
<pre class="code">&lt;animate begin="3s" attributeType="CSS" attributeName="fill-opacity" to="0" dur="2s" fill="freeze" /&gt;
</pre>
<p>Otra caracter&iacute;stica interesante de SVG es la posibilidad de iniciar las animaciones ante determinados eventos, donde estos pueden ser: click, mousedown, mouseup, mousemove, mouseover, y mouseout.</p>
<p>Por ejemplo podemos hacer que al hacer click sobre el rect&aacute;ngulo, este se rellene de color amarillo:</p>
<pre class="code">&lt;set begin="click" attributeName="fill" to="yellow" /&gt;
</pre>
<p>Este &uacute;ltimo c&oacute;digo se debe incluir dentro de la etiqueta rect&aacute;ngulo al igual que hac&iacute;amos con el &lsquo;animate&rsquo;. El elemento &lsquo;set&rsquo; de SMIL es una forma corta de realizar un &lsquo;animate&rsquo; con duraci&oacute;n 0s, por tanto de esta forma cuando se produzca un click sobre el rect&aacute;ngulo este cambiar&aacute; su color automaticamente.</p>
<p>Hay que tener en cuenta que podemos combinar los eventos con los segundos, es decir, podemos hacer que se inicie 2 segundos despu&eacute;s del evento por ejemplo:</p>
<pre class="code">&lt;set begin="click+2s" attributeName="fill" to="yellow" /&gt;
</pre>
<p>Los eventos se pueden combinar con los identificadores de otros elementos SVG para as&iacute; iniciar una animaci&oacute;n cuando ocurra un evento particular de otro elemento. Vamos a verlo con el siguiente ejemplo:</p>
<pre class="code">&lt;rect id="rect1" width="200" height="100" style="fill:blue;"/&gt;

&lt;rect id="rect2" width="200" height="100" style="fill:red; fill-opacity: 0;"&gt;
&lt;animate begin="rect1.mouseover" attributeType="CSS" attributeName="fill-opacity" to="1" dur="1s" fill="freeze" /&gt;
&lt;/rect&gt;
</pre>
<p>En este ejemplo tenemos dos rect&aacute;ngulos, uno de color azul y otro de color amarillo con opacidad 0, es decir, que este amarillo inicialmente no se ve. Ahora bien le colocamos al segundo rect&aacute;ngulo dentro una animaci&oacute;n para que cambie su opacidad a 1 en 1 segundo y conserve los cambios (&lsquo;freeze&rsquo;). Esta animaci&oacute;n se inicia cuando se ejecuta el evento &lsquo;mouseover&rsquo; sobre el elemento que tenga el identificador &lsquo;rect1&rsquo;.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=117</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/animaciones-css-y-eventos-en-svg.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Introducción a las animaciones de SVG</title>
			<link>http://www.imaginanet.com/blog/introduccion-a-las-animaciones-de-svg.html</link>
			<guid>http://www.imaginanet.com/blog/introduccion-a-las-animaciones-de-svg.html</guid>
			<comments>http://www.imaginanet.com/blog/introduccion-a-las-animaciones-de-svg.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon,  6 Aug 2012 10:13:33 +0100</pubDate>
					<category><![CDATA[HTML5]]></category>
					<category><![CDATA[Apps]]></category>
					<description><![CDATA[Una de las grandes utilidades de SVG es la posibilidad de realizar animaciones, cambiando los gr&aacute;ficos vectoriales representados a lo largo del tiempo. Existen dos formas de realizar animaciones en SVG, la primera consiste en utilizar elementos 'animation', y la segunda es acceder directamente al DOM del SVG y modificar...]]></description>
			<content:encoded><![CDATA[><p>Una de las grandes utilidades de SVG es la posibilidad de realizar animaciones, cambiando los gr&aacute;ficos vectoriales representados a lo largo del tiempo. Existen dos formas de realizar animaciones en SVG, la primera consiste en utilizar elementos 'animation', y la segunda es acceder directamente al DOM del SVG y modificar atributos de los gr&aacute;ficos.</p>
<p>Las animaciones de SVG han sido definidas para permitir SMIL (Synchronized Multimedia Integration Language), esto representa una ventaja ya que se trata de un lenguaje basado en xml, enfocado a realizar presentaciones multimedia con etiquetas para variaciones temporales, transiciones, etc. Este est&aacute;ndar permite organizar todo lo referente a presentaciones multimedia pero en el caso de SVG nos vamos a centrar en la parte de las animaciones.</p>
<p>Vamos a realizar algunos ejemplos para introducir los conceptos: - Primero vamos a ver un ejemplo donde vamos a mover un rect&aacute;ngulo:</p>
<pre class="code">&gt;rect width="200" height="100" style="fill:rgb(0,0,255);"/&lt;
</pre>
<p>En este c&oacute;digo tenemos declarado un rect&aacute;ngulo de 200x100 relleno de color azul.</p>
<pre class="code">&lt;rect width="200" height="100" style="fill:rgb(0,0,255);"&gt;
&lt;animateTransform attributeName="transform" attributeType="XML" type="translate" to=" 50,0" dur="3s"/&gt;
&lt;/rect&gt;
</pre>
<p>Si nos fijamos introducimos dentro del rect&aacute;ngulo la etiqueta &lsquo;animateTransform&rsquo; lo que nos permite crear animaciones del elemento transform, el cual recordamos permite realizar escalados, traslaciones, rotaciones, y torsiones. Concretamente aqui estamos realizando una traslaci&oacute;n de 50 en el eje x indicada por el par&aacute;metro &lsquo;to&rsquo;, con una duraci&oacute;n de 3 segundos indicada por el par&aacute;metro &lsquo;dur&rsquo;. Podemos modificar el par&aacute;metro type para realizar una rotaci&oacute;n:</p>
<pre class="code">&lt;animateTransform attributeName="transform" attributeType="XML" type="rotate" to=" 90" dur="3s"/&gt;
</pre>
<p>De esta forma rotamos el rect&aacute;ngulo 90&ordm;. Ahora bien, todos estos cambio tras terminar se pierden, es decir no se conservan los valores cambiados a no ser que indiquemos en el par&aacute;metro &lsquo;filll&rsquo; el estado &lsquo;freeze&rsquo; de conservaci&oacute;n o tambi&eacute;n podr&iacute;amos decir congelaci&oacute;n.</p>
<p>Supongamos un ejemplo algo m&aacute;s complejo, donde queremos mover primero el rect&aacute;ngulo y luego rotarlo, es decir primero una animaci&oacute;n y luego otra. Esto se consigue con el par&aacute;metro begin.</p>
<pre class="code">&lt;animateTransform id=&rdquo;anim1&rdquo; attributeName="transform" attributeType="XML" type="translate" to=" 50,0" dur="3s"/&gt;
&lt;animateTransform begin=&rdquo;anim1.end&rdquo; attributeName="transform" attributeType="XML" type="rotate" to=" 90" dur="3s"/&gt;
</pre>
<p>Como podemos observar hemos a&ntilde;adido el par&aacute;metro 'begin' con 'anim1.end', lo que quiere decir que esta animaci&oacute;n empezara cuando termine la animaci&oacute;n primera (fij&eacute;monos que a la primera animaci&oacute;n le hemos puesto el nombre id1 como par&aacute;metro id para asi poder referirnos a dicha animaci&oacute;n). El par&aacute;metro 'begin' nos permite indicar un offset de inicio, por ejemplo en vez de indicar que la animaci&oacute;n 2 se inicie al terminar la 1 podr&iacute;amos indicarle begin='3s' para empiece transcurridos 3 segundos desde el inicio global, de esta forma como la animaci&oacute;n 1 dura 3 segundos, tendr&iacute;amos el mismo resultado.</p>
<p>Esto nos da la libertad de encadenar animaciones y crear secuencias. Cabe destacar que los elementos animate no solo se usan con rectangulos, circulos o otras primitivas, sino que se pueden aplicar a agrupaciones (elementos &lsquo;g&rsquo;) para as&iacute; poder mover/modificar elementos m&aacute;s complejos con un solo animate.</p>
<p>Actualmente todos los navegadores modernos soportan animaciones mediante este m&eacute;todo, aunque explorer presenta algunas pegas a la hora de realizar morphings.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=116</wfw:commentRss>
			<slash:comments>1</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/introduccion-a-las-animaciones-de-svg.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Streaming de vídeo H.264 desde un navegador web con Wowza</title>
			<link>http://www.imaginanet.com/blog/streaming-de-video-h264-desde-un-navegador-web-con-wowza.html</link>
			<guid>http://www.imaginanet.com/blog/streaming-de-video-h264-desde-un-navegador-web-con-wowza.html</guid>
			<comments>http://www.imaginanet.com/blog/streaming-de-video-h264-desde-un-navegador-web-con-wowza.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed, 18 Jul 2012 13:22:25 +0100</pubDate>
					<category><![CDATA[Flash]]></category>
					<category><![CDATA[HTML5]]></category>
					<category><![CDATA[Servidores y Seguridad]]></category>
					<category><![CDATA[Rendimiento]]></category>
					<description><![CDATA[El streaming de v&iacute;deo nos proporciona que un evento en directo pueda ser visto por miles de personas simult&aacute;neamente, como por ejemplo desde una c&aacute;mara IP.
Lo m&aacute;s interesante es que el acceso a dicho v&iacute;deo sea de manera sencilla, como por ejemplo visualizar el streaming de v&iacute;deo desde un...]]></description>
			<content:encoded><![CDATA[><p>El streaming de v&iacute;deo nos proporciona que un evento en directo pueda ser visto por miles de personas simult&aacute;neamente, como por ejemplo desde una c&aacute;mara IP.</p>
<p>Lo m&aacute;s interesante es que el acceso a dicho v&iacute;deo sea de manera sencilla, como por ejemplo visualizar el <strong>streaming de v&iacute;deo desde un navegador web</strong> a trav&eacute;s de una aplicaci&oacute;n Flash o HTML 5.</p>
<p>A continuaci&oacute;n vamos a explicar como poner en marcha el <strong>servidor Wowza</strong> y como leer desde un visor de v&iacute;deo Flash para web el streaming, en nuestro caso <strong>JWPlayer</strong>.</p>
<p>&nbsp;</p>
<h3>Servidor de streaming de v&iacute;deo Wowza</h3>
<p>Este software proporciona el servicio de streaming de v&iacute;deo bajo demanda con un bajo coste de licencia con medios como Flash u otros reproductores como VLC.</p>
<p>M&aacute;s informaci&oacute;n acerca del coste de licencia y del servidor de streaming lo pod&eacute;is encontrar en su p&aacute;gina web&nbsp;<a href="http://www.wowza.com" target="_blank">http://www.wowza.com</a></p>
<h4>Instalando Wowza en Linux</h4>
<p>La instalaci&oacute;n es bastante sencilla, en primer lugar bajamos el paquete y lo instalamos, substituyendo la extensi&oacute;n XXX por la distribuci&oacute;n de paquetes de nuestra versi&oacute;n de Linux. Durante la instalaci&oacute;n nos pedir&aacute; el n&uacute;mero de licencia, existe una versi&oacute;n de prueba de 30 d&iacute;as y otras de pago que van desde la licencia por d&iacute;as de uso, mensual o permanente:</p>
<pre class="code">sudo chmod 777 WowzaMediaServer-3.1.2.XXX 
sudo ./WowzaMediaServer-3.1.2.XXX</pre>
<p>Encenderemos y pararemos el servidor con:</p>
<pre class="code">cd /usr/local/WowzaMediaServer/bin 
./startup.sh</pre>
<p>y pararemos el servidor con</p>
<pre class="code">cd /usr/local/WowzaMediaServer/bin 
./shutdown.sh
</pre>
<h4>Corriendo Wowza desde Amazon EC2</h4>
<p>Una soluci&oacute;n sencilla para desplegar el servidor online es hacer uso de una imagen AMI con el servidor preinstalado. En funci&oacute;n del n&uacute;mero de usuarios que esperemos que hagan uso del servicio deberemos hacer uso de de un tipo de instancia u otra. Podemos encontrar m&aacute;s informaci&oacute;n en <a href="http://www.wowza.com/forums/content.php?203-ec2-support-center_1" target="_blank">Wowza Amazon EC2 Support center</a></p>
<p>&nbsp;</p>
<h3>Streaming de v&iacute;deo de una c&aacute;mara IP (RTP / RTSP)</h3>
<p>Crearemos las carpetas</p>
<pre class="code">/usr/local/WowzaMediaServer/applications/miStreaming
/usr/local/WowzaMediaServer/conf/miStreaming</pre>
<p>y copiaremos el archivo</p>
<pre class="code">/usr/local/WowzaMediaServer/conf/Application.xml</pre>
<p>a la carpeta</p>
<pre class="code">/usr/local/WowzaMediaServer/conf/miStreaming/Application.xml</pre>
<p>haciendo los siguientes cambios en el archivo XML:</p>
<ol>
<li>
<pre class="code">&lt;StreamType&gt;live&lt;/StreamType&gt;</pre>
</li>
<li>
<pre class="code">&lt;HTTPStreamers&gt;cupertinostreaming, smoothstreaming, sanjosestreaming&lt;/HTTPStreamers&gt;
</pre>
</li>
<li>
<pre class="code">&lt;LiveStreamPacketizers&gt;cupertinostreamingpacketizer, smoothstreamingpacketizer, sanjosestreamingpacketizer&lt;/LiveStreamPacketizers&gt;
</pre>
</li>
<li>
<pre class="code">&lt;PlayMethod&gt;none&lt;/PlayMethod&gt;</pre>
</li>
<li>
<pre class="code">&lt;Property&gt;
    &lt;Name&gt;forceInterleaved&lt;/Name&gt;
    &lt;Value&gt;true&lt;/Value&gt;
    &lt;Type&gt;Boolean&lt;/Type&gt;
&lt;/Property&gt;
</pre>
</li>
</ol>
<p>Ahora configuraremos la fuente de streaming y de emis&oacute;n de &eacute;sta:</p>
<ol>
<li>Crear el archivo <em>/usr/local/WowzaMediaServer/content/miCamara.stream</em> y poner la ruta fuente del RTP / RTSP, por ejemplo <em>rtsp://192.168.1.200/vod/mp4:camara.mov</em></li>
<li>Editar el archivo <em>/usr/local/WowzaMediaServer/conf/admin.password</em> y a&ntilde;adir un usuario y contrase&ntilde;a para el gestor de Wowza, por ejemplo:
<pre class="code">usuario clave</pre>
</li>
<li>Opcional: aseguraremos la contrase&ntilde;a (se guarda en texto plano) d&aacute;ndole permisos de s&oacute;lo lectura al propietario del archivo <em>admin.password</em> mediante:
<pre class="code">chmod 700 /usr/local/WowzaMediaServer/conf/admin.password</pre>
</li>
<li>Iniciar Wowza con el comando:
<pre class="code">cd /usr/local/WowzaMediaServer/bin 
./startup.sh</pre>
</li>
<li> Abriremos un navegador e iremos al gestor <em>http://ip-servidor-wowza:8086/streammanager</em> introduciendo el usuario y contrase&ntilde;a elegido previamente </li>
<li> Hacer click debajo de <em>miStreaming</em> en <em>[start-receiving-stream]</em> </li>
<li> Seleccionar <em>MediaCaster Type: rtp</em> </li>
<li>Dentro del campo <em>Stream Name</em>, introduciremos el nombre del archivo de streaming, en nuestro caso <em>miCamara.stream</em></li>
<li>Hacemos click en OK para comenzar el re-streaming</li>
</ol>
<p>Para probar que la instalaci&oacute;n era correcta, abriremos el archivo <em>/usr/local/WowzaMediaServer/examples/LiveVideoStreaming/client/live.html</em> que mostrar&aacute; un reproductor de v&iacute;deo. Introduciremos los siguientes datos para conectarnos al stream, rellenando el campo <em>Server</em></p>
<pre class="code">rtmp://ip-servidor-wowza/miStreaming</pre>
<p>y el campo <em>Stream</em></p>
<pre class="code">miCamara.stream</pre>
<p>haciendo click en el campo <em>Play</em></p>
<p>Si no tenemos c&aacute;mara IP podemos utilizar el fuente RTSP que podemos encontrar en <a href="http://www.wowza.com/html/mobile.html" target="_blank">http://www.wowza.com/html/mobile.html</a></p>
<p>&nbsp;</p>
<h3>Reproduciendo streaming de v&iacute;deo en un navegador web con JWPlayer</h3>
<p>El anterior reproductor est&aacute; bastante bien, pero no nos permite configurar internamente los datos para que la conexi&oacute;n sea transparente al usuario. Para ello vamos a hacer uso de JWPlayer, un reproductor libre que se puede descargar desde <a href="http://www.longtailvideo.com/players" target="_blank">http://www.longtailvideo.com/players</a>. Descomprimiremos los archivos y donde est&eacute;n los archivos JS crearemos un nuevo archivo HTML con el siguiente contenido:</p>
<pre class="code">&lt;html&gt;

&lt;head&gt;&lt;title&gt;Reproduciendo Streaming de v&iacute;deo H.264 con Wowza y JWPlayer&lt;/title&gt;&lt;/head&gt;

&lt;body&gt;
&lt;script type="text/javascript" src="swfobject.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="jwplayer.js"&gt;&lt;/script&gt;

&lt;div id='container'&gt;Cargando...&lt;/div&gt;

&lt;script type="text/javascript"&gt;
  var flashvars = {
    file:'miCamara.stream',
    streamer:'rtmp://ip-servidor-wowza/miStream'
  };

  swfobject.embedSWF('player.swf','container','480','270','9.0.115','false', flashvars,
                     {allowfullscreen:'true',allowscriptaccess:'always'},
                     {id:'jwplayer',name:'jwplayer'}
                    );
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Es muy importante que este archivo sea llamado desde el navegador web a una URL contenida en un servidor web, como Apache, IIS, Lighthttpd, etc. ya que la configuraci&oacute;n de seguridad de Flash no permite ejecutarlo como archivo local.</p>
<p>&nbsp;</p>
<h3>Fuentes</h3>
<p>Parte de la gu&iacute;a de Wowza es una versi&oacute;n reducida de la documentaci&oacute;n oficial <a href="http://www.wowza.com/forums/content.php?39" target="_blank">http://www.wowza.com/forums/content.php?39</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=115</wfw:commentRss>
			<slash:comments>1</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/streaming-de-video-h264-desde-un-navegador-web-con-wowza.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Introducción a SVG</title>
			<link>http://www.imaginanet.com/blog/introduccion-a-svg.html</link>
			<guid>http://www.imaginanet.com/blog/introduccion-a-svg.html</guid>
			<comments>http://www.imaginanet.com/blog/introduccion-a-svg.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed, 11 Jul 2012 13:35:49 +0100</pubDate>
					<category><![CDATA[HTML5]]></category>
					<category><![CDATA[Apps]]></category>
					<description><![CDATA[Un SVG, como su nombre indica, es un gr&aacute;fico vectorial escalable. &iquest;Qu&eacute; quiere decir esto? Pues que el gr&aacute;fico se construye con primitivas como l&iacute;neas, curvas, pol&iacute;gonos, etc. Y de esta forma se puede escalar sin perder calidad. A d&iacute;a de hoy todos los navegadores modernos soportan...]]></description>
			<content:encoded><![CDATA[><p>Un SVG, como su nombre indica, es un gr&aacute;fico vectorial escalable. &iquest;Qu&eacute; quiere decir esto? Pues que el gr&aacute;fico se construye con primitivas como l&iacute;neas, curvas, pol&iacute;gonos, etc. Y de esta forma se puede escalar sin perder calidad. A d&iacute;a de hoy todos los navegadores modernos soportan SVG, pero no todos implementan correctamente todo el API javascript que introducen para un mayor control de los trazos y animaciones.</p>
<p>SVG incorpora una forma de realizar animaciones y transformaciones sobre sus objetos. En el caso de las transformaciones, estas nos permiten trasladar elementos, rotarlos, escalarlos y torcerlos. Por ejemplo:</p>
<pre class="code html">    &lt;g transform="translate(10,0)"&gt;
        ...
    &lt;/g&gt;
</pre>
<p>De esta forma estamos trasladando el contenedor g (g se utiliza para agrupar elementos) 10 puntos en el eje x y 0 en el eje y.</p>
<p>Entre los elementos que podemos definir dentro de un SVG, se encuentran:</p>
<p>- L&iacute;neas<br /> - Rect&aacute;ngulos<br /> - C&iacute;rculos<br /> - Elipses<br /> - Caminos<br /> - Pol&iacute;gonos<br /> - Textos</p>
<p>Por ejemplo podemos definir una l&iacute;nea de la siguiente manera:</p>
<pre class="code html">&lt;line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(255,0,0);stroke-width:2"/&gt;
</pre>
<p>De esta forma dibujamos una l&iacute;nea desde el punto 0,0 de nuestro eje de coordenadas, hata el punto 200,200. En en el estilo le definimos que tendr&aacute; una anchura de 2 y ser&aacute; de color rojo. El resto de elemento son similares, es decir, se definen sus propiedades y su estilo, as&iacute; por ejemplo para definir un rect&aacute;ngulo bastar&aacute; indicar la anchura y altura que deber&aacute; tener. Los caminos (path) son algo m&aacute;s complejos y de los que m&aacute;s libertad nos dan pues se van construyendo con una serie de construcciones como curvas de bezier o simples l&iacute;neas.</p>
<p>Una vez tengamos el SVG dibujado no hay que olvidar definir su viewbox, es decir la anchura y altura que tiene inicialmente, para posteriormente indicar la anchura y altura de visualizaci&oacute;n actual. Ejemplo, si nuestro gr&aacute;fico se hace pensando para 800x600, entonces nuestro viewbox ser&aacute;:</p>
<pre class="code html">viewbox="0 0 800 600"
</pre>
<p>Siendo los dos primeros valores, el m&iacute;nimo valor de "x", y el m&iacute;nimo valor de "y". Y si nuestra pantalla actualmente es la de un m&oacute;vil de 500x400, entonces en los atributos "width" y "height" del svg deberemos indicarle dichos valores, para as&iacute; autom&aacute;ticamente el navegador poder escalar el gr&aacute;fico correctamente.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=114</wfw:commentRss>
			<slash:comments>2</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/introduccion-a-svg.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Open graph para 'me gusta' de Facebook</title>
			<link>http://www.imaginanet.com/blog/open-graph-para-me-gusta-de-facebook.html</link>
			<guid>http://www.imaginanet.com/blog/open-graph-para-me-gusta-de-facebook.html</guid>
			<comments>http://www.imaginanet.com/blog/open-graph-para-me-gusta-de-facebook.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed, 11 Jul 2012 13:24:58 +0100</pubDate>
					<category><![CDATA[XHTML]]></category>
					<category><![CDATA[Windows 8]]></category>
					<description><![CDATA[Open graph es una iniciativa de Facebook que pretende mediante un API basada en metas obtener informaci&oacute;n de m&aacute;s objetos que los t&iacute;picos: personas, fotos, eventos y p&aacute;ginas, y sus relaciones entre ellos. Para ello se crea una aplicaci&oacute;n (app) que contiene una serie de objetos sobre los que se...]]></description>
			<content:encoded><![CDATA[><p>Open graph es una iniciativa de Facebook que pretende mediante un API basada en metas obtener informaci&oacute;n de m&aacute;s objetos que los t&iacute;picos: personas, fotos, eventos y p&aacute;ginas, y sus relaciones entre ellos. Para ello se crea una aplicaci&oacute;n (app) que contiene una serie de objetos sobre los que se puede realizar una serie de acciones, por ejemplo si tenemos el objeto receta, podemos realizar la acci&oacute;n de cocinarla, y de esta manera que aparezca reflejado en nuestra l&iacute;nea temporal que hemos cocinado dicha receta.</p>
<p>No vamos a entrar en el detalle de ver esto a fondo, pero vamos a ver que podemos emplear dichos metas para que Facebook interprete mejor nuestras p&aacute;ginas web. Puesto que normalmente cuando incluimos un bot&oacute;n de &ldquo;Me gusta&rdquo; en nuestra p&aacute;gina web, no nos paramos a pensar en que se basa Facebook para sacar un texto de descripci&oacute;n de la p&aacute;gina compartida, as&iacute; como la foto que muestra.</p>
<p>Por ello, habr&aacute; ocasiones en las que de la casualidad y coja justo el texto y la foto que deseamos, pero por norma general esto no suele ser as&iacute;, por ello debemos indicarle a Facebook que texto y qu&eacute; foto debe coger.</p>
<pre class="code html">&lt;meta property="og:title" content="Stuffed Cookies" &gt;
&lt;meta property="og:image" content="http://fbwerks.com:8000/zhen/cookie.jpg" &gt;
&lt;meta property="og:description" content="The Turducken of Cookies" &gt;
&lt;meta property="og:url" content="http://fbwerks.com:8000/zhen/cookie.html"&gt;
</pre>
<p>He aqu&iacute; los metas b&aacute;sicos que vamos a utilizar. De esta forma indicamos un t&iacute;tulo, una foto, una descripci&oacute;n y la direcci&oacute;n correcta. Ahora cuando se haga click en un &ldquo;Me gusta&rdquo; tendremos el control sobre que aparecer&aacute; en Facebook.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=113</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/open-graph-para-me-gusta-de-facebook.html</feedburner:origLink>
		</item>
				
		<item>
			<title>PHPDocs</title>
			<link>http://www.imaginanet.com/blog/documentacion-en-php-utilizando-phpdocs.html</link>
			<guid>http://www.imaginanet.com/blog/documentacion-en-php-utilizando-phpdocs.html</guid>
			<comments>http://www.imaginanet.com/blog/documentacion-en-php-utilizando-phpdocs.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Fri,  6 Jul 2012 09:22:45 +0100</pubDate>
					<category><![CDATA[Linux]]></category>
					<category><![CDATA[PHP]]></category>
					<description><![CDATA[&iquest;Por qu&eacute; es importante generar documentaci&oacute;n?
La programaci&oacute;n es, generalmente, un entorno colaborativo, especialmente en proyectos de cierta emvergadura donde varios programadores y anal&iacute;stas trabajan de forma conjunta.Cada programador tiene una forma concreta de comentar y de programar, y esto...]]></description>
			<content:encoded><![CDATA[><h2>&iquest;Por qu&eacute; es importante generar documentaci&oacute;n?</h2>
<p>La programaci&oacute;n es, generalmente, <strong>un entorno colaborativo, </strong>especialmente en proyectos de cierta emvergadura donde varios programadores y anal&iacute;stas trabajan de forma conjunta.<br /><br />Cada programador tiene una forma concreta de comentar y de programar, y esto es un inconveniente porque dota de mucha hetereogeneidad a los proyectos haciendo que los programadores sepan dificilmente para qu&eacute; son determinadas clases o funciones. Y m&aacute;s grave todav&iacute;a es cuando hay que volver a retomar un proyecto hace tiempo olvidado.<br /><br />M&aacute;s motivos para utilizar una documentaci&oacute;n sistem&aacute;tica <strong>es la tendencia actual del software de ser fabricarlo como si fueran piezas que fueran f&aacute;cilmente interconectadas</strong>, por lo que una aplicaci&oacute;n web por ejemplo, pudiera integrar f&aacute;cilmente un foro o un blog. <strong>Generar una documentaci&oacute;n est&aacute;ndar da muchas facilidades al entendimiento del c&oacute;digo.</strong><br /><br />Adem&aacute;s, generar una documentaci&oacute;n que siga un cierto est&aacute;ndar<strong> nos va a permitir automatizar su generaci&oacute;n en otros documentos como p&aacute;ginas HTML o PDFs</strong> adem&aacute;s de poder integrarlo con los famosos entornos IDE de programaci&oacute;n de forma que conforme escribimos veamos la descripci&oacute;n de la funci&oacute;n, as&iacute; como sus par&aacute;metros.</p>
<p>&nbsp;</p>
<h2>&iquest;Qu&eacute; es PHPDocumentor?</h2>
<span>Es una herramienta que podemos instalar mediante PEAR con lo cual podemos generar autom&aacute;ticamente el c&oacute;digo fuente. Para instalarla en nuestro servidor podemos hacerlo de la siguiente manera:</span><br />
<blockquote>
<p dir="ltr"><code><span>$ </span><span>sudo apt-get install php-pear</span></code></p>
</blockquote>
<br /><span>Una vez instalado PEAR, instalamos phpDocumentor</span><br />
<blockquote>
<p dir="ltr"><code> <span>$ </span><span>pear channel-discover pear.phpdoc.org</span><br /> <span>$ </span><span>pear install phpdoc/phpDocumentor-alpha</span> </code></p>
</blockquote>
<br /><span>Tambi&eacute;n es posible que tengamos que instalar las siguiente extensiones para poder generar gr&aacute;ficos para los diagramas de clases y para poder parsear el c&oacute;digo fuente, aunque algunos servidores ya traen este software instalado.</span><br />
<blockquote>
<p dir="ltr"><code> <span>$ </span><span>sudo apt-get install php-xsl</span><br /> <span>$ </span><span>sudo apt-get install graphviz</span> </code></p>
</blockquote>
<br /><span>Su uso m&aacute;s b&aacute;sico podemos ejecutarlo desde la consola de comandos indic&aacute;ndole la carpeta donde est&aacute; el c&oacute;digo fuente y la carpeta de destino</span><br />
<blockquote>
<p dir="ltr"><code><span>$ </span><span>phpdoc -d . -t docs</span><span style="line-height: 0px;"> </span></code></p>
<p dir="ltr"><span style="line-height: 0px;"><br /></span></p>
</blockquote>
<h2>DocBlocks</h2>
<p>La documentaci&oacute;n de PHPDoc <strong>est&aacute; basada en bloques de comentarios conocidos como DocBlocks</strong>.</p>
<p><br />En este <a href="http://www.phpdoc.org/docs/latest/for-users/anatomy-of-a-docblock.html">ejemplo</a>, vamos a ver como es la anatom&iacute;a de uno de estos bloques</p>
<p style="padding-left: 30px;"><code>/**<br class="kix-line-break" /> &nbsp;* This is the short description for a DocBlock.<br class="kix-line-break" /> &nbsp;*<br class="kix-line-break" /> &nbsp;* This is the long description for a DocBlock.&nbsp;<br class="kix-line-break" /> &nbsp;*<br class="kix-line-break" /> &nbsp;* * Markdown style lists function too<br class="kix-line-break" /> &nbsp;* * Just try this out once<br class="kix-line-break" /> &nbsp;*<br class="kix-line-break" /> &nbsp;* The section after the long description contains the tags;&nbsp;<br class="kix-line-break" /> &nbsp;* <span>which provide&nbsp;</span>structured meta-data concerning&nbsp;<br class="kix-line-break" /> &nbsp;*&nbsp;<span>the given element.</span><br class="kix-line-break" /> &nbsp;* @author &nbsp;Mike van Riel &lt;mike.vanriel@naenius.com&gt;<br class="kix-line-break" /> &nbsp;*<br class="kix-line-break" /> &nbsp;* @since 1.0<br class="kix-line-break" /> &nbsp;*<br class="kix-line-break" /> &nbsp;* @param int &nbsp;&nbsp;&nbsp;$example &nbsp;This is an example description.<br class="kix-line-break" /> &nbsp;* @param string $example2 This is a second example.<br class="kix-line-break" /> &nbsp;*/</code></p>
<p><br />Este bloque se divide en los siguientes apartados:</p>
<ul>
<li>Descripci&oacute;n corta</li>
<li>Descripci&oacute;n larga</li>
<li>Tags</li>
</ul>
<p><br />Existen dos tipos principales de DocBlocks. A <strong>nivel de fichero</strong> y a <strong>nivel de elemento.&nbsp;</strong>Los <strong>bloques a nivel de fichero </strong>definen el funcionamiento o el prop&oacute;sito del fichero y los de nivel de elemento comentan una determinada clase o funci&oacute;n.</p>
<p>A continuaci&oacute;n vamos a ver la forma recomendada de utilizar estos bloques en un fichero de ejemplo.</p>
<p><br /><code><span>&lt;?php</span><br /><span>/**</span><br /><span> * This is a file-level DocBlock</span><br /><span> * </span><br /><span> * No warning will be raised. &nbsp;This is the recommended usage</span><br /><span> * </span><span>@package</span><span> SomePackage</span><br /><span> */</span></code></p>
<p><code><span>&nbsp;</span><br /><br /><span>/**</span><br /><span> * This is a not a file-level DocBlock, because it&nbsp;</span><br /><span> * <span>precedes a class declaration</span></span><br /><span> * This is also the recommended usage</span><br /><span> * </span><span>@package</span><span> SomePackage</span><br /><span> */</span><br /><span>class </span><span>foo </span><span>{}</span><br /><span>?&gt;</span></code></p>
<p>Vemos aqu&iacute; como el primer bloque es a nivel de fichero e indica el atributo de package (paquete). Y el siguiente bloque de documentaci&oacute;n se refiere a la clase <strong>foo</strong>.</p>
<h2><br />Paquetes</h2>
<p>El concepto de paquete, como tal, no existe en PHP, pero desde la documentaci&oacute;n no es posible indicar un paquete de forma que podamos agrupar conceptos similares. Si especificamos un paquete en el un bloque de documentaci&oacute;n todas las funciones, clases, etc ser&aacute;n agrupadas juntas.  En el caso de no especificar ning&uacute;n paquete todo ir&aacute; al paquete DEFAULT.</p>
<p><br />Referencias</p>
<ul>
<li><a href="http://manual.phpdoc.org/">http://manual.phpdoc.org/</a></li>
<li><a href="http://www.phpdoc.org/">http://www.phpdoc.org/</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=112</wfw:commentRss>
			<slash:comments>1</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/documentacion-en-php-utilizando-phpdocs.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Asset Manager Javascript</title>
			<link>http://www.imaginanet.com/blog/asset-manager-javascript.html</link>
			<guid>http://www.imaginanet.com/blog/asset-manager-javascript.html</guid>
			<comments>http://www.imaginanet.com/blog/asset-manager-javascript.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Thu,  5 Jul 2012 10:14:09 +0100</pubDate>
					<category><![CDATA[JavaScript]]></category>
					<description><![CDATA[A veces necesitamos esperar a que se carguen im&aacute;genes para poder realizar alguna acci&oacute;n, como animaciones en canvas. Como es una tarea que se repite muchas veces y no siempre es f&aacute;cil de controlar aqu&iacute; dejo una funci&oacute;n que os ayudar&aacute;.
	function ImageManager() {
		this._queue =...]]></description>
			<content:encoded><![CDATA[><p>A veces necesitamos esperar a que se carguen im&aacute;genes para poder realizar alguna acci&oacute;n, como animaciones en <a href="http://www.imaginanet.com/blog/canvas-2d-dibuja-en-tu-navegador.html">canvas</a>. Como es una tarea que se repite muchas veces y no siempre es f&aacute;cil de controlar aqu&iacute; dejo una funci&oacute;n que os ayudar&aacute;.</p>
<pre class="code js">	function ImageManager() {
		this._queue = [];
		this._count = 0;
	}
	ImageManager.prototype.add = function (url) {
		if (url instanceof Image) {
			var url = url.src;
		}
		this._queue.push(url);
	}
	ImageManager.prototype.waitForAll = function (callback) {
		var self = this;
		for (var i=0; i&lt;this._queue.length; i++) {
			var url = this._queue[i];
			var img = new Image();
			img.onload = function () {
				self._count++;
				if (self._count == self._queue.length) {
					callback();
				}
			}
			img.src = url;
		}
	}
</pre>
<p>Lo que hace esta funci&oacute;n es crear una cola de im&aacute;genes y un contador inicializado a 0. A medida que una imagen se carga el contador aumenta y cuando alcanza el valor del n&uacute;mero de im&aacute;genes en cola se llama a la funci&oacute;n "callback".</p>
<p>El uso es muy sencillo. Iremos a&ntilde;adiendo las im&aacute;genes que necesitemos que est&eacute;n precargadas y cuando ya las tengamos todas llamaremos al m&eacute;todo waitForAll pas&aacute;ndole como par&aacute;metro una funci&oacute;n que ser&aacute; la que comenzar&aacute; con nuestro c&oacute;digo. Al m&eacute;todo add le podemos pasar tanto las rutas de las im&aacute;genes como un objecto Image.</p>
<pre class="code js">	var init = function () {
		// Aqu&iacute; ir&aacute; nuestro c&oacute;digo principal
	}
	
	var im = new ImageManager();
	im.add('image1.png');
	im.add('image2.png');
	var img = new Image();
	img.src = "image3.png";
	im.add(img);

	im.waitForAll(init);
</pre>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=111</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/asset-manager-javascript.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Canvas 2D. Dibuja en tu navegador.</title>
			<link>http://www.imaginanet.com/blog/canvas-2d-dibuja-en-tu-navegador.html</link>
			<guid>http://www.imaginanet.com/blog/canvas-2d-dibuja-en-tu-navegador.html</guid>
			<comments>http://www.imaginanet.com/blog/canvas-2d-dibuja-en-tu-navegador.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Thu,  5 Jul 2012 09:12:36 +0100</pubDate>
					<category><![CDATA[HTML5]]></category>
					<category><![CDATA[JavaScript]]></category>
					<description><![CDATA[Canvas es una etiqueta introducida en HTML5 que sirve generar gr&aacute;ficos dinamicamente a trav&eacute;s de su API javascript. Pueden ser tanto gr&aacute;ficos est&aacute;ticos como animaciones
El elemento canvas tiene 2 atributos b&aacute;sicos width y height, que son el tama&ntilde;o del lienzo, por defecto su valor es de...]]></description>
			<content:encoded><![CDATA[><p>Canvas es una etiqueta introducida en HTML5 que sirve generar gr&aacute;ficos dinamicamente a trav&eacute;s de su API javascript. Pueden ser tanto gr&aacute;ficos est&aacute;ticos como animaciones</p>
<p>El elemento canvas tiene 2 atributos b&aacute;sicos width y height, que son el tama&ntilde;o del lienzo, por defecto su valor es de 160</p>
<pre class="code html">	&lt;canvas id="micanvas" width="640" height="480"&gt;No puedes ver esto&lt;/canvas&gt;
</pre>
<p>Dentro del elemento canvas no puede ir nada, ya que los gr&aacute;ficos los generamos a trav&eacute;s de javascript, pero podemos introducir un texto o una imagen, para indicar a los usuarios de un navegador que no lo tenga implementado, que se actualicen, por ejemplo. El navegador c&oacute;mo no interpretar&aacute; el canvas, nos mostrar&aacute; el contenido que le pongamos dentro.</p>
<p>El canvas tambi&eacute;n se puede usar para dibujar gr&aacute;ficos en tres dimensiones, pero en este art&iacute;culo nos centraremos en su contexto 2D.</p>
<p>Lo primero que tenemos que hacer para empezar a dibujar es obtener el contexto:</p>
<pre class="code js">	var canvas = document.getElementById('micanvas');
	var context = canvas.getContext('2d');
</pre>
<p>El contexto nos permitir&aacute; dibujar primitivas sobre el canvas como rect&aacute;ngulos, c&iacute;rculos, arcos, curvas, l&iacute;neas y tamb&iacute;en cargar im&aacute;genes externas dentro de &eacute;l. Podemos ver una referencia completa <a href="http://www.w3schools.com/html5/html5_ref_canvas.asp">aqu&iacute;</a></p>
<p>Ejemplo:</p>
<pre class="code js">	var image = new Image();
	image.src = "ruta/a/la/imagen.png";
	context.clearRect(0, 0, 640, 480);
	context.save();
	context.drawImage(image, 100, 200, 50, 50);
	context.restore();
</pre>
<p>En este ejemplo hemos cargado una imagen sobre el canvas. Primero creamos en objecto image y establecemos su ruta. Esta imagen debe estar precargada para que se dibuje correctamente. Luego con clearRect limpiamos todos los p&iacute;xeles del canvas. Con el m&eacute;todo drawImage ponemos la imagen sobre el canvas, en la posicion (100, 200) y con un tama&ntilde;o de 50x50</p>
<p>Haciendo esto varias veces ayud&aacute;ndonos de <a href="http://www.imaginanet.com/blog/animaciones-en-html5.html">requestAnimationFrame</a> es como crearemos animaciones.</p>
<p>Quedan dos m&eacute;todos por explicar, save y restore. Con el m&eacute;todo save lo que hacemos es guardar el estado del contexto, luego hacemos toda clase de dibujos y transformaciones para que al llamar al m&eacute;todo restore, volvamos al estado anterior y podamos volver a empezar de cero.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=110</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/canvas-2d-dibuja-en-tu-navegador.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Animaciones en HTML5</title>
			<link>http://www.imaginanet.com/blog/animaciones-en-html5.html</link>
			<guid>http://www.imaginanet.com/blog/animaciones-en-html5.html</guid>
			<comments>http://www.imaginanet.com/blog/animaciones-en-html5.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Thu,  5 Jul 2012 08:31:12 +0100</pubDate>
					<category><![CDATA[HTML5]]></category>
					<category><![CDATA[Web 2.0]]></category>
					<description><![CDATA[Para crear animaciones en HTML5 tenemos varias opciones. Una es crearlas directamente en la hoja de estilos con las transiciones de CSS3, otra es con la programaci&oacute;n de scripts y el uso de requestAnimationFrame
Transiciones
Las transiciones de CSS3 son m&aacute;s apropiadas para la creaci&oacute;n de efectos visuales. Por...]]></description>
			<content:encoded><![CDATA[><p>Para crear animaciones en HTML5 tenemos varias opciones. Una es crearlas directamente en la hoja de estilos con las transiciones de CSS3, otra es con la programaci&oacute;n de scripts y el uso de requestAnimationFrame</p>
<h2>Transiciones</h2>
<p>Las transiciones de CSS3 son m&aacute;s apropiadas para la creaci&oacute;n de efectos visuales. Por ejemplo, podemos hacer que un elemento se mueva cuando el rat&oacute;n est&eacute; dobre &eacute;l, para eso tenemos que definir su posici&oacute;n en el estado normal y en su estado "hover". Definimos la transici&oacute;n, el tiempo de la duraci&oacute;n, y el navagador se encargar&aacute; de animar ese elemento por t&iacute;. Veamos un ejemplo simple.</p>
<pre class="code css">	#elemeto {
		position: relative;
		left: 0;
		transition: left 500ms;
	}
	#elemento:hover {
		left: 10px;
	}
</pre>
<div>
<style><!--
		#div_ejemplo {
			position: relative;
			left: 0;
			padding: 20px;
			float: left;
			background-color: red;
			color: white;
			transition: left 500ms;
			-moz-transition: left 500ms;
			-webkit-transition: left 500ms;
			-ms-transition: left 500ms;
			-o-transition: left 500ms;
		}
		#div_ejemplo:hover {
			left: 10px;
		}
--></style>
<div id="div_ejemplo">Ejemplo: pasa el rat&oacute;n por encima.</div>
<div class="clearfix"></div>
</div>
<p>A una transici&oacute;n le podemos especificar la propiedad que queremos animar "<strong>transition-property: left;</strong>", la duraci&oacute;n de la animaci&oacute;n "<strong>transition-duration: 1s;</strong>", la funci&oacute;n que realizar&aacute; la animaci&oacute;n "<strong>transition-timing-function: linear;</strong>" y el retardo a la hora de empezar "<strong>transition-delay: 2s;</strong>"</p>
<h2>requestAnimationFrame</h2>
<p>Para animaciones m&aacute;s complejas como presentaciones o videojuegos no nos llega con usar transiciones de CSS3, necesitamos controlar mejor lo que vamos a hacer. La idea es crear una funci&oacute;n de dibujo que se ejecute cada cierto tiempo. Antes de la llegada de HTML5 usar&iacute;amos las funciones de javascript <strong>setTimeout</strong> o <strong>setInverval</strong>, pero ahora tenemos <strong>requestAnimationFrame</strong> que nos proporciona algunas ventajas. Estas ventajas son la creaci&oacute;n de animaciones suaves y un mejor aprovechamiento de los recursos.</p>
<p>Los navegadores implementan esta funci&oacute;n de manera que las animaciones se sincronicen con el refresco de pantalla, generalmente unos 60hz, lo que hace que las animaciones se vean m&aacute;s suaves. Tambi&eacute;n hacen que, por ejemplo, al cambiar de pesta&ntilde;a en el navegador, la animaci&oacute;n se pare, dejando de consumir recursos de CPU y de memoria.</p>
<p>Su uso es muy sencillo:</p>
<pre class="code js">	var requestId = 0;
	var animationStartTime = 0;

	function animate(time) {
		document.getElementById("animated").style.left = (time - animationStartTime) % 2000 / 4 + "px";
		requestId = window.requestAnimationFrame(animate);
	}
	function start() {
		animationStartTime = Date.now();
		requestId = window.requestAnimationFrame(animate);
	}
	function stop() {
		if (requestId)
			window.cancelAnimationFrame(requestId);
		requestId = 0;
	}
</pre>
<p>Para terminar aqu&iacute; dejo un <a href="http://www.imaginanet.com/blog/polyfills-para-css3-y-html5.html">polyfill</a> para hacer que requestAnimationFrame funcione en cualquier navegador:</p>
<pre class="code js">(function() {
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for(var x = 0; x &lt; vendors.length &amp;&amp; !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame = 
          window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
    }
 
    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function() { callback(currTime + timeToCall); }, 
              timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };
 
    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}());
</pre>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=109</wfw:commentRss>
			<slash:comments>1</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/animaciones-en-html5.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Cómo crear triángulos con CSS</title>
			<link>http://www.imaginanet.com/blog/como-crear-triangulos-con-css.html</link>
			<guid>http://www.imaginanet.com/blog/como-crear-triangulos-con-css.html</guid>
			<comments>http://www.imaginanet.com/blog/como-crear-triangulos-con-css.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon,  4 Jun 2012 08:10:45 +0100</pubDate>
					<category><![CDATA[CSS]]></category>
					<description><![CDATA[En muchas ocasiones necesitamos colocar en una p&aacute;gina web un tri&aacute;ngulo, ya sea para se&ntilde;alar algo con una flecha, en una paginaci&oacute;n de una galer&iacute;a o listado de cualquier cosa, o incluso para ponerle a una capa esquinas con cierta forma poligonal (donde obviamente no son redondeadas).
Es posible...]]></description>
			<content:encoded><![CDATA[><p>En muchas ocasiones necesitamos colocar en una p&aacute;gina web un tri&aacute;ngulo, ya sea para se&ntilde;alar algo con una flecha, en una paginaci&oacute;n de una galer&iacute;a o listado de cualquier cosa, o incluso para ponerle a una capa esquinas con cierta forma poligonal (donde obviamente no son redondeadas).</p>
<p>Es posible que de primeras pensemos en colocar im&aacute;genes con dichas formas, pero hay que tener en cuenta el papel de los bordes en las capas HTML. Los bordes al formarse se generan en &aacute;ngulo, es decir, si a una capa le ponemos anchura 0 y altura 0, y le damos tama&ntilde;o a sus bordes veremos c&oacute;mo estos tienden hacia el centro de la capa. Si hacemos esto, veremos un cuadrado normal y corriente.</p>
<p>Supongamos el siguiente c&oacute;digo HTML:</p>
<pre class="code">&lt; span id="flecha" &gt;</pre>
<p>Si le asignamos el siguiente c&oacute;digo CSS:</p>
<pre class="code">#flecla {
display: block;
width: 0;
height: 0;
border: 10px solid red;
}</pre>
<p>Est&eacute; c&oacute;digo genera un cuadrado rojo con anchura 10 px. Ahora bien el truco consiste en los bordes transparentes. Si hacemos que 3 de los 4 bordes sean transparentes, entonces conseguiremos la flecha buscada, concretamente una flecha con &aacute;ngulos de 45&ordm;.</p>
<p>Esto lo conseguimos a&ntilde;adiendo al CSS anterior:</p>
<pre class="code">border-width: 10px;
border-color: red transparent transparent transparent;</pre>
<p>Esto genera una flecha hacia abajo. Si el color rojo lo colocamos a la derecha entonces tendremos una fecha hacia la izquierda, es decir, siempre se genera la punta hacia el centro de la capa, el lado contrario a donde coloquemos el color. Eso s&iacute; no solo se pueden hacer formas triangulares de 45&ordm;, estos &aacute;ngulos se pueden variar jugando con los tama&ntilde;os de los bordes.</p>
<p>Ejemplo:</p>
<pre class="code">border-width: 40px 10px 10px 10px;</pre>
<p>Jugando con el tama&ntilde;o del lado donde le damos el color haremos que la flecha se haga m&aacute;s larga, imitando a un bander&iacute;n. Esto se aplica a todos los lados, es decir si al bottom le incrementamos el tama&ntilde;o este se har&aacute; m&aacute;s largo por tanto si lo reducimos a 0 alcanzaremos un &aacute;ngulo de 90&ordm;.</p>
<p>Es posible llegar a realizar la bandera de Inglaterra solo con CSS, puesto que se compone de una serie de tri&aacute;ngulos. Para colocar una capa con esquinas triangulares, basta poner dicha forma con posici&oacute;n absoluta y colocar otra capa extra como lateral para cubrir donde termina la forma triangular.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=108</wfw:commentRss>
			<slash:comments>1</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/como-crear-triangulos-con-css.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Detectar la orientación de una foto con PHP</title>
			<link>http://www.imaginanet.com/blog/detectar-la-orientacion-de-una-foto-con-php.html</link>
			<guid>http://www.imaginanet.com/blog/detectar-la-orientacion-de-una-foto-con-php.html</guid>
			<comments>http://www.imaginanet.com/blog/detectar-la-orientacion-de-una-foto-con-php.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Sun,  6 May 2012 19:34:37 +0100</pubDate>
					<category><![CDATA[Web 2.0]]></category>
					<category><![CDATA[PHP]]></category>
					<description><![CDATA[Para detectar la orientaci&oacute;n de una foto sacada con tu c&aacute;mara digital deberemos obtener la informaci&oacute;n Exif (Exchangeable image file format) de la foto. Esta informaci&oacute;n est&aacute; presente en los formatos JPEG y TIFF generados por la mayor&iacute;a de las c&aacute;maras digitales.
Con PHP esto es muy...]]></description>
			<content:encoded><![CDATA[><p>Para detectar la orientaci&oacute;n de una foto sacada con tu c&aacute;mara digital deberemos obtener la informaci&oacute;n Exif (Exchangeable image file format) de la foto. Esta informaci&oacute;n est&aacute; presente en los formatos JPEG y TIFF generados por la mayor&iacute;a de las c&aacute;maras digitales.</p>
<p>Con PHP esto es muy sencillo si tenemos instalada la extensi&oacute;n Exif. Lo que tenemos que hacer es detectar la informaci&oacute;n de la orientaci&oacute;n de la imagen y rotarla usando la librer&iacute;a GD.</p>
<p>Vamos a ver un ejemplo de como hacerlo:</p>
<pre class="code php">class Photo {

	private static function mirrorImage ( $imgsrc ) {
		$width = imagesx ( $imgsrc );
		$height = imagesy ( $imgsrc );

		$src_x = $width -1;
		$src_y = 0;
		$src_width = -$width;
		$src_height = $height;

		$imgdest = imagecreatetruecolor ( $width, $height );

		if ( imagecopyresampled ( $imgdest, $imgsrc, 0, 0, $src_x, $src_y, $width, $height, $src_width, $src_height ) ) {
			return $imgdest;
		}

		return $imgsrc;
	}

	public static function adjustPhotoOrientation($full_filename) {        
		$exif = exif_read_data($full_filename);
		if($exif &amp;&amp; isset($exif['Orientation'])) {
			$orientation = $exif['Orientation'];
			if($orientation != 1){
				$img = imagecreatefromjpeg($full_filename);

				$mirror = false;
				$deg    = 0;

				switch ($orientation) {
					case 2:
						$mirror = true;
						break;
					case 3:
						$deg = 180;
						break;
					case 4:
						$deg = 180;
						$mirror = true;  
						break;
					case 5:
						$deg = 270;
						$mirror = true; 
						break;
					case 6:
						$deg = 270;
						break;
					case 7:
						$deg = 90;
						$mirror = true; 
						break;
					case 8:
						$deg = 90;
						break;
				}
				if ($deg) $img = imagerotate($img, $deg, 0); 
				if ($mirror) $img = self::mirrorImage($img);
				
				imagejpeg($img, $full_filename);
			}
		}
		return true;
	}

	
}
</pre>
<p>Ahora solo tenemos que hacer Photo::adjustPhotoOrientation($ruta_absoluta_de_la_imagen) y ya tenemos la foto rotada correctamente.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=107</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/detectar-la-orientacion-de-una-foto-con-php.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Gestores de correo electrónico para Android (Una alternativa al predeterminado GMAIL)</title>
			<link>http://www.imaginanet.com/blog/gestores-de-correo-electronico-para-android-una-alternativa-al-predeterminado-gmail.html</link>
			<guid>http://www.imaginanet.com/blog/gestores-de-correo-electronico-para-android-una-alternativa-al-predeterminado-gmail.html</guid>
			<comments>http://www.imaginanet.com/blog/gestores-de-correo-electronico-para-android-una-alternativa-al-predeterminado-gmail.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Fri, 20 Apr 2012 11:00:16 +0100</pubDate>
					<category><![CDATA[Android]]></category>
					<category><![CDATA[Correo Electrónico]]></category>
					<description><![CDATA[Cada vez, son m&aacute;s los dispositivos que utilizan el sistema operativo Android. Generalmente, para la gesti&oacute;n de nuestro correo elect&oacute;nico siempre empleamos las opciones que vienen por defecto en el aparato para la creaci&oacute;n de cuentas de correo, ya que nos permiten una configuraci&oacute;n...]]></description>
			<content:encoded><![CDATA[><p>Cada vez, son m&aacute;s los dispositivos que utilizan el sistema operativo Android. Generalmente, para la gesti&oacute;n de nuestro correo elect&oacute;nico siempre empleamos las opciones que vienen por defecto en el aparato para la creaci&oacute;n de cuentas de correo, ya que nos permiten una configuraci&oacute;n autom&aacute;tica en unos pocos segundos. El problema de esto, es que estas opciones est&aacute;n limitadas a proveedores de correo conocidos o m&aacute;s populares, como hotmail, google mail, etc.</p>
<p>Si queremos configurar una cuenta de correo alternativa a la que ya tenemos por defecto, como por ejemplo la <strong>cuenta de la empresa</strong>, debemos utilizar alguna aplicaci&oacute;n alternativa, ya que las empresas, suelen tener su propio servidor para la gesti&oacute;n del correo con sus propios par&aacute;metros de configuraci&oacute;n. Dependiendo de la versi&oacute;n de Android, es posible que se disponga de una aplicaci&oacute;n predeterminada de sistema alternativa a la configuraci&oacute;n autom&aacute;tica mediante asistente, que nos permite configurar nuestro correo, pero como en principio, no se sabe que versi&oacute;n del sistema tendr&aacute; el usuario, hay que buscar una alternativa que nos permita, configurar el correo de forma manual en funci&oacute;n de los par&aacute;metros de nuestro servidor.</p>
<p>MAILDROID</p>
<p>MailDroid, es una aplicaci&oacute;n que nos permite configurar cualquier cuenta de correo electr&oacute;nico, ya sea de un proveedor conocido como hotmail, google mail, o de un servidor de nuestra empresa. Esta aplicaci&oacute;n funciona correctamente en versiones de android 2.2 y 2.3 (&eacute;sta &uacute;ltima la hemos usado para la configuraci&oacute;n de una cuenta de empresa y funciona correctamente).</p>
<p>&nbsp;</p>
<p>&iquest;C&oacute;mo instalo MailDroid en mi tablet o smartphone Android?</p>
<p>Teniendo acceso a Android Market, basta con buscar "maildroid" y saldr&aacute; como primer resultado. Lo descargamos y una vez instalado lo arrancamos y aceptamos la licencia de usuario final. La aplicaci&oacute;n est&aacute; en ingl&eacute;s.</p>
<p>&iquest;C&oacute;mo configuro mi cuenta de correo de la empresa o de cualquier otro servidor?</p>
<p>Una vez que hemos instalado la aplicaci&oacute;n y aceptado los t&eacute;rminos de licencia, nos aparecer&aacute;n las opciones de configuraci&oacute;n para ingresar nuestros datos de la cuenta de correo y el modo de configuraci&oacute;n que queremos emplear. Disponemos de tres opciones: Autom&aacute;tica, manual e importar configuraci&oacute;n.</p>
<p>Autom&aacute;tica. La configuraci&oacute;n autom&aacute;tica, evita al usuario tener que conocer par&aacute;metro alguno sobre la configuraci&oacute;n de su servidor entrante y saliente de&nbsp; correo. Esta opci&oacute;n solo funciona con servidores de correo conocidos o que utilizan una configuraci&oacute;n est&aacute;ndar.</p>
<p>Manual. Esta&nbsp; opci&oacute;n es la que se deber&aacute; utilizar para&nbsp; configurar una cuenta de correo que prtenezca a un dominio propio y no est&aacute;ndar, para ello necesitamos conocer los siguientes par&aacute;metros del servidor:</p>
<ul>
<li>Servidor entrante: Define el servidor que utilizar&aacute; nuestra cuenta para recibir los correos (IMAP o POP3).</li>
<li>Puerto y seguridad del servidor entrante. Debemos conocer cual es el puerto que utiliza el servidor de correo y si requiere de alg&uacute;n tipo de seguridad (SSL o TLS).</li>
<li>Servidor de correo Saliente (smtp) define el servidor de correo que se utilizar&aacute; para el env&iacute;o de correos.</li>
<li>Puerto y seguridad del servidor de correo saliente. Debemos conocer el puerto que utiliza el servidor de correo smtp (normalmente es el 25) y si requiere cifrado (TLS o SSL). adem&aacute;s, tenemos que marcar la opci&oacute;n que indica: usar los mismos credenciales, para que utilice los mismos datos de usuario y contrase&ntilde;a para el servidor de correo saliente SMTP que para el servidor de correo entrante.</li>
</ul>
<p><img style="display: block; margin-left: auto; margin-right: auto;" title="Mail Droid (Pantalla de configuraci&oacute;n)" src="http://www.imaginanet.com/ftp/blog/correoMovil/android1.jpg" alt="Pantalla de configuraci&oacute;n de mail Droid" width="320" height="533" /></p>
<p>Destacar que se est&aacute; empleando la configuraci&oacute;n mediante el protocolo IMAP, pero para el protocolo POP3, ser&iacute;a similar.</p>
<p>Una vez que tenemos todos los par&aacute;metros de configuraci&oacute;n establecidos y continuamos con el asistente, se validar&aacute; nuestra configuraci&oacute;n con un correo de prueba. si todo funciona bien, tendremos una patalla principal, con la bandeja de entrada de nuestro correo.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" title="Correlo (Pantalla principal)" src="http://www.imaginanet.com/ftp/blog/correoMovil/androidPantallaPrincipal.jpg" alt="Pantalla principal de la bandeja de entrada del correo elect&oacute;nico" width="480" height="854" /></p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=106</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/gestores-de-correo-electronico-para-android-una-alternativa-al-predeterminado-gmail.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Importación de correo electrónico a Google Apps</title>
			<link>http://www.imaginanet.com/blog/importacion-de-correo-electonico-a-google-apps.html</link>
			<guid>http://www.imaginanet.com/blog/importacion-de-correo-electonico-a-google-apps.html</guid>
			<comments>http://www.imaginanet.com/blog/importacion-de-correo-electonico-a-google-apps.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Thu, 12 Apr 2012 16:12:52 +0100</pubDate>
					<category><![CDATA[Correo Electrónico]]></category>
					<category><![CDATA[Google Apps]]></category>
					<description><![CDATA[En esta peque&ntilde;a gu&iacute;a se explicar&aacute; como importar los correos que tengamos en otra cuenta a una cuenta GMail en Google Apps.
En primer lugar se necesita un cliente de correo para configurar las dos cuentas, tanto aquella desde la que queremos exportar como la cuenta destino de Google Apps. En este caso se...]]></description>
			<content:encoded><![CDATA[><p>En esta peque&ntilde;a gu&iacute;a se explicar&aacute; como importar los correos que tengamos en otra cuenta a una cuenta <em>GMail</em> en <em>Google Apps</em>.</p>
<p>En primer lugar se necesita un <em>cliente de correo</em> para configurar las dos cuentas, tanto aquella desde la que queremos <em>exportar</em> como la cuenta destino de Google Apps. En este caso se utilizar&aacute; <em>Microsoft Outlook</em>, aunque tambi&eacute;n se pueden utilizar otros clientes de correo como <em>Thunderbird</em>.</p>
<p>Una vez que ya tenemos instalado el cliente de correo procedemos a las configuraci&oacute;n de las cuentas origen y destino.  Es importante destacar que para la cuenta de Google Apps se debe habilitar el protocolo <em>IMAP</em> en la configuraci&oacute;n de la cuenta.</p>
<p>Para habilitar el protocolo <em>IMAP</em> vamos a la pantalla de configuraci&oacute;n de nuestra cuenta de <em>Google Mail</em>, y en la pesta&ntilde;a de <em><strong>Reenv&iacute;o y correo POP/IMAP</strong></em>, habilitamos el protocolo <em>IMAP</em> como se muestra en la imagen.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" title="Habilitar IMAP y POP3" src="http://www.imaginanet.com/ftp/blog/Importacion de Correo/imapConfig.jpg" alt="habilitar imap y POP3 en cuentas de google" width="791" height="400" /></p>
<p>&nbsp;</p>
<p>Una vez que hemos configurado el correo de Google Apps vamos a <em>Outlook</em>. En la pantalla principal del programa vamos a <strong>Herramientas &gt;</strong> <strong>Configuraci&oacute;n</strong> <strong>de Cuenta</strong> y nos aparecer&aacute; una pantalla como esta:</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" title="Configuraci&oacute;n de cuentas (Pantalla principal)" src="http://www.imaginanet.com/ftp/blog/Importacion de Correo/configuracionCuentasPrincipal.jpg" alt="Pantalla principal de la configuraci&oacute;n de cuentas de Outlook" width="602" height="500" /></p>
<p>&nbsp;</p>
<p>A continuaci&oacute;n creamos una nueva cuenta. (Opci&oacute;n <strong>Nuevo</strong>) En la patalla que se despliega seleccionamos la opci&oacute;n <strong>Microsoft Exchange, POP, IMAP o HTTP</strong> y en la siguiente la opci&oacute;n de configuraci&oacute;n manual y seleccionamos la opci&oacute;n <strong>Correo electr&oacute;nico de Internet</strong> y pasamos a la siguiente pantalla:</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" title="Selecci&oacute;n de Configuraci&oacute;n" src="http://www.imaginanet.com/ftp/blog/Importacion de Correo/configuracionCuentasPantallaTipoConfiguracion.jpg" alt="Configuraci&oacute;n autom&aacute;tica o manual de la cuenta de correo." width="564" height="400" /></p>
<p>&nbsp;</p>
<h3>Datos para la configuraci&oacute;n de la cuenta de correo GMail</h3>
<p>Una vez en esta pantalla introducimos los datos que nos pide. Hay que tener en cuenta que los datos que se tienen que introducir en este paso, dependen del <em>proveedor de correo </em>al que pertenezca la cuenta, pero se hace de forma id&eacute;ntica para todas las cuentas que deseemos configurar. Para el caso de una cuenta de <em>Google Mail</em>, los par&aacute;metros a introducir son los siguientes:</p>
<ul>
<li>
<p><strong>Su nombre</strong>: 	Un nombre o alias. Ej: Mario.</p>
</li>
<li>
<p><strong>Direcci&oacute;n 	de Correo Electr&oacute;nico</strong>: La direcci&oacute;n de la cuenta a configurar 	ej: info@imaginanet.com</p>
</li>
<li>
<p><strong>Tipo de 	cuenta</strong>: En nuestro caso IMAP, aunque tambi&eacute;n se puede utilizar 	el protocolo POP3.</p>
</li>
<li>
<p><strong>Servidor 	de correo entrante</strong>: imap.googlemail.com</p>
</li>
<li>
<p><strong>Servidor 	de correo saliente</strong> (SMTP): smtp.googlemail.com</p>
</li>
<li>
<p><strong>Nombre de usuario y Contrase&ntilde;a</strong>: Datos de la cuenta de correo 	a configurar.</p>
</li>
<li>
<p>En el bot&oacute;n m&aacute;s configuraciones podemos acceder a opciones 	avanzadas para configurar el tipo de cifrado que necesita nuestra 	cuenta tanto para el servidor de correo entrante como el de correo 	saliente, as&iacute; como los puertos sobre los que trabajan los mismos.</p>
<ul>
<li>
<p><strong>Puerto imap</strong>: 993</p>
</li>
<li>
<p><strong>Puerto smtp</strong>: 465</p>
</li>
</ul>
</li>
</ul>
<p><img style="display: block; margin-left: auto; margin-right: auto;" title="Configuraci&oacute;n de cuenta. Paso 1" src="http://www.imaginanet.com/ftp/blog/Importacion de Correo/configProces1.jpg" alt="Configuraci&oacute;n de cuenta Paso1" width="500" height="432" /></p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" title="configuraci&oacute;n de cuenta. Paso 2" src="http://www.imaginanet.com/ftp/blog/Importacion de Correo/configProces2.jpg" alt="configuraci&oacute;n de cuenta. Paso 2" width="500" height="339" /></p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" title="Configuraci&oacute;n de cuentas. Paso 3" src="http://www.imaginanet.com/ftp/blog/Importacion de Correo/configProces3.jpg" alt="Configuraci&oacute;n de cuenta. Paso 3" width="480" height="390" /></p>
<h3>&iquest;C&oacute;mo importamos el correo electr&oacute;nico de GMail a otra cuenta?</h3>
<p>Una vez que ya hemos configurado todos los parametros de la cuenta pulsamos en el bot&oacute;n <em>Probar configuraci&oacute;n de cuenta</em> y si no hay  errores, s&oacute;lo queda finalizar el asistente de configuraci&oacute;n.</p>
<p>Este proceso se repetir&iacute;a tantas veces como cuentas necesitemos configurar. Una vez que tengamos las dos cuentas configuradas, la de <em>Google Apps</em> y la  cuenta de la que queremos importar el correo, basta con seleccionar la bandeja de entrada y las carpetas que tengamos en el correo origen y arrastrar el contenido de las mismas  a la cuenta de Google.</p>
<ul>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=105</wfw:commentRss>
			<slash:comments>1</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/importacion-de-correo-electonico-a-google-apps.html</feedburner:origLink>
		</item>
				
		<item>
			<title>GOOGLE APPS ¿QUE TE OFRECE?</title>
			<link>http://www.imaginanet.com/blog/google-apps-que-te-ofrece.html</link>
			<guid>http://www.imaginanet.com/blog/google-apps-que-te-ofrece.html</guid>
			<comments>http://www.imaginanet.com/blog/google-apps-que-te-ofrece.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed, 11 Apr 2012 16:19:59 +0100</pubDate>
					<category><![CDATA[Google Apps]]></category>
					<description><![CDATA[Google Apps es un conjunto de aplicaciones que nos permite organizar de forma sencilla todo nuestro trabajo, y la  comunicaci&oacute;n entre los distintos trabajadores con diversas herramientas  para la gesti&oacute;n del correo electr&oacute;nico, mensajer&iacute;a instant&aacute;nea, planificaci&oacute;n de reuniones y tareas,...]]></description>
			<content:encoded><![CDATA[><p>Google Apps es un conjunto de aplicaciones que nos permite organizar de forma sencilla todo nuestro trabajo, y la  comunicaci&oacute;n entre los distintos trabajadores con diversas herramientas  para la gesti&oacute;n del correo electr&oacute;nico, mensajer&iacute;a instant&aacute;nea, planificaci&oacute;n de reuniones y tareas, generaci&oacute;n de documentos hojas de c&aacute;lculo, etc. Adem&aacute;s, tambi&eacute;n dispone de mecanismos de seguridad para empresas mas espec&iacute;ficos para el control de cuentas con contrase&ntilde;as personalizadas y restricciones de acceso espec&iacute;ficas.</p>
<p>Existen dos ediciones de <span style="text-decoration: underline;">Google Apps:</span><strong> la edici&oacute;n gratuita</strong>, que nos permite probar el conjunto de herramientas, pero de forma mas limitada, y <strong>la edici&oacute;n Business</strong>, que contiene todo el potencial de Google Apps pensado para empresas.</p>
<h2><span style="font-size: medium;"><strong>Google APPS Gratuito</strong></span></h2>
<p>Esta es una versi&oacute;n b&aacute;sica de Google Apps con las herramientas principales de comunicaci&oacute;n, as&iacute; como las de generaci&oacute;n de documentos, adem&aacute;s de tener la posibilidad de crear blogs o de publicitar la empresa o el dominio que se desee. Con esta edici&oacute;n podemos probar durante 30 d&iacute;as y con un limite m&aacute;ximo de 10 usuarios herramientas como Google Mail, Google Calendar, Google Docs, Google Sites, Blogger, AdWords, etc.</p>
<h2><span style="font-size: medium;"><strong>Google Apps for Business</strong></span></h2>
<p>Esta es una edici&oacute;n de pago que nos ofrece adem&aacute;s de lo anteriormente mencionado, una serie de ventajas frente a su edici&oacute;n gratuita, como son:</p>
<ul>
<li>
<p><em><span style="text-decoration: underline;">Sistemas de seguridad 		avanzados</span></em>. Nos  permite emplear mecanismos como SSO o SSL, 		adem&aacute;s de tener requisitos de contrase&ntilde;a personalizada y otras 		funciones.</p>
</li>
<li>
<p><em><span style="text-decoration: underline;">Mayor espacio de 		almacenamiento por usuario e interoperabilidad entre dispositivos 		m&oacute;viles y el PC</span></em>. Se dispone de una capacidad de 		almacenamiento de 25 GB por usuario y de la posibilidad de 		sincronizar el correo y de <em>Google Mail</em> y las tareas de 		<em>Google Calendar</em> con dispositivos m&oacute;viles como <em>Black 		Berry,</em> <em>IPhone</em> o sistemas <em>Android</em>.</p>
</li>
<li>
<p><span style="text-decoration: underline;">Fiabilidad</span>. Google 		 garantiza un tiempo de funcionamiento del sistema de un 99,9%, por lo 		 que siempre tendremos acceso a nuestra cuenta. Tambi&eacute;n se cuenta 		con  replicaci&oacute;n s&iacute;ncrona.</p>
</li>
<li>
<p><span style="text-decoration: underline;">Aplicaciones adicionales</span> para empresas como Google Video for Business y Google Groups for 		Business.</p>
</li>
<li>
<p><span style="text-decoration: underline;">Acceso 		a las aplicaciones de mensajer&iacute;a para m&oacute;viles</span> de 		calendario y de correo electr&oacute;nico.</p>
</li>
<li>
<p><span style="text-decoration: underline;">Asistencia 		t&eacute;cnica</span>,<em> </em>ya  sea telef&oacute;nica o por 		correo electr&oacute;nico, siendo ininterrumpida en caso  de incidencias 		graves. Adem&aacute;s tambi&eacute;n dispone de un servicio de  asistencia online 		para que el propio usuario pueda resolver las  incidencias.</p>
</li>
<li>
<p><span style="text-decoration: underline;">Sin 		limite de cuentas de usuario</span>, 		ya que podemos crear tantas cuentas como se necesiten.</p>
</li>
</ul>
<ul>
</ul>
<p><span style="text-decoration: underline;"><strong>Costes del servicio.</strong></span></p>
<p>Podemos contratar Google Apps for Bussines en dos modalidades, una mensual y otra anual.</p>
<p><em><strong>Modalidad Mensual</strong></em>. En  este caso, pagamos un precio de 4 &euro; por cuenta de usuario que creemos al mes, de forma indefinida a menos que demos de baja el servicio.</p>
<p><em><strong>Modalidad Anual</strong></em>. En este caso el coste es de un total de 40 &euro; anuales por cuenta de usuario creada, siendo 8 &euro; menor que en el caso de la modalidad mensual, pero con la condici&oacute;n de que se debe mantener el servicio durante un a&ntilde;o.</p>
<h2><span style="font-size: medium;"><strong>Herramientas de uso habitual</strong></span></h2>
<p>A continuaci&oacute;n se explicar&aacute; brevemente lo que nos ofrecen algunas de las herramientas mas utilizadas dentro de Google Apps para que se tenga una mejor visi&oacute;n sobre el funcionamiento de este sistema. Se debe tener en cuenta, que algunas de las opciones que ofrecen estas herramientas s&oacute;lo est&aacute;n disponibles para la <em>E</em><em>dici&oacute;n Business</em> de Google Apps.</p>
<h3><em><strong>Google <span style="text-decoration: underline;">Mail</span></strong></em></h3>
<p>Esta aplicaci&oacute;n nos permite gestionar nuestro correo electr&oacute;nico de forma sencilla pudiendo clasificar nuestros mensajes en funci&oacute;n de un criterio de etiquetas que nos permite saber cuales la importancia de los mismos, pudiendo organizarlos por medio de estas etiquetas de relevancia. Adem&aacute;s, tambi&eacute;n disponemos de un sistema de b&uacute;squeda que utiliza el motor de google para encontrar f&aacute;cilmente los mensajes de correo electr&oacute;nico .</p>
<p>Por otra parte, se dispone de accesibilidad total desde cualquier dispositivo ya sea m&oacute;vil o PC, ya que es posible acceder mediante la web de Google, o bien mediante la aplicaci&oacute;n movil de Google Mail para <em>Android</em>, <em>IPhone</em> o <em>BlackBerry</em>.</p>
<p>Por &uacute;ltimo, el filtro antispam nos permite evitar el correo malicioso y evita que se pierda tiempo eliminando mensajes basura.</p>
<h3><em><strong>Google Calendar</strong></em></h3>
<p>Google Calendar es una aplicaci&oacute;n de planificaci&oacute;n de reuniones y proyectos que est&aacute; totalmente integrada con Google Mail, por lo que su acceso es rapido y sencillo.</p>
<p><em>&iquest;Qu&eacute; nos permite hacer Google Calendar?</em></p>
<p>Con esta aplicaci&oacute;n podemos comprobar f&aacute;cilmente la disponibilidad de los empleados para las a la hora de asignar tareas o concretar reuniones con la posibilidad de superponer varios calendarios al mismo tiempo para poder tener una visi&oacute;n cronol&oacute;gica global de todos los eventos asignados a todos los empleados.</p>
<p>Por otra parte, tambien se dispone de una gran accesibilidad, gracias a la integraci&oacute;n con el correo electr&oacute;nico y el acceso mediante dispositivos m&oacute;viles. Adem&aacute;s se pueden utilizar los calendarios de manera compartida donde el administrador puede gestionar los permisos que tienen los usuarios con los que comparte el calendario, de forma que se garantiza la seguridad y la privacidad. Tambi&eacute;n es posible publicar calendarios de forma sencilla en la web de la empresa.</p>
<h3><em><strong>Google Docs</strong></em></h3>
<p>Esta herramienta es un conjunto de aplicaciones ofim&aacute;ticas que nos permiten editar y crear documentos, presentaciones , dibujos y hojas de c&aacute;lculo desde el navegador sin necesidad de instalar complemento o aplicaci&oacute;n alguna.</p>
<p>Nos ofrece un entorno que puede compartirse con m&uacute;ltiples usuarios que tendr&aacute;n una serie de permisos gestionados por el administrador que comparte el documento, adem&aacute;s del hecho de que estos documentos podr&aacute;n ser editados de forma simultanea por todos los usuarios al mismo tiempo, lo que permite que cada usuario tenga sus propias anotaciones dentro del documento y los dem&aacute;s puedan guiarse por ellas para una mejor cohesi&oacute;n a la hora de trabajar.</p>
<p>Al igual que Google Calendar, Google Docs, nos permite acceder a nuestros documentos desde cualquier parte, incluso desde el tel&eacute;fono m&oacute;vil, teniendo la posibilidad de trabajar sin conexi&oacute;n a internet. Adem&aacute;s, se realiza una copia de seguridad de todos los archivos, para garantizar que nunca se pierda informaci&oacute;n, o en su caso, minimizar las perdidas.</p>
<p>Tambi&eacute;n es posible utilizar la aplicaci&oacute;n <em>Google Groups</em> para compartir documentos directamente a grupos de personas en lugar de a una persona concreta, haciendo mas f&aacute;cil y r&aacute;pida la gesti&oacute;n de usuarios que tienen acceso a los distintos documentos.</p>
<h3><em><strong>Google Talk</strong></em></h3>
<p>Es una aplicaci&oacute;n de mensajer&iacute;a, que funciona de forma similar al <em>Messenger</em> de <em>Microsoft</em> o <em>Skype</em>, pero para cuentas de <em>Google Mail</em>. Nos permite realizar <span style="text-decoration: underline;">llamadas de voz</span> y enviar <span style="text-decoration: underline;">mensajes instant&aacute;neos</span> a todos los contactos que tengamos en nuestra cuenta de Google siempre que estos tengan una cuenta de Google tambi&eacute;n, para asegurar todas las funcionalidades de la aplicaci&oacute;n. Es posible utilizar la funcionalidad de mensajer&iacute;a instant&aacute;nea de Google Talk con otros usuarios que tengan cuentas de <em>Windows</em> <em>Live</em> o <em>Yahoo</em> por ejemplo, pero no se garantiza que las funcionalidades respondan igual de bien por cuestiones de compatibilidad entre protocolos de comunicaci&oacute;n, ya que para estos casos se utiliza una pasarela que hace posible la comunicaci&oacute;n entre cuentas, pero existen algunos problemas de funcionamiento.</p>
<p>Google Talk, dispone de una versi&oacute;n descargable para PC y Android que contiene todas las funcionalidades mencionadas. Existe una versi&oacute;n web  integrada con el correo electr&oacute;nico que tiene funci&oacute;n de chat para poder enviar mensajes instant&aacute;neos a tus contactos. Adem&aacute;s, tambi&eacute;n se puede instalar un complemento para Google Talk para poder realizar videollamadas.</p>
<h3><em><strong>Google Sites</strong></em></h3>
<p>Esta aplicaci&oacute;n nos permite crear peque&ntilde;os sitios web donde podemos  compartir enlaces, documentos, v&iacute;deos, etc. Se facilitan plantillas para diferentes tipos de web que nos hacen mas sencilla la creaci&oacute;n de nuestro sitio en funci&oacute;n de para qu&eacute; lo queramos, ya sean Intranets, proyectos, entre otros.</p>
<p>Esta aplicaci&oacute;n nos puede ser &uacute;til para centralizar por ejemplo todo el contenido relacionado con un proyecto concreto.</p>
<p>Adem&aacute;s de las aplicaciones que se han descrito en este documento, disponemos de otras que tambi&eacute;n pueden ser de inter&eacute;s, como Google Video, Google AdWords (para cuestiones de publicidad sobre la empresa) o un Maket Place para las aplicaciones de la empresa.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=104</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/google-apps-que-te-ofrece.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Instalación y configuración de un servidor Apache  con PHP y MySQL (Parte 1)</title>
			<link>http://www.imaginanet.com/blog/instalacion-y-configuracion-de-un-servidor-apache-con-php-y-mysql-parte-1.html</link>
			<guid>http://www.imaginanet.com/blog/instalacion-y-configuracion-de-un-servidor-apache-con-php-y-mysql-parte-1.html</guid>
			<comments>http://www.imaginanet.com/blog/instalacion-y-configuracion-de-un-servidor-apache-con-php-y-mysql-parte-1.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed, 11 Apr 2012 10:35:40 +0100</pubDate>
					<category><![CDATA[Servidores y Seguridad]]></category>
					<category><![CDATA[Linux]]></category>
					<description><![CDATA[Existen multitud de herramientas para instalar y configurar f&aacute;cilmente un servidor Apache con MySQL tanto en Windows como en Linux, que nos permiten tener un sistema local para hacer nuestras pruebas en el mundo de la web, pero a nivel local y sin los problemas de seguridad que puede dar un servidor real.
El uso de...]]></description>
			<content:encoded><![CDATA[><p>Existen multitud de herramientas para instalar y configurar f&aacute;cilmente un servidor Apache con MySQL tanto en Windows como en Linux, que nos permiten tener un sistema local para hacer nuestras pruebas en el mundo de la web, pero a nivel local y sin los problemas de seguridad que puede dar un servidor real.</p>
<p>El uso de herramientas de este tipo viene bien cuando no queremos complicarnos demasiado con la configuraci&oacute;n de PHP, MySQL y Apache. De esta forma tenemos una configuraci&oacute;n b&aacute;sica de apache sin problemas y perf&eacute;ctamente funcional. Herramientas como  EasyPHP (<span style="color: #000080;"><span style="text-decoration: underline;"><a href="http://www.easyphp.org/">http://www.easyphp.org/</a></span></span>) para Windows o  XAMPP para Linux que se puede encontrar en la web <span style="color: #000080;"><span style="text-decoration: underline;"><a href="http://sourceforge.net/">http://sourceforge.net</a></span></span>, son algunos ejemplos de &eacute;sto.</p>
<p>En esta primera parte se va a explicar lo necesario para instalar un servidor Apache en Linux, as&iacute; como las diferentes opciones de configuraci&oacute;n del servidor de las que disponemos en el fichero <em>httpd.conf</em></p>
<p><em><br /></em></p>
<h3>Instalaci&oacute;n de Apache en Linux</h3>
<p>A d&iacute;a de hoy los gestores de paquetes  disponen de la mayor&iacute;a de aplicaciones en los repositorios que vienen de serie en las distintas distribuciones, especialmente si utilizamos Ubuntu que facilita bastante la instalaci&oacute;n de aplicaciones en nuestro sistema.</p>
<p>En nuestro caso utilizaremos el gestor de paquetes <em>apt-get</em> que nos permitir&aacute; de forma sencilla descargar e instalar una versi&oacute;n de Apache. Para instalar nuestro servidor apache ejecutamos:</p>
<pre class="code">sudo apt-get install apache2</pre>
<p>Una vez que ha terminado el proceso ya tenemos nuestro servidor Apache en funcionamiento. Ahora tenemos que comprobar que  el servidor responde a nuestras peticiones. Para eso abrimos nuestro navegador web habitual e introducimos la direcci&oacute;n <span style="color: #000080;"><span style="text-decoration: underline;"><a href="http://127.0.0.1/">http://127.0.0.1</a></span></span>. De esta forma obtendremos una web con un texto que dice: <strong>IT'S WORKS!</strong> Esto indica que Apache est&aacute; respondiendo a nuestras peticiones.</p>
<p>&nbsp;</p>
<h3>Funcionamiento b&aacute;sico del sistema de directivas de Apache. Ejemplo de configuraci&oacute;n</h3>
<p>Ahora que ya disponemos de nuestro servidor, tenemos que saber como configurarlo correctamente para lo que queramos hacer. Para ello, vamos a describir el funcionamiento b&aacute;sico del fichero <em><strong>httpd.conf</strong></em> que podemos encontrar normalmente en la ruta <em>/etc/apache2/httpd.conf</em>.</p>
<p>La configuraci&oacute;n de Apache se basa en un sistema de directivas que se aplican de forma general o bien en secciones concretas (un directorio o una IP por ejemplo). Todos los par&aacute;metros que se le pueden aplicar al fichero <em>httpd.conf</em> se denominan directivas. Estas directivas son de dos tipos:</p>
<p><strong>Directivas generales</strong>. Las directivas generales son aquellas que se aplican a todo el servidor, de forma que lo que indique afectar&aacute; a toda petici&oacute;n que se realice a dicho servidor. Por ejemplo si en nuestro fichero <em>httpd.conf</em> indicamos lo siguiente.</p>
<pre class="code">DirectoryIndex index.php</pre>
<p>esta directiva le esta diciendo al servidor que el fichero a buscar cuando el cliente solicita una web a este servidor, ser&aacute; index.php. Es posible a&ntilde;adir mas de un fichero separado por espacios.</p>
<p><em><strong>Directivas de secci&oacute;n</strong></em>. A diferencia de las generales, las directivas de secci&oacute;n solo afectan a partes concretas del servidor (un directorio, un dominio o subdominio, etc.).</p>
<p>Se puede decir que las directivas de secci&oacute;n nos permiten agrupar directivas generales, y que mientras que las primeras permiten establecer un &aacute;mbito de efecto dentro del servidor por s&iacute; solas, las segundas afectan a todo el servidor  a menos que est&eacute;n dentro de una directiva de secci&oacute;n.</p>
<p>Apache se divide en varios m&oacute;dulos cada uno de los cuales hace referencia a un grupo de directivas que tratan partes distintas del servidor, como puede ser el sistema de archivos, el n&uacute;cleo, etc. Los m&oacute;dulos de los que dispone Apache los podemos encontrar en la web de Apache <span style="color: #000080;"><span style="text-decoration: underline;"><a href="http://httpd.apache.org/docs/2.0/es/mod/">httpd.apache.org/docs/2.0/es/mod</a>/</span></span><span style="color: #000080;">.&nbsp;</span></p>
<p><span style="color: #000080;"><span style="color: #000000;">A continuaci&oacute;n se expone un ejemplo de configuraci&oacute;n de un servidor Apache para el caso en que queramos utlilizar </span></span><span style="color: #000080;"><span style="color: #000000;"><em>hosts virtuales</em></span></span><span style="color: #000080;"><span style="color: #000000;">:</span></span></p>
<pre class="code">NameVirtualHost 192.168.55.1
DirectoryIndex index.php
&lt;Directory /&gt;
order Deny, Allow
Deny from all
Allow from 192,168.55.1
&lt;/Directory&gt;
&lt;VirtualHost 192.168.55.1&gt;
DocumentRoot /web/miweb
ServerName www.miweb.midominio.es
&lt;/VirtualHost&gt;
&lt;VirtualHost 192.168.55.1&gt;
DocumentRoot /web/webmitio
ServerName www.webmitio.midominio.es
ServerAlias www.mitio.es
&lt;Directory /web/webmitio&gt;
order Deny, Allow
Allow from all
&lt;/Directory&gt;
&lt;/VirtualHost&gt;
</pre>
<p><span style="color: #000080;"><span style="color: #000000;">Esta configuraci&oacute;n es un ejemplo del uso de host virtuales. Como se puede ver, el fichero <em>httpd.conf</em> no es m&aacute;s que una serie de directivas generales y de secci&oacute;n que en este caso definen dos subdominios para el dominio </span></span><span style="color: #000080;"><span style="text-decoration: underline;"><a href="http://www.midomino.es/">www.midomino.es</a></span></span><span style="color: #000080;"><span style="color: #000000;">. Se suele utilizar cuando queremos alojar en un servidor mas de una web sin necesidad de comprar m&aacute;s de un dominio en la red, se conoce como servidor compartido. </span></span></p>
<p><span style="color: #000080;"><span style="color: #000000;">En nuestro ejemplo queremos alojar las web </span></span><span style="color: #000080;"><span style="text-decoration: underline;"><a href="http://www.miweb.midominio.es/">www.miweb.es</a></span></span><span style="color: #000080;"><span style="color: #000000;"> y </span></span><span style="color: #000080;"><span style="text-decoration: underline;"><a href="http://www.webmitio.midominio.es/">www.webmitio.es</a></span></span><span style="color: #000080;"><span style="color: #000000;"> en nuestro servidor Apache, pero tan s&oacute;lo disponemos del dominio </span></span><span style="color: #000080;"><span style="text-decoration: underline;"><a href="http://www.midominio.es/">www.midominio.es</a></span></span><span style="color: #000080;"><span style="color: #000000;"> y para ello se utilizan los hosts virtuales, de tal manera que se pueden crear subdominios para tener mas de una web usando los recursos de los que disponemos. De esta forma tenemos </span></span><span style="color: #000080;"><span style="text-decoration: underline;"><a href="http://www.miweb.midominio.es/">www.miweb.midominio.es</a></span></span><span style="color: #000080;"><span style="color: #000000;"> y </span></span><span style="color: #000080;"><span style="text-decoration: underline;"><a href="http://www.webmitio.midominio.es/">www.webmitio.midominio.es</a></span></span><span style="color: #000080;"><span style="color: #000000;"> en el servidor como subdominios de </span></span><span style="color: #000080;"><span style="text-decoration: underline;"><a href="http://www.midominio.es/">www.midominio.es</a></span></span><span style="color: #000080;"><span style="color: #000000;">.</span></span></p>
<p><span style="color: #000080;"><span style="color: #000000;"> </span></span><span style="color: #000080;"><span style="color: #000000;">Cada host virtual se trata como si fuese una m&aacute;quina independiente dentro del sistema, por lo que puede llevar sus propias directivas para dar o denegar permisos, establecer un alias para ese host virtual, etc. Cada una de las webs que se cren con hosting virtual tiene su propio direcotrio raiz que definimos con la directiva <em>DocumentRoot</em>, as&iacute; como un nombre de host que definiremos con la directiva <em>ServerName</em>. </span></span></p>
<p><span style="color: #000080;"><span style="color: #000000;">Adem&aacute;s, se le pueden incluir restricciones con directivas de secci&oacute;n como en el segundo de los casos del ejemplo. Con la directiva <em>Directory</em>, podemos crear restricciones a un directorio concreto. En este caso estamos dando permiso total al directorio raiz de la web. </span></span></p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=103</wfw:commentRss>
			<slash:comments>1</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/instalacion-y-configuracion-de-un-servidor-apache-con-php-y-mysql-parte-1.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Formularios en HTML5</title>
			<link>http://www.imaginanet.com/blog/formularios-en-html5.html</link>
			<guid>http://www.imaginanet.com/blog/formularios-en-html5.html</guid>
			<comments>http://www.imaginanet.com/blog/formularios-en-html5.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Sun, 25 Mar 2012 19:43:51 +0100</pubDate>
					<category><![CDATA[HTML5]]></category>
					<category><![CDATA[Web 2.0]]></category>
					<description><![CDATA[HTML5 nos ofrece nuevas opciones a la hora de crear formularios, como son nuevos tipos de campos y validaci&oacute;n autom&aacute;tica del lado del cliente, sin necesidad de scripts.
Aunque no todos los navegadores implementan todav&iacute;a todas estas nuevas caracter&iacute;sticas, siempre podemos utilizar alg&uacute;n script...]]></description>
			<content:encoded><![CDATA[><p>HTML5 nos ofrece nuevas opciones a la hora de crear formularios, como son nuevos tipos de campos y validaci&oacute;n autom&aacute;tica del lado del cliente, sin necesidad de scripts.</p>
<p>Aunque no todos los navegadores implementan todav&iacute;a todas estas nuevas caracter&iacute;sticas, siempre podemos utilizar alg&uacute;n script que nos permita su uso, como puede ser este <a href="http://code.google.com/p/html5form/">plugin de jquery</a></p>
<p>Veamos los nuevos tipos de campo que nos ofrece:</p>
<ul>
<li><strong>email</strong>: nos sirve para introducir direcciones de email</li>
<li><strong>url</strong>: para direcciones de p&aacute;ginas web</li>
<li><strong>number</strong>: para la introducci&oacute;n de n&uacute;meros</li>
<li><strong>tel</strong>: para n&uacute;meros de tel&eacute;fono</li>
<li><strong>search</strong>: para campos de b&uacute;squeda</li>
<li><strong>search</strong>: para campos de b&uacute;squeda</li>
<li><strong>datetime</strong>: para seleccionar fecha y hora</li>
<li><strong>date</strong>: para seleccionar una fecha</li>
<li><strong>month</strong>: para seleccionar un mes</li>
<li><strong>week</strong>: para seleccionar una semana</li>
<li><strong>time</strong>: para seleccionar una hora</li>
<li><strong>datetime-local</strong>: para seleccionar una fecha y una hora sin zona horaria</li>
<li><strong>range</strong>: para seleccionar entre un rango de valores</li>
<li><strong>color</strong>: para seleccionar un color en valor hexadecimal</li>
</ul>
<p>Nuevos atributos que nos ofrecen nuevas posibilidades:</p>
<ul>
<li><strong>placeholder</strong>: nos muestra un texto de ejemplo dentro de la caja de texto que desaparece cuando hacemos foco en &eacute;l.</li>
<li><strong>required</strong>: nos indica que ese campo no puede ser enviado vac&iacute;o, y debe cumplir las especificaciones del tipo de campo que sea, por ejemplo, en un campo tipo email debemos introducir una direcci&oacute;n de correo v&aacute;lida</li>
<li><strong>autofocus</strong>: Hace que el cursor se coloque autom&aacute;ticamente en ese campo sin necesidad de ning&uacute;n script.</li>
<li><strong>pattern</strong>: Expresi&oacute;n regular que debe coincidir con el valor correcto que queremos que introduzca el usuario.</li>
<li><strong>maxlength</strong>: En los textareas ahora podemos utilizar este atributo para limitar el n&uacute;mero m&aacute;ximo de caracteres introducidos.</li>
</ul>
<p>Estos son las principales novedades que nos ofrece HTML5, aunque hay muchas m&aacute;s que puedes consultar <a href="http://www.w3.org/TR/html5/">aqu&iacute;</a></p>
<p>Veamos un ejemplo de un formulario en HTML5 que muestre estas novedades:</p>
<pre class="code php">	&lt;form method="post" action="script_de_proceso.php" autocomplete="off"&gt;
		&lt;input type="text" placeholder="Nombre" name="nombre" value="" required autofocus&gt;
		&lt;input type="email" placeholder="Direcci&oacute;n de correo" name="email" value="" required&gt;
		&lt;textarea placeholder="Observaciones" name="observaciones" maxlength="200"&gt;&lt;/textarea&gt;
		&lt;input type="submit" name="enviar" value="Enviar"&gt;
	&lt;/form&gt;
</pre>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=102</wfw:commentRss>
			<slash:comments>2</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/formularios-en-html5.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Polyfills para CSS3 y HTML5</title>
			<link>http://www.imaginanet.com/blog/polyfills-para-css3-y-html5.html</link>
			<guid>http://www.imaginanet.com/blog/polyfills-para-css3-y-html5.html</guid>
			<comments>http://www.imaginanet.com/blog/polyfills-para-css3-y-html5.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 12 Mar 2012 08:13:01 +0100</pubDate>
					<category><![CDATA[HTML5]]></category>
					<category><![CDATA[CSS]]></category>
					<category><![CDATA[Internet Explorer]]></category>
					<category><![CDATA[Navegadores]]></category>
					<description><![CDATA[Antes de nada debemos preguntarnos, &iquest;qu&eacute; es un polyfill? Un polyfill es un trozo de c&oacute;digo (un plugin) que proporciona la tecnolog&iacute;a que el desarrollador espera obtener del navegador de forma nativa. En definitiva se trata de hacer que aquellos navegadores que no son compatibles con una...]]></description>
			<content:encoded><![CDATA[><p>Antes de nada debemos preguntarnos, &iquest;qu&eacute; es un polyfill? Un polyfill es un trozo de c&oacute;digo (un plugin) que proporciona la tecnolog&iacute;a que el desarrollador espera obtener del navegador de forma nativa. En definitiva se trata de hacer que aquellos navegadores que no son compatibles con una caracter&iacute;stica nueva, la incorporen a trav&eacute;s de fallbacks, es decir de c&oacute;digo, en su mayor medida javascript, que se encargue de realizar dicha funcionalidad.</p>
<p>Por ejemplo si queremos utilizar las nuevas etiquetas sem&aacute;nticas de HTML 5, debemos utilizar un polyfill que se encargue de hacer dichas etiquetas compatibles con versiones antiguas de Internet Explorer. El m&aacute;s utilizado es html5shiv.</p>
<p>O si por ejemplo queremos hacer que todos los navegadores hagan uso del nuevo atributo placeholder, que permite mostrar texto cuando dichos campos est&aacute;n vac&iacute;os. Entonces tan solo debemos buscar uno de los muchos polyfills que existen. O incluso crearlo nosotros mismos. Si optas por crearlo tu mismo, lo primero es ver si merece la pena comparando las versiones actuales para saber que podemos aportar. Y utilizar siempre detecci&oacute;n de caracter&iacute;sticas. Es decir con HTML 5 ya nos nos basamos en detecci&oacute;n de versiones de navegadores sino en caracter&iacute;sticas, es decir, si el navegador en concreto, sea la versi&oacute;n que sea, es capaz de realizar lo que se le pide. Para en caso correcto hacerlo de forma nativa.</p>
<p>Una de las ventajas de utilizar polyfills como desarrolladores es que nos olvidamos de los problemas y carencias de navegadores antiguos, y as&iacute; podemos desarrollar p&aacute;ginas web centr&aacute;ndonos en los nuevos est&aacute;ndares y sacando el m&aacute;ximo provecho.</p>
<p>Si queremos utilizar propiedades de CSS3 como border-radius, box-shadow, border-image, rgba, gradientes, &hellip; Para as&iacute; olvidarnos de tener que colocar im&aacute;genes en Internet Explorer, en el caso de bordes redondeados. Entonces es de recomendado uso utilizar CSS3 PIE. Obteniendo soporte para Internet Explorer 6, 7 y 8.</p>
<p>Volviendo al tema de entrada. El poly de polyfill, viene porque en algunas ocasiones para hacer funcional una caracter&iacute;stica se requiere de una soluci&oacute;n cuando esta disponible cierta tecnolog&iacute;a externa como podr&iacute;a ser flash o silverlight, y de otra soluci&oacute;n cuando esta tecnolog&iacute;a no esta.</p>
<p>En la mayor&iacute;a de casos debemos utilizar polyfills porque Internet Explorer no se actualiza para corregir sus carencias. Concretamente se cierra en versiones, las cuales mantiene hasta que sale una nueva versi&oacute;n, abandonando as&iacute; la anterior y no permitiendo la actualizaci&oacute;n a la nueva versi&oacute;n, a no ser que cumplamos los requisitos necesarios (como el sistema operativo necesario). Si dicho navegador se actualizara como Firefox o Chrome estoy seguro de que nos ahorrar&iacute;a mucho tiempo.</p>
<p>Para finalizar, un enlace con una recopilaci&oacute;n de polyfills para hacer m&aacute;s f&aacute;cil el tr&aacute;nsito hacia los nuevos est&aacute;ndares.<br /> https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-browser-Polyfills</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=101</wfw:commentRss>
			<slash:comments>4</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/polyfills-para-css3-y-html5.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Añadir la autoridad de validación FNMT para el DNI electrónico al KeyStore de Java usando keytool</title>
			<link>http://www.imaginanet.com/blog/anadir-la-autoridad-de-validacion-fnmt-para-el-dni-electronico-al-keystore-de-java.html</link>
			<guid>http://www.imaginanet.com/blog/anadir-la-autoridad-de-validacion-fnmt-para-el-dni-electronico-al-keystore-de-java.html</guid>
			<comments>http://www.imaginanet.com/blog/anadir-la-autoridad-de-validacion-fnmt-para-el-dni-electronico-al-keystore-de-java.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Thu,  1 Mar 2012 09:56:24 +0100</pubDate>
					<category><![CDATA[Servidores y Seguridad]]></category>
					<category><![CDATA[Java]]></category>
					<description><![CDATA[Anteriormente hemos visto c&oacute;mo crear nuestros propios certificados digitales en un entorno de desarrollo.
El principal problema que coment&aacute;bamos acerca de &eacute;sto es que la autoridad certificadora que los emit&iacute;a no era confiable (s&iacute;, nosotros mismos no lo somos), por lo que en el mundo real siempre...]]></description>
			<content:encoded><![CDATA[><p>Anteriormente hemos visto <a href="http://www.imaginanet.com/blog/crear-certificados-digitales-con-openssl.html">c&oacute;mo crear nuestros propios certificados digitales en un entorno de desarrollo</a>.</p>
<p>El principal problema que coment&aacute;bamos acerca de &eacute;sto es que la autoridad certificadora que los emit&iacute;a no era confiable (s&iacute;, nosotros mismos no lo somos), por lo que en el mundo real siempre dar&iacute;a un fallo a la hora de <a href="http://www.imaginanet.com/blog/firmar-y-verificar-firma-digital-en-pdfs-mediante-java-con-itext.html">verificar la firma digital de documentos</a>, por lo que la soluci&oacute;n es utilizar un certificado digital emitido por una autoridad certificadora de verdad.</p>
<h3>Importando la Autoridad Certificadora de la Fundaci&oacute;n Nacional de Moneda y Timbre al KeyStore de Java</h3>
<p>Por defecto, el KeyStore de Java no trae incluido el certificado de la FNMT, por lo que deberemos a&ntilde;adirlo. En primer lugar deberemos descargarlo de la p&aacute;gina:</p>
<p><a href="http://www.dnielectronico.es/seccion_integradores/certs.html" target="_blank">http://www.dnielectronico.es/seccion_integradores/certs.html</a></p>
<p>En concreto la autoridad de validaci&oacute;n <em>AV FNMT DNIE</em> y su certificado <em>Certificado pkcs1-sha256WithRSAEncryption</em></p>
<p>Lo descargamos y descomprimimos y procedemos a buscar las herramientas necesarias para la importaci&oacute;n de la JVM (<em>Java Virtual Machine</em>), que son el archivo <em>cacerts</em> que es donde se guardar&aacute; el certificado y el programa <em>keytool</em> que se encarga de manejar dicho archivo.</p>
<p>En primer lugar, deberemos buscar donde est&aacute;n ubicado el JRE de nuestra JVM buscando la aplicaci&oacute;n keytool. Las rutas son las siguientes:</p>
<pre class="code">&lt;JRE_PATH&gt;/bin/keytool</pre>
<pre class="code">&lt;JRE_PATH&gt;/lib/security/cacerts</pre>
<p>por lo que podemos proceder a importarlo con el comando y modificando previamente las rutas. Adem&aacute;s deberemos ejecutarlo como Administrador en Windows o Super Usuario en Linux:</p>
<pre class="code">&lt;JRE_PATH&gt;/bin/keytool -import -keystore &lt;JRE_PATH&gt;/lib/security/cacerts -file &lt;CERT_PATH&gt;/AVDNIEFNMTSHA2.cer -alias AVDNIE -storepass changeit</pre>
<p>El par&aacute;metro <em>alias</em> especifica el nombre con el que se guardar&aacute; y el par&aacute;metro <em>storepass</em> es por defecto <em>changeit</em> para el cacerts si no lo hemos cambiado.</p>
<p>&nbsp;</p>
<h3>Comandos &uacute;tiles de keytool para el KeyStore</h3>
<p><strong>Cambiar contrase&ntilde;a de cacerts (como super usuario)<br /></strong></p>
<pre class="code">&lt;JRE_PATH&gt;/bin/keytool -list -keystore  &lt;JRE_PATH&gt;/lib/security/cacerts -storepasswd -new &lt;NUEVA_CONTRASE&Ntilde;A&gt;</pre>
<p><strong>Listar certificados en nuestro cacerts</strong></p>
<pre class="code">&lt;JRE_PATH&gt;/bin/keytool -list -keystore  &lt;JRE_PATH&gt;/lib/security/cacerts -storepass &lt;CONTRASE&Ntilde;A&gt;</pre>
<p><strong>Borrar certificado del cacerts (como super usuario)<br /></strong></p>
<pre class="code">&lt;JRE_PATH&gt;/bin/keytool -delete -alias &lt;ALIAS&gt; -keystore  &lt;JRE_PATH&gt;/lib/security/cacerts</pre>
<p>&nbsp;</p>
<h3>Fuentes</h3>
<p>Este art&iacute;culo fue inspirado en la entrada de blog <a href="http://vjavierf.wordpress.com/2010/05/12/importar-certificados-de-una-ca-a-java/" target="_blank">http://vjavierf.wordpress.com/2010/05/12/importar-certificados-de-una-ca-a-java/</a></p>
<p>&nbsp;</p>
<h3>Art&iacute;culos relacionados</h3>
<ul>
<li><a href="http://www.imaginanet.com/blog/crear-certificados-digitales-con-openssl.html">Crear certificados digitales con OpenSSL</a></li>
<li><a href="http://www.imaginanet.com/blog/firmar-y-verificar-firma-digital-en-pdfs-mediante-java-con-itext.html">Firmar y verificar la firma digital en documentos PDF con Java</a><em><br /></em></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=100</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/anadir-la-autoridad-de-validacion-fnmt-para-el-dni-electronico-al-keystore-de-java.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Firmar y verificar firma digital en PDFs mediante Java con iText</title>
			<link>http://www.imaginanet.com/blog/firmar-y-verificar-firma-digital-en-pdfs-mediante-java-con-itext.html</link>
			<guid>http://www.imaginanet.com/blog/firmar-y-verificar-firma-digital-en-pdfs-mediante-java-con-itext.html</guid>
			<comments>http://www.imaginanet.com/blog/firmar-y-verificar-firma-digital-en-pdfs-mediante-java-con-itext.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Thu,  1 Mar 2012 08:11:58 +0100</pubDate>
					<category><![CDATA[Java]]></category>
					<category><![CDATA[Servidores y Seguridad]]></category>
					<category><![CDATA[PHP]]></category>
					<description><![CDATA[Ya hemos hablado anteriormente sobre c&oacute;mo empezar a utilizar certificados digitales en un entorno de desarrollo de programaci&oacute;n, ahora vamos a ver la primera aplicaci&oacute;n real con &eacute;stos certificados.
Firma digital de documentos PDF
La firma verifica la autor&iacute;a y validez de una persona, por lo que...]]></description>
			<content:encoded><![CDATA[><p>Ya hemos hablado anteriormente sobre c&oacute;mo empezar a <a href="http://www.imaginanet.com/blog/crear-certificados-digitales-con-openssl.html">utilizar certificados digitales en un entorno de desarrollo</a> de programaci&oacute;n, ahora vamos a ver la primera aplicaci&oacute;n real con &eacute;stos certificados.</p>
<h3>Firma digital de documentos PDF</h3>
<p>La firma verifica la autor&iacute;a y validez de una persona, por lo que es especialmente &uacute;til cuando hablamos de PDF que contienen facturas o documentos oficiales.</p>
<p>Tambi&eacute;n lo podemos usar para validar un certificado en entornos Web de manera transparente al navegador. Quien lo haya hecho, sabr&aacute; que si queremos usar certificados en una aplicaci&oacute;n web, hacerlo funcionar en todos los navegadores web puede causar bastantes dolores de cabeza, pero una sencilla manera es firmar un PDF <em>dummy</em> mediante <a href="http://proyectostic.uji.es/pr/cryptoapplet/" target="_blank">CryptoApplet</a> y validar si esa firma es v&aacute;lida, pero este procedimiento ya lo trataremos m&aacute;s adelante en otras entradas de blog.</p>
<h3>Creaci&oacute;n y modificaci&oacute;n de PDFs con la librer&iacute;a iText</h3>
<p>La librer&iacute;a <a href="http://itextpdf.com/" target="_blank">iText</a> disponible para Java y .NET permite crear y modificar PDFs din&aacute;micamente desde un entorno de programaci&oacute;n. En nuestro caso vamos a <a href="http://itextpdf.sourceforge.net/" target="_blank">descargarnos las librer&iacute;as OpenSource</a> y a&ntilde;adirlas a nuestro proyecto Java, en nuestro caso hemos utlizado <strong>NetBeans</strong>.</p>
<h3>Creando PDFs din&aacute;micamente mediante PHP</h3>
<p>En anteriores  entradas del blog ya tratamos la manera de <a href="http://www.imaginanet.com/blog/creando-documentos-pdfs-dinamicos-con-php.html">c&oacute;mo crear PDFs din&aacute;micamente  mediante la librer&iacute;a mPDF</a>, que podr&iacute;a ser interesante para esta  aplicaci&oacute;n.</p>
<h3>Preparando nuestro certificado digital</h3>
<p>El paso previo es tener preparado nuestro certificado digital. &Eacute;ste debe estar en formato con extensi&oacute;n PFX (est&aacute;ndar PKCS12), que en el caso de no tener ninguno disponible, ya hemos explicado anteriormente en el art&iacute;culo c&oacute;mo crear certificados digitales como crear uno.</p>
<p>Un paso previo muy importante, a la finalizaci&oacute;n de nuestro proyecto, es a&ntilde;adir la autoridad certificadora a nuestra KeyStore de Java. En el caso de seguir el art&iacute;culo de blog ser&aacute; obligado hacerlo si queremos que funcione correctamente, al igual que si por ejemplo queremos utilizar un certificado digital del DNIe, ya que el KeyStore de Java s&oacute;lo contempla los t&iacute;picos usados para HTTPS y algunos otros como Verisign.</p>
<p>Pod&eacute;is encontrar m&aacute;s informaci&oacute;n de <a href="http://www.imaginanet.com/blog/anadir-la-autoridad-de-validacion-fnmt-para-el-dni-electronico-al-keystore-de-java.html">c&oacute;mo a&ntilde;adir autoridades certificadoras a nuestro KeyStore de Java en este art&iacute;culo de blog</a>.</p>
<h3>Firmando PDFs en Java</h3>
<p>Crearemos el proyecto en NetBeans <em>PDFSigner</em> y pegaremos en el <em>Main.java</em> el siguiente c&oacute;digo:</p>
<pre class="code php">package pdfsigner;

import java.security.*;
import java.security.cert.Certificate;
import java.io.*;
import com.lowagie.text.pdf.*;
import com.lowagie.text.*;

/**
 * @author Imaginanet
 */
public class Main {

    public static void main(String[] args) {
        try {

            if(args.length == 0) {
                System.out.print("Necesito el nombre del PDF a firmar");
                System.exit(1);
            }

            KeyStore ks = KeyStore.getInstance("pkcs12");
            ks.load(new FileInputStream("RUTA_CERTIFICADO_PFX"), "CLAVE_PRIVADA_CERTIFICADO".toCharArray());
            String alias = (String)ks.aliases().nextElement();
            PrivateKey key = (PrivateKey)ks.getKey(alias, "CLAVE_PRIVADA_CERTIFICADO".toCharArray());
            Certificate[] chain = ks.getCertificateChain(alias);
            // Recibimos como par&aacute;metro de entrada el nombre del archivo PDF a firmar
            PdfReader reader = new PdfReader(args[0]); 
            FileOutputStream fout = new FileOutputStream("RUTA_ARCHIVO_PDF_FIRMADO");

            // A&ntilde;adimos firma al documento PDF
            PdfStamper stp = PdfStamper.createSignature(reader, fout, '?');
            PdfSignatureAppearance sap = stp.getSignatureAppearance();
            sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
            sap.setReason("Firma PKCS12");
            sap.setLocation("Imaginanet");
            // A&ntilde;ade la firma visible. Podemos comentarla para que no sea visible.
            sap.setVisibleSignature(new Rectangle(100,100,200,200),1,null);
            stp.close();
        }
        catch(Exception e) {
            e.printStackTrace();
        }

    }

}
</pre>
<p>Donde esperamos como par&aacute;metro de entrada al programa la ruta al archivo PDF original sin firmar y modificar las rutas al certificado digital PFX y la clave privada de &eacute;ste.</p>
<h3>Verificando firmas en PDFs desde Java</h3>
<p>Ahora comprobaremos la vericidad de la firma con otro proyecto NetBeans <em>PDFVerifier</em> y colocaremos en su <em>Main.java</em>:</p>
<pre class="code php">package pdfverifier;

import java.security.*;
import java.security.cert.Certificate;
import java.io.*;
import com.lowagie.text.pdf.*;
import java.util.Calendar;
import java.util.ArrayList;
import java.util.Random;

/**
 * @author Imaginanet
 */
public class Main {

    public static void main(String[] args) {
        try {
            if(args.length == 0) {
                System.out.print("Necesito el nombre del PDF a comprobar");
                System.exit(1);
            }
 
            Random rnd = new Random();
            KeyStore kall = PdfPKCS7.loadCacertsKeyStore();
            PdfReader reader = new PdfReader(args[0]);
            AcroFields af = reader.getAcroFields();
            ArrayList names = af.getSignatureNames();
            for (int k = 0; k &lt; names.size(); ++k) {
               String name = (String)names.get(k);
               int random = rnd.nextInt();
               FileOutputStream out = new FileOutputStream("revision_" + random + "_" + af.getRevision(name) + ".pdf");

               byte bb[] = new byte[8192];
               InputStream ip = af.extractRevision(name);
               int n = 0;
               while ((n = ip.read(bb)) &gt; 0)
               out.write(bb, 0, n);
               out.close();
               ip.close();

               PdfPKCS7 pk = af.verifySignature(name);
               Calendar cal = pk.getSignDate();
               Certificate pkc[] = pk.getCertificates();
               Object fails[] = PdfPKCS7.verifyCertificates(pkc, kall, null, cal);
               if (fails == null) {
                   System.out.print(pk.getSignName());
               }
               else {
                   System.out.print("Firma no v&aacute;lida");
               }
               File f = new File("revision_" + random + "_" + af.getRevision(name) + ".pdf");
               f.delete();
            }
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }
}
</pre>
<p>Al igual que el anterior programa, necesita como par&aacute;metro de entrada el archivo PDF a comprobar, mostrando en caso de ser verificada la firma los datos del propietario y en caso contrario el mensaje de error "<em>Firma no v&aacute;lida</em>".</p>
<h3>Llamada a los programas desde una aplicaci&oacute;n</h3>
<p>Hemos separado ambos programas para que act&uacute;en como programas como cajas negras y sea independiente del lenguaje de programaci&oacute;n del que se llame.</p>
<p>En el caso de firmar, llamaremos como <em>java pdfsigner archivo.pdf</em> generando un archivo pdf firmado.</p>
<p>Tras ello, podemos vertificar la firma con <em>java pdfverifier firmado.pdf</em> mostrando la salida de la firma en caso positivo. Ya que la firma puede guardarse en varios formatos seg&uacute;n el certificado PFX, recomendamos que esa salida hagamos el parseo necesario desde nuestra aplicaci&oacute;n buscando datos que estemos seguros que vayan a salir en la firma, como es el caso del DNI, CIF, direcci&oacute;n email, etc.</p>
<h3>Comunicando nuestro programa de firma digital de PDF con aplicaciones PHP</h3>
<p>Una de las aplicaciones m&aacute;s interesantes es la de usar esta aplicaci&oacute;n de firma con PHP. Las librer&iacute;as que permiten hacer &eacute;sto en PHP no son libres, pero sin embargo podemos llamar a nuestras aplicaciones Java mediante <em>passthru</em>, <em>exec</em>, etc. permitiendo tener firma digital open source en PHP.</p>
<h3>Referencias</h3>
<ul>
<li><a href="http://itextpdf.com/" target="_blank">iText</a></li>
<li><a href="http://itextpdf.sourceforge.net/" target="_blank">Proyecto OpenSource iText</a></li>
<li><a href="http://itextpdf.sourceforge.net/howtosign.html" target="_blank">Ejemplos y referencia de la librer&iacute;a iText</a></li>
<li><a href="http://www.imaginanet.com/blog/crear-certificados-digitales-con-openssl.html">Crear y configurar certificados digitales con OpenSSL</a></li>
<li><a href="http://www.imaginanet.com/blog/creando-documentos-pdfs-dinamicos-con-php.html">Crear PDFs din&aacute;micamente con PHP mediante mPDF</a></li>
<li><a href="http://www.imaginanet.com/blog/anadir-la-autoridad-de-validacion-fnmt-para-el-dni-electronico-al-keystore-de-java.html">A&ntilde;adir Autoridades Certificadoras al KeyStore de Java para usar el DNIe en nuestras aplicaciones</a></li>
<li><a href="http://proyectostic.uji.es/pr/cryptoapplet/" target="_blank">CryptoApplet</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=99</wfw:commentRss>
			<slash:comments>13</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/firmar-y-verificar-firma-digital-en-pdfs-mediante-java-con-itext.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Dar de alta, matricular y desmatricular en cursos de Moodle mediante módulo enrolment</title>
			<link>http://www.imaginanet.com/blog/dar-de-alta-matricular-y-desmatricular-en-cursos-de-moodle-mediante-modulo-enrolment.html</link>
			<guid>http://www.imaginanet.com/blog/dar-de-alta-matricular-y-desmatricular-en-cursos-de-moodle-mediante-modulo-enrolment.html</guid>
			<comments>http://www.imaginanet.com/blog/dar-de-alta-matricular-y-desmatricular-en-cursos-de-moodle-mediante-modulo-enrolment.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue, 21 Feb 2012 08:23:23 +0100</pubDate>
					<category><![CDATA[Internet]]></category>
					<category><![CDATA[PHP]]></category>
					<description><![CDATA[Cuando trabajamos con Moodle, una de las interactuaciones desde una aplicaci&oacute;n externa m&aacute;s interesantes con Moodle es poder dar matricular y desmatricular en cursos y tambi&eacute;n poder dar de alta usuarios en Moodle de manera externa.
Dar de alta usuarios en Moodle
La alta de usuarios es bastante sencillo ya que...]]></description>
			<content:encoded><![CDATA[><p style="font-size: 15px; line-height: 21px;">Cuando trabajamos con Moodle, una de las interactuaciones desde una aplicaci&oacute;n externa m&aacute;s interesantes con Moodle es poder dar <strong style="font-size: 15px; line-height: 21px;">matricular y desmatricular en cursos</strong> y tambi&eacute;n poder <strong style="font-size: 15px; line-height: 21px;">dar de alta usuarios en Moodle</strong> de manera externa.</p>
<h3 style="font-size: 17.55px; line-height: 22.5px;">Dar de alta usuarios en Moodle</h3>
<p style="font-size: 15px; line-height: 21px;">La alta de usuarios es bastante sencillo ya que simplemente deberemos a&ntilde;adirlo a la base de datos con el formato que Moodle requiere en la tabla <em style="font-size: 15px; line-height: 21px;">mdl_user</em> cuyo contenido m&aacute;s destacado es el siguiente:</p>
<ul style="font-size: 15px; line-height: 21px;">
<li style="font-size: 15px; line-height: 21px;">id: identificador &uacute;nico dentro del sistema, debe ser n&uacute;mero y autoincremental, por ejemplo el valor en la consulta SQL deber&iacute;a ser NULL<br style="font-size: 15px; line-height: 21px;" /></li>
<li style="font-size: 15px; line-height: 21px;">auth: con valor "manual", especifica el m&eacute;todo de autenticaci&oacute;n</li>
<li style="font-size: 15px; line-height: 21px;">confirmed: valor 1, especifica si se ha confirmado el alta</li>
<li style="font-size: 15px; line-height: 21px;">username: nombre de usuario</li>
<li style="font-size: 15px; line-height: 21px;">password: contrase&ntilde;a guardada mediante hash MD5</li>
</ul>
<p style="font-size: 15px; line-height: 21px;">El resto de campos su contenido es bastante obvio.</p>
<h3 style="font-size: 17.55px; line-height: 22.5px;">Matricular y desmatricular usuarios en cursos</h3>
<p style="font-size: 15px; line-height: 21px;">Dado que es bastante complicado dar de alta en cursos usuarios, deberemos utilizar el m&oacute;dulo enrolments de Moodle para hacerlo mediante la creaci&oacute;n de un archivo con un formato determinado.</p>
<p style="font-size: 15px; line-height: 21px;">En primer lugar deberemos <strong>activarlo como administrador desde Moodle</strong> en la opci&oacute;n: <em>Courses -&gt; Enrolments -&gt; Flat file</em></p>
<p style="font-size: 15px; line-height: 21px;">Despu&eacute;s buscaremos <strong>la ruta donde deberemos generar el fichero</strong>. Por defecto se encuentra fuera de la ra&iacute;z p&uacute;blica de archivos, en el archivo <em>moodledata/1/enrolments.txt</em></p>
<p style="font-size: 15px; line-height: 21px;">El siguiente paso es <strong>generar el archivo en texto plano</strong> en el formato correspondiente:</p>
<pre class="code">add, student, idnumber_mdl_user1, idnumber_mdl_course1
del, student, idnumber_mdl_user2, idnumber_mdl_course5
</pre>
<p>Donde idnumber_mdl_user1 corresponde con el campo <em>idnumber</em> de la tabla <em>mdl_user</em> del usuario correspondiente y idnumber_mdl_course1 es el campo <em>idnumber</em> del curso en la tabla <em>mdl_course</em>. Atenci&oacute;n, desde Moodle deberemos rellenar correctamente estos campos, ya que no pueden estar vac&iacute;os.</p>
<p>En ese archivo generado en primer lugar a&ntilde;adiremos al usuario 1 al curso 1 como estudiante y borraremos al usuario 2 del curso 5 como estudiante.</p>
<p>El &uacute;ltimo paso es <strong>llamar al archivo que ejecuta el cron peri&oacute;dico de mantenimiento de Moodle</strong> para forzar la actualizaci&oacute;n:</p>
<p><em>http://HOST/admin/cron.php</em></p>
<p>Si tuvi&eacute;ramos alg&uacute;n error en la configuraci&oacute;n, se indicar&iacute;a en este fichero.</p>
<h3>Referencia</h3>
<ul>
<li><a href="http://docs.moodle.org/dev/Developer_documentation" target="_blank">http://docs.moodle.org/dev/Developer_documentation</a></li>
<li><a href="http://docs.moodle.org/20/en/Flat_file" target="_blank">http://docs.moodle.org/20/en/Flat_file</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=98</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/dar-de-alta-matricular-y-desmatricular-en-cursos-de-moodle-mediante-modulo-enrolment.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Galería de fotos 3D con CSS3</title>
			<link>http://www.imaginanet.com/blog/galeria-de-fotos-3d-con-css3.html</link>
			<guid>http://www.imaginanet.com/blog/galeria-de-fotos-3d-con-css3.html</guid>
			<comments>http://www.imaginanet.com/blog/galeria-de-fotos-3d-con-css3.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Sun, 12 Feb 2012 21:26:32 +0100</pubDate>
					<category><![CDATA[HTML5]]></category>
					<category><![CDATA[Web 2.0]]></category>
					<category><![CDATA[JavaScript]]></category>
					<category><![CDATA[Navegadores]]></category>
					<description><![CDATA[Veamos un ejemplo de una galer&iacute;a de im&aacute;genes en 3D utilizando javascript y CSS3. Este ejemplo funciona en firefox, chrome, safari y opera, aunque ofrece un mejor rendimiento en los navegadores basados en webkit.

Haz click sobre la galer&iacute;a y pulsa las flechas izquierda y derecha de tu teclado para hacer girar...]]></description>
			<content:encoded><![CDATA[><p>Veamos un ejemplo de una galer&iacute;a de im&aacute;genes en 3D utilizando javascript y CSS3. Este ejemplo funciona en firefox, chrome, safari y opera, aunque ofrece un mejor rendimiento en los navegadores basados en webkit.</p>
<iframe src="http://www.imaginanet.com/blog_files/3dgallery/index.htm" style="border: black dotted 1px; display: block; width: 100%; height: 220px; overflow: hidden; margin: 20px 0;"></iframe>
<p>Haz click sobre la galer&iacute;a y pulsa las flechas izquierda y derecha de tu teclado para hacer girar la galer&iacute;a.</p>
<p>Para el desarrollo de este ejemplo hemos usado jquery. Creamos una figura con tantos lados como im&aacute;genes tenga la galer&iacute;a y las posicionamos en un espacio 3D utilizando las propiedad de CSS3 "transform", y la funci&oacute;n "rotate". Para la animaci&oacute;n, definimos otra propiedad CSS3 en la hoja de estilos, "transition", y animamos la propiedad "transform". Al modificar esa propiedad por javascript conseguimos la animaci&oacute;n deseada.</p>
<p>Si est&aacute;s viendo esta web en un navegador antiguo o en <span style="color: #ff0000;">Internet explorer</span> quiz&aacute;s no puedas apreciar el funcionamiento. Recomendamos usar los navegadores firefox o Chrome (siendo &eacute;ste el que mejores resultados ofrece).</p>
<p><a href="http://www.imaginanet.com/blog_files/3dgallery/files.zip">Descarga el c&oacute;digo del ejemplo.</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=97</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/galeria-de-fotos-3d-con-css3.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Google Maps API (Versión 3)</title>
			<link>http://www.imaginanet.com/blog/google-maps-api-version-3.html</link>
			<guid>http://www.imaginanet.com/blog/google-maps-api-version-3.html</guid>
			<comments>http://www.imaginanet.com/blog/google-maps-api-version-3.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed,  8 Feb 2012 17:41:17 +0100</pubDate>
					<category><![CDATA[Google Apps]]></category>
					<category><![CDATA[Google]]></category>
					<category><![CDATA[JavaScript]]></category>
					<description><![CDATA[Introducci&oacute;n
La nueva versi&oacute;n de la popular API de Google Maps est&aacute; llena de novedades que hacen  	que trabajar con mapas y geolocalizaci&oacute;n sea una tarea cada vez m&aacute;s potente y  	sencilla. Con esta &uacute;ltima actualizaci&oacute;n de la API podemos f&aacute;cilmente incorporar  	mapas a...]]></description>
			<content:encoded><![CDATA[><h3>Introducci&oacute;n</h3>
<p>La nueva versi&oacute;n de la popular <strong>API de Google Maps</strong> est&aacute; llena de novedades que hacen  	que <strong>trabajar con mapas y geolocalizaci&oacute;n sea una tarea cada vez m&aacute;s potente y  	sencilla</strong>. Con esta &uacute;ltima actualizaci&oacute;n de la API podemos f&aacute;cilmente incorporar  	mapas a nuestras webs, personalizando todo lo que necesitemos.</p>
<p>En este art&iacute;culo vamos a seguir un sencillo tutorial para poder empezar a trabajar con esta API:</p>
<h3>Primeros pasos</h3>
<p>Lo primero de todo, tenemos que a&ntilde;adir la API en el <strong>TAG HEAD</strong></p>
<code> &lt;script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=<em style="color: blue;">set_to_true_or_false</em>"&gt; </code>
<p>En este ejemplo, sacado del tutorial de Google, vemos que hace hincapie en definir  	una variable llamada sensor en el mismo instante de invocar la librer&iacute;a. Como podemos  	ver en la documentaci&oacute;n de la API</p>
<blockquote><em> Ten en cuenta que tambi&eacute;n debemos establecer un par&aacute;metro sensor para indicar si esta  	aplicaci&oacute;n utiliza un sensor para determinar la ubicaci&oacute;n del usuario. En este ejemplo  	hemos dejado el par&aacute;metro como la variable <strong>set_to_true_or_false</strong> para hacer  	<strong>hincapi&eacute; en que se debe definir este valor en true o false de forma expl&iacute;cita.</strong> </em></blockquote>
<p>Una vez aclarado esto, entonces vamos a inicializar la API con la variable sensor a <strong>FALSE</strong></p>
<code> &lt;script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"&gt;: </code>
<p>Ahora ya podemos crear en nuestro c&oacute;digo JavaScript un mapa, indicando en el constructor del  	objeto la longitud y latitud donde queremos que inicialmente se encuentre el mapa.</p>
<code> var myOptions =    {     zoom: 5,     center: new google.maps.LatLng(latitud, longitude),     mapTypeId: google.maps.MapTypeId.ROADMAP,   } ;  map = new google.maps.Map (document.getElementById("<em>ID DEL CONTENDOR</em>"), myOptions); </code>
<p>Si nos fijamos bien, con estos pasos tenemos mucha versatilidad para crear nuestros mapas,  	pues hemos definido la posici&oacute;n inicial del mapa definiendo zoom, posici&oacute;n y tipo de mapa.</p>
<p>Luego, al crear el mapa lo "<em>v&iacute;nculamos</em>" dentro de un elemento HTML como puede ser un  	elemento DIV por ejemplo.</p>
<br /><br />
<h3>Marcadores</h3>
<p>Los Marcadores es algo que tambi&eacute;n es m&aacute;s sencillo de manejar que en versiones  	anteriores de la API</p>
<p>En primer lugar, basta con crear un objeto <strong>marker</strong></p>
<code> marker = new google.maps.Marker ({position: new google.maps.LatLng(latitude, longitude), title: "Mi marcador"}) ; </code>
<p>Y luego asociarlo al mapa</p>
<code> marker.setMap(map); </code>
<p>Esto es un ejemplo muy sencillo de lo que podemos hacer, pero la funcionalidad de estos  	marcadores viene en que podemos asociarle <strong>Listeners</strong>, que estar&aacute;n pendientes de los  	eventos que ocurran,</p>
<p>Por ejemplo, si queremos escuchar el evento click del marcador, basta con hacer esto:</p>
<code> google.maps.event.addListener (marker, "click", function (event)  {   &hellip; } </code> <br /><br />
<h3>Centrado en funci&oacute;n marcadores</h3>
<p>Centrar el mapa en funci&oacute;n de un conjunto de marcadores nos implica crear un objeto <strong>Bounds</strong>:</p>
<code> var bounds = new google.maps.LatLngBounds() ; </code>
<p><strong>Conforme vamos creando marcadores y situ&aacute;ndolos en el mapa</strong>, debemos de a&ntilde;adirlos tambi&eacute;n a este objeto</p>
<code> bounds.extend (new google.maps.LatLng(latitude, longitude)); </code>
<p>Y como &uacute;ltimo paso, ajustamos el mapa a este contorno. Esta funci&oacute;n nos ajustar&aacute; tanto  	el zoom como las coordenadas para se vea todo centrado en nuestro mapa.</p>
<code> map.fitBounds (bounds); </code>
<p>En pr&oacute;ximas entregas trateremos de ir profundizando m&aacute;s en esta potente API</p>
<h3>Fuentes</h3>
<p><a href="http://code.google.com/intl/es-ES/apis/maps/documentation/javascript/" target="_blank">http://code.google.com/intl/es-ES/apis/maps/documentation/javascript/</a> <a href="http://code.google.com/intl/es-ES/apis/maps/documentation/javascript/reference.html" target="_blank">http://code.google.com/intl/es-ES/apis/maps/documentation/javascript/reference.html</a></p>
<p><em> Dise&ntilde;o del icono: <a href="http://www.iconarchive.com/show/palm-icons-by-thiago-silva/Google-Maps-icon.html">Thiago Silva</a> </em></p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=96</wfw:commentRss>
			<slash:comments>3</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/google-maps-api-version-3.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Patrón MVP</title>
			<link>http://www.imaginanet.com/blog/patron-mvp.html</link>
			<guid>http://www.imaginanet.com/blog/patron-mvp.html</guid>
			<comments>http://www.imaginanet.com/blog/patron-mvp.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Thu,  2 Feb 2012 08:21:30 +0100</pubDate>
					<category><![CDATA[Patrones]]></category>
					<description><![CDATA[El Patr&oacute;n Modelo-Vista-Presentador (MVP) surge para ayudar a realizar pruebas autom&aacute;ticas de la interfaz gr&aacute;fica, para ello la idea es codificar la interfaz de usuario lo m&aacute;s simple posible, teniendo el menor c&oacute;digo posible, de forma que no merezca la pena probarla. En su lugar, toda la...]]></description>
			<content:encoded><![CDATA[><p>El Patr&oacute;n Modelo-Vista-Presentador (MVP) surge para ayudar a realizar pruebas autom&aacute;ticas de la interfaz gr&aacute;fica, para ello la idea es codificar la interfaz de usuario lo m&aacute;s simple posible, teniendo el menor c&oacute;digo posible, de forma que no merezca la pena probarla. En su lugar, toda la l&oacute;gica de la interfaz de usuario, se hace en una clase separada (que se conoce como Presentador), que no dependa en absoluto de los componentes de la interfaz gr&aacute;fica y que, por tanto, es m&aacute;s f&aacute;cil de realizar pruebas.</p>
<p>La idea b&aacute;sica es que la clase Presentador haga de intermediario entre la Vista (la interfaz gr&aacute;fica de usuario) y el modelo de datos. La vista tiene m&eacute;todos en los que le pasan los datos que debe pintar ya "mascados" (una lista de cadenas por ejemplo, en vez del modelo...). &Uacute;nicamente debe meter esos datos en los componentes gr&aacute;ficos (cajas de texto, checkbox, etc). Tambi&eacute;n m&eacute;todos get para obtener el contenido de esos componentes.</p>
<p>El Presentador har&aacute; de enlace entre el modelo y la vista, y dotar&aacute; de inteligencia a la vista. Como el objetivo es poder probarlo f&aacute;cilmente, el Presentador recibe las interfaces que deben implementar el modelo y la vista, con los m&eacute;todos p&uacute;blicos a los que el Presentador debe llamar.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://www.imaginanet.com/ftp/blog/patronmvp.jpg" alt="Patr&oacute;n MVP" width="240" height="185" /></p>
<p>Se puede decir que el patr&oacute;n MVP es una mejora del patr&oacute;n Modelo-Vista-Controlador (MVC) basado en tres caracter&iacute;sticas:</p>
<ul>
<li>La vista no conoce el modelo.</li>
<li>El presentador es independiente de la tecnolog&iacute;a de interfaz de usuario.</li>
<li>La vista y el presentador son testeables puesto que esta basada en un contrato.</li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=95</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/patron-mvp.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Cómo reducir la carga del servidor reduciendo y combinando las hojas de estilo y javascripts</title>
			<link>http://www.imaginanet.com/blog/como-reducir-la-carga-del-servidor-reduciendo-y-combinando-las-hojas-de-estilo-y-javascripts.html</link>
			<guid>http://www.imaginanet.com/blog/como-reducir-la-carga-del-servidor-reduciendo-y-combinando-las-hojas-de-estilo-y-javascripts.html</guid>
			<comments>http://www.imaginanet.com/blog/como-reducir-la-carga-del-servidor-reduciendo-y-combinando-las-hojas-de-estilo-y-javascripts.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Thu, 19 Jan 2012 10:18:02 +0100</pubDate>
					<category><![CDATA[Internet]]></category>
					<category><![CDATA[CSS]]></category>
					<category><![CDATA[Navegadores]]></category>
					<category><![CDATA[PHP]]></category>
					<category><![CDATA[jQuery]]></category>
					<description><![CDATA[El dise&ntilde;o web cada vez se est&aacute; aprovechando de las ventajas de aplicar los conceptos clave de la Ingenier&iacute;a.
Si imaginamos la fabricaci&oacute;n de un coche, podemos verlo como la fabricaci&oacute;n por separado de una serie de piezas (motor, sistema de frenado, ruedas, tapicer&iacute;a, &hellip;) que se...]]></description>
			<content:encoded><![CDATA[><p><em><strong>El dise&ntilde;o web cada vez se est&aacute; aprovechando de las ventajas de aplicar los conceptos clave de la Ingenier&iacute;a</strong></em>.</p>
<p>Si imaginamos la fabricaci&oacute;n de un coche, podemos verlo como la fabricaci&oacute;n por separado de una serie de piezas (motor, sistema de frenado, ruedas, tapicer&iacute;a, &hellip;) que se dise&ntilde;an por separado y se combinan.&nbsp;As&iacute;, en el dise&ntilde;o web muchas veces se combinan librer&iacute;as Javascript como jQuery o m&oacute;dulos personalizados que a&ntilde;aden funcionalidad a la web.</p>
<p>El problema de esto, es que <strong>un navegador est&aacute; obligado a realizar una petici&oacute;n al servidor por cada archivo</strong> (imagen, librer&iacute;a, hoja de estilos, &hellip;) que se utiliza en la p&aacute;gina web. Una vez cargadas, el navegador las cachea y la navegaci&oacute;n resulta m&aacute;s fluida, pero &iquest;C&oacute;mo podemos agilizar ese primer paso tan decisivo?</p>
<p>La respuesta es simple:&nbsp;<strong>Minimizando&nbsp;las peticiones al servidor</strong></p>
<h3><strong>Hojas de estilo y librer&iacute;as Javascript</strong></h3>
<p>Lo ideal es que todas las peticiones vayan en un mismo fichero. Esto en un principio obligar&iacute;a al programador a realizar todo el proceso de la hoja de estilos en un &uacute;nico fichero, lo cual, en algunos casos puede no ser lo m&aacute;s aconsejable por modularidad, aunque s&iacute; por eficiencia.</p>
<p>Existen librer&iacute;as que son capaces de combinar varios ficheros en uno solo de forma autom&aacute;tica cada vez que alguno de los ficheros se modifica. Esto quiz&aacute;s a&ntilde;ada un poco de tiempo de procesamiento en PHP pero las ventajas a la larga cuando la web est&eacute; en producci&oacute;n son grandes.</p>
<h3><br /><strong>Im&aacute;genes</strong></h3>
<p>Si una hoja de estilos hace uso de unas 10 im&aacute;genes de fondo, <strong>tiene que realizar una llamada al servidor por cada una de estas im&aacute;genes</strong>. La soluci&oacute;n para minimizar esto es combinar todas las im&aacute;genes en una sola utilizando una t&eacute;cnica llamada <strong><a href="http://www.librosweb.es/css_avanzado/capitulo1/rollovers_y_sprites.html">CSS Sprites</a></strong>.</p>
<p>Con esta t&eacute;cnica, y mediante hojas de estilo somos capaces de coger como imagen de fondo s&oacute;lo la porci&oacute;n que necesitamos.</p>
<p>No hay que menospreciar el trabajo que lleva generar la imagen combinada adem&aacute;s de calcular las posiciones de cada imagen ya que estamos utilizando uno de los recursos m&aacute;s importantes del programador, que es el tiempo.</p>
<p><br /><br />Para ayudar con esto, existen una serie de herramientas online que permiten simplificar la tarea:</p>
<p>Algunas herramientas son:</p>
<ul>
<li><a href="http://spriteme.org/">http://spriteme.org/</a></li>
<li><a href="http://spritegen.website-performance.org/">http://spritegen.website-performance.org/</a></li>
</ul>
<h3><br /><strong>Minimizar y comprimir los archivos</strong></h3>
<p>Antes hemos comentando las ventajas de combinar los archivos en uno para minimizar el n&uacute;mero de peticiones web. <strong>Si adem&aacute;s, somos capaces de reducir el tama&ntilde;o del fichero en producci&oacute;n estaremos incrementando la eficiencia de nuestra web</strong>.</p>
<p>Para ello, existen dos t&eacute;cnicas que se pueden combinar:</p>
<ul>
<li><strong>Minimizar los ficheros</strong>: Eliminando comentarios, espacios en blanco, &hellip;</li>
<li><strong>Comprimir los ficheros</strong>: Algunos navegadores son capaces de entender que los datos pueden venir comprimidos utilizando alg&uacute;n algoritmo de compresi&oacute;n.&nbsp;</li>
</ul>
<p>Con esto, lo que vamos a conseguir es que el servidor est&eacute; m&aacute;s holgado pues tendr&aacute; que transmitir menos cantidad de datos a cada uno de los clientes que realicen peticiones y por tanto, el rendimiento global ser&aacute; mayor.</p>
<p>Todas estas ventajas las podemos conseguir de forma autom&aacute;tica utilizando la librer&iacute;a <a href="http://code.google.com/p/minify/">minify </a>que se encarga de juntar, combinar y reducir los ficheros indicados.</p>
<p><a href="http://code.google.com/p/minify/">http://code.google.com/p/minify/</a></p>
<h3><br /><strong>Cache</strong></h3>
<p>Es posible que le indiquemos a cada p&aacute;gina web, de manera individual, cuanto tiempo debe pertenecer esta en cache. Las dos posibilidades son:Para p&aacute;ginas est&aacute;ticas es implentar una pol&iacute;tica de establecer una fecha de caducidad de la cache lejanaPara p&aacute;ginas din&aacute;micas usar una fecha aproviada para ayudar al navegador con las peticiones condicionales<br /><br />En servidores como Apache, somos capaces de indicar una fecha relativa a la fecha actual, indicando que la p&aacute;gina caducar&aacute;, por ejemplo, pasados d&iacute;as (e incluso a&ntilde;os) de la fecha de la petici&oacute;n.<br />En el caso de cambinar un componente, es necesario indic&aacute;rselo al navegador a&ntilde;adiendo alg&uacute;n par&aacute;metro a la consulta o a&ntilde;adiendo alg&uacute;n n&uacute;mero de versi&oacute;n al fichero.<br /><strong><br /></strong></p>
<h3><strong>Otros consejos</strong></h3>
<p>Poner las hojas de estilo en la cabecera:&nbsp;Tal y como indica el estandar W3C</p>
<p style="padding-left: 30px;"><em>The HTML specification clearly states that stylesheets are to be included in the HEAD of the page: "Unlike A, [LINK] may only appear in the HEAD section of a document, although it may appear any number of times." Neither of the alternatives, the blank white screen or flash of unstyled content, are worth the risk. The optimal solution is to follow the HTML specification and load your stylesheets in the document HEAD.</em><em><br /></em></p>
<p><em><br /></em>Esto nos indica que poniendo las hojas de estilo all&iacute;, el navegador ser&aacute; capaz de cargar la p&aacute;gina de forma progresiva</p>
<p><br /><strong>Utilizar ficheros externos</strong></p>
<p>Al margen de los beneficios de reusabilidad y modularidad, usando ficheros externos para almacenar nuestras hojas de estilo y scripts permiten al navegador cachearlos.</p>
<p>Por consiguiente, las p&aacute;ginas web son m&aacute;s livianas y tardan menos en descargarse.</p>
<p><br /><strong>Reducir el n&uacute;mero de elementos DOM en la p&aacute;gina</strong></p>
<p>Maquetar de forma clara y sem&aacute;ntica reducen el n&uacute;mero de elementos del &aacute;rbol ya que no es necesario a&ntilde;adir DIVs u otros elementos para corregir problemas de LAYOUT. De esta forma, los scripts ser&aacute;n m&aacute;s r&aacute;pidos y eficientes porque tendr&aacute;n que buscar en menos nodos</p>
<p><br /><strong>Evita tener im&aacute;genes vac&iacute;as</strong></p>
<p>Las im&aacute;genes vac&iacute;as (&lt;img src=&rdquo;&rdquo; alt=&rdquo;Vac&iacute;a&rdquo; /&gt;) o var img = new Image(); img.src=&rsquo;&rsquo;; obligan a los navegadores a realizar peticiones HTTP que no son &uacute;tiles.</p>
<p>&nbsp;</p>
<h3>Fuentes:</h3>
<ul>
<li><a href="http://developer.yahoo.com/performance/rules.html">http://developer.yahoo.com/performance/rules.html</a></li>
<li><a href="http://code.google.com/p/minify/">http://code.google.com/p/minify/</a></li>
<li><a href="http://spritegen.website-performance.org/">http://spritegen.website-performance.org/</a></li>
<li><a href="http://spriteme.org/">http://spriteme.org/</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=94</wfw:commentRss>
			<slash:comments>1</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/como-reducir-la-carga-del-servidor-reduciendo-y-combinando-las-hojas-de-estilo-y-javascripts.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Instalando un antispam con SpamAssassin y Postfix</title>
			<link>http://www.imaginanet.com/blog/instalando-un-antispam-con-spamassassin-y-postfix.html</link>
			<guid>http://www.imaginanet.com/blog/instalando-un-antispam-con-spamassassin-y-postfix.html</guid>
			<comments>http://www.imaginanet.com/blog/instalando-un-antispam-con-spamassassin-y-postfix.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue, 17 Jan 2012 15:46:24 +0100</pubDate>
					<category><![CDATA[Servidores y Seguridad]]></category>
					<category><![CDATA[Linux]]></category>
					<description><![CDATA[Tras leer la documentaci&oacute;n oficial y varias gu&iacute;as de como hacerlo, vamos a explicar nuestra experiencia de c&oacute;mo instalar el antispam SpamAssassin sobre CentOS 6.0 (v&aacute;lido tambi&eacute;n para el resto de distribuciones) utilizando el servicio de correo Postfix, consiguiendo unos muy buenos resultados...]]></description>
			<content:encoded><![CDATA[><div class="content selectable wrapchrome">
<div id="text-block-view-012335f5-60b8-4b9e-8d0e-d8c174810d4e-editable" class="editable wrapchrome">
<p>Tras leer la documentaci&oacute;n oficial y varias gu&iacute;as de como hacerlo, vamos a explicar nuestra experiencia de c&oacute;mo instalar el <strong>antispam SpamAssassin</strong> sobre <strong>CentOS 6.0 </strong>(<span style="text-decoration: underline;">v&aacute;lido tambi&eacute;n para el resto de distribuciones</span>) utilizando el servicio de correo <strong>Postfix</strong>, consiguiendo unos muy buenos resultados para mantenernos libres de spam en nuestros correos.</p>
<p>Esta gu&iacute;a est&aacute; basada en otras (indicadas como referencias) y extendida y m&aacute;s ampliamente explicada en algunos conceptos en los que hemos tenido problemas.</p>
<h3>Instalar Perl</h3>
<p>En primer lugar instalaremos Perl si no lo tenemos instalado:</p>
<pre class="code">yum install perl
yum install perl-Mail-DKIM.noarch
yum install spamassassin
</pre>
<p>En este punto, en nuestro caso nos hemos encontrado con alguna dificultad ya que las librer&iacute;as de SpamAssassin requer&iacute;an Perl 5.8.8 y CentOS 6.0 nos acababa de instalar Perl 6.0, por lo que existir&aacute;n conflictos en paquetes con <span style="text-decoration: underline;">dependencias sin resolver</span>.</p>
<pre class="code">error: Failed dependencies:
perl(:MODULE_COMPAT_5.8.8)
</pre>
Tenemos dos opciones para solucionarlo:<br /> 
<ul>
<li><strong>Actualizar a CentOS 6.2</strong>. Si nuestro servidor no est&aacute; en producci&oacute;n o estamos seguros de lo que hacemos, tal vez sea la mejor opci&oacute;n.</li>
<li><strong>Instalar RPMs de la versi&oacute;n 6.2</strong>. Hemos elegido esta opci&oacute;n ya que el servidor en concreto sobre el que lo hemos hecho ya est&aacute; en producci&oacute;n y nos provocaba bastante incertidumbre el hecho de qu&eacute; pasar&aacute; tras actualizar. Tras buscar en los <a href="http://www.centos.org/modules/tinycontent/index.php?id=30" target="_blank">repositorios oficiales de CentOS</a> hemos elegido uno de ellos como &eacute;ste <a href="ftp://centos.arcticnetwork.ca/pub/centos/6.2/os/x86_64/Packages/" target="_blank">ftp://centos.arcticnetwork.ca/pub/centos/6.2/os/x86_64/Packages/</a>&nbsp; y lo hemos instalado a la vieja usanza, con <em>rpm -Uvh rutadelpaquete.rpm </em>todos los paquetes que est&aacute;n dentro de los paquetes requeridos </li>
</ul>
</div>
<div class="editable wrapchrome">
<h3>Configurando SpamAssassin</h3>
<div class="editable wrapchrome">En primer lugar crearemos el usuario de SpamAssassin</div>
<pre class="code">useradd -d /home/spamfilter -s /bin/false spamfilter
chmod 766 /home/spamfilter
</pre>
<div class="editable wrapchrome">Crear el archivo</div>
<pre class="code">nano /etc/mail/spamassassin/local.cf
</pre>
y pegar
<pre class="code"># Puntuaci&oacute;n para ser marcado spam
required_hits 5.0
# Texto que se antepondr&aacute; al asunto de los emails que sean spam
rewrite_header Subject [*****SPAM*****]
# Encapsular spam en un adjunto al email de aviso
report_safe 1
# Habilitar systema Bayes
use_bayes 1
# Autoaprendizaje
bayes_auto_learn 1
bayes_path /home/spamfilter/
bayes_file_mode 0666
# Comprobaciones de spam
skip_rbl_checks 0
use_razor2 1
use_dcc 1
use_pyzor 1
</pre>
<p>Comprobar si la configuraci&oacute;n es correcta:</p>
<pre class="code">spamassassin --lint
</pre>
<p>Posiblemente nos avise de algunos warnings referentes a las comprobaciones de spam, pero en principio no tiene mayor importancia.</p>
<h3>Configurando Postfix</h3>
Editar /etc/postfix/master.cf. Reemplazaremos la directiva <em>smtp</em> por lo siguiente
<pre class="code">smtp inet n - n - - smtpd
   -o content_filter=spamfilter:dummy
spamfilter unix - n n - - pipe
   flags=Rq user=spamfilter argv=/usr/local/bin/spamfilter.sh -f ${sender} -- ${recipient}
</pre>
<p>Editar /etc/postfix/main.cf</p>
<pre class="code">strict_rfc821_envelopes = yes
disable_vrfy_command = yes
smtpd_helo_required = yes
smtpd_client_restrictions =
smtpd_helo_restrictions =
smtpd_sender_restrictions =
smtpd_recipient_restrictions =
   permit_mynetworks,
   permit_sasl_authenticated,
   reject_unauth_destination,
   reject_invalid_hostname,
   reject_unauth_pipelining,
   reject_non_fqdn_sender,
   reject_unknown_sender_domain,
   reject_non_fqdn_recipient,
   reject_unknown_recipient_domain,
   check_client_access hash:$config_directory/access_client,
   check_sender_access hash:$config_directory/access_sender
   permit
</pre>
<h3 class="editable wrapchrome">Conectando Postfix a SpamAssassin</h3>
<div class="editable wrapchrome">Buscar los binarios <em>spamc</em> y <em>sendmail</em> (variar&aacute; seg&uacute;n la distribuci&oacute;n)
<pre class="code">locate spamc
 /usr/bin/spamc
locate sendmail
 /usr/sbin/sendmail
</pre>
<p>Crear el siguiente script shell</p>
<pre class="code">nano /usr/local/bin/spamfilter.sh
</pre>
<p>y pegar</p>
<pre class="code">#!/bin/bash
/usr/bin/spamc | /usr/sbin/sendmail -i "$@"
exit $?
</pre>
<p>Debemos tener <span style="text-decoration: underline;">mucho cuidado con las rutas</span>, ya que si ponemos mal las rutas los correos no llegar&aacute;n o llegar&aacute;n vac&iacute;os</p>
<pre class="code">chmod 755 /usr/local/bin/spamfilter.sh
chown spamfilter:spamfilter /usr/local/bin/spamfilter.sh
</pre>
<p>Reiniciamos servicios</p>
<pre class="code">/etc/init.d/spamassassin start
/etc/init.d/postfix restart
</pre>
<h3>Actualizar spam assassin y a&ntilde;adirlo al inicio del arranque de Linux</h3>
<p>Actualizaremos el servicio de cron</p>
<pre class="code">crontab -e
</pre>
<p>y a&ntilde;adiremos la siguiente l&iacute;nea para ejecutarse todos los viernes a las 8:01</p>
<pre class="code">01  8  *  *  5  sa-update &amp;&amp; service spamassassin restart
</pre>
<p>Por &uacute;ltimo lo a&ntilde;adimos a los scripts de inicio de CentOS</p>
<pre class="code">chkconfig --add spamd
</pre>
<h3>Borrando el spam recibido</h3>
<p>SpamAssassin no recomienda borrar el correo marcado spam por si ocurren falsos positivos, pero a&uacute;n as&iacute; vamos a filtrar los que claramente sean spam.</p>
<pre class="code">mkdir /var/spamchk
chmod -R 777 /var/spamchk 
chown -R spamfilter:spamfilter /var/spamchk
</pre>
<p>Hacemos una copia de seguridad de /usr/local/bin/spamfilter.sh a simple_spamfilter.sh y editaremos el archivo poniendo</p>
<pre class="code">#!/bin/sh

# Variables
SENDMAIL="/usr/sbin/sendmail -i"
EGREP=/bin/egrep
TMPFILE=/tmp/spamchk.$$
SIDELINE_DIR=/var/spamchk
# Puntuaci&oacute;n m&iacute;nima del correo para ser tratado como spam
SPAMLIMIT=10
# Limpiamos el archivo temporal
trap "rm -f $TMPFILE" 0 1 2 3 15
# Guardamos el mensaje temporalmente en $TMPFILE
cat | /usr/bin/spamc -u filter | sed 's/^.$/../' &gt; $TMPFILE
# Comprobamos si el correo est&aacute; marcado con un alto nivel de spam
if $EGREP -q "^X-Spam-Level: *{$SPAMLIMIT,}" &lt; $TMPFILE
then
  # Opci&oacute;n 1: guardarlos en el disco duro
  # mv $TMPFILE $SIDELINE_DIR/`date +%Y-%m-%d_%R`-$$
  # Opci&oacute;n 2: Env&iacute;alo a una cuenta de correo de spam para tenerlos guardados
   $SENDMAIL spam@xxxx.xx &lt; $TMPFILE
  # Opci&oacute;n 3: Borra el mensaje
  # rm -f $TMPFILE
else
$SENDMAIL "$@" &lt; $TMPFILE
fi
# Postfix devuelve el estado de salida de la llamada a sendmail command.
exit $?
</pre>
<p>El umbral para tratar los correos de spam es la variable SPAMLIMIT. Un valor de 10 es un buen valor inicial, pero deberemos ir cambi&aacute;ndolo hasta afinar con el valor m&aacute;s correcto. Aconsejamos un valor m&iacute;nimo de 5.</p>
<h3>Desinstalando Spam Assassin</h3>
<p>Si tenemos alg&uacute;n problema, podemos desinstalarlo editando /etc/postfix/master.cf reemplazando el contenido</p>
<pre class="code">smtp inet n - n - - smtpd
   -o content_filter=spamfilter:dummy
spamfilter unix - n n - - pipe
   flags=Rq user=spamfilter argv=/usr/local/bin/spamfilter.sh -f ${sender} -- ${recipient}
</pre>
por
<pre class="code">smtp inet n - n - - smtpd
</pre>
<p>despu&eacute;s reinicia los servicios</p>
<pre class="code">/etc/init.d/spamassassin start
/etc/init.d/postfix restart
</pre>
<h3>Instalando una interfaz web para SpamAssassin: webuserprefs</h3>
<p>El hecho de tener que aprender o estar revisando la documentaci&oacute;n para modificar el archivo de configuraci&oacute;n es bastante tedioso. Podemos instalar la interfaz gr&aacute;fica <strong>webuserprefs</strong> (hecha en PHP) que nos ayudar&aacute; en ello.</p>
<p>En nuestro caso crearemos desde Plesk un subdominio para ello. No es necesario, ya que podremos instalarlo en una carpeta, pero por comodidad lo hemos hecho as&iacute;: webuserprefs.xxxxxxx.xxx</p>
<p>Borramos todo el contenido que por defecto trae Plesk y nos situaremos en el directorio objetivo para descargarnos la &uacute;ltima versi&oacute;n de webuserprefs (0.6 en el momento de escribir esta gu&iacute;a).</p>
<p>Lo descomprimiremos y daremos permisos necesarios.</p>
<pre class="code">wget http://downloads.sourceforge.net/project/webuserprefs/webuserprefs/0.6/webuserprefs-0.6.tar.gz
tar xvzf webuserprefs-0.6.tar.gz
chown -R user:group *</pre>
<p>Protegeremos el subdominio mediante "Plesk protected directories system", si no usamos Plesk deberemos usar el sistema de usuarios de Apache y htaccess.</p>
<div class="editable wrapchrome">La aplicaci&oacute;n webuserprefs modifica el archivo $HOME/.spamassassin/user_prefs donde $HOME es el directorio home del usuario que ejecuta spamd (podemos saberlo ejecutando de nuevo <em>spamassassin --lint</em>) pero como webuserprefs es una aplicaci&oacute;n web, las restricciones de PHP open_basedir no nos van a permitir modificarlo. A partir de ahora, $WEBUSERPREFS ser&aacute; el directorio donde est&aacute; webuserprefs.</div>
<div class="editable wrapchrome"></div>
<div class="editable wrapchrome">Una forma f&aacute;cil es crear ese archivo en el directorio donde est&eacute; la ra&iacute;z de webuserprefs y crear un enlace s&iacute;mb&oacute;lico desde $HOME/.spamassassin/user_prefs a &eacute;ste.</div>
<pre class="code">touch $WEBUSERPREFS/user_prefs
chmod 666 $WEBUSERPREFS/user_prefs
cd $HOME/.spamassassin
ln -s $WEBUSERPREFS/user_prefs user_prefs
</pre>
<p>&Eacute;ste archivo estar&aacute; protegido mediante el usuario y contrase&ntilde;a de htaccess y tampoco contiene informaci&oacute;n sensible, como mucho redes o dominios desde no se acepta emails.</p>
<p>Finalmente editaremos webuserprefs desde su archivo de configuraci&oacute;n buscando las siguientes l&iacute;neas y cambi&aacute;ndolas a:</p>
<pre class="code">// require("auth/server.php");
$user_prefs     = "user_prefs";
$group_sort     = "yes";
</pre>
<h3>Fuentes</h3>
<p>Este art&iacute;culo es una mezcla con a&ntilde;adidos y modificaciones en varias partes de &eacute;ste de las siguientes fuentes:</p>
<ul>
<li><a href="http://www.xnote.com/howto/postfix-spamassassin.html" target="_blank">http://www.xnote.com/howto/postfix-spamassassin.html</a></li>
<li><a href="http://www.akadia.com/services/postfix_spamassassin.html" target="_blank">http://www.akadia.com/services/postfix_spamassassin.html</a></li>
<li><a href="http://wiki.apache.org/spamassassin/FrequentlyAskedQuestions" target="_blank">http://wiki.apache.org/spamassassin/FrequentlyAskedQuestions</a></li>
<li><a href="http://wiki.apache.org/spamassassin/DeletingAllMailsMarkedSpam" target="_blank">http://wiki.apache.org/spamassassin/DeletingAllMailsMarkedSpam</a></li>
<li><a href="http://blog.garion.org/2011/04/23/deleting-spam-with-postfix-and-spamassassin/" target="_blank">http://blog.garion.org/2011/04/23/deleting-spam-with-postfix-and-spamassassin/</a></li>
<li><a href="http://wiki.apache.org/spamassassin/WebUserInterfaces" target="_blank">http://wiki.apache.org/spamassassin/WebUserInterfaces</a></li>
<li><a href="http://wiki.apache.org/spamassassin/SingleUserUnixInstall#head-1dd15c06b7e645638def3d2ed2ef31557d853659" target="_blank">http://wiki.apache.org/spamassassin/SingleUserUnixInstall#head-1dd15c06b7e645638def3d2ed2ef31557d853659</a></li>
</ul>
</div>
</div>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=93</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/instalando-un-antispam-con-spamassassin-y-postfix.html</feedburner:origLink>
		</item>
				
		<item>
			<title>HTML 5. Inserción de video o audio en la web</title>
			<link>http://www.imaginanet.com/blog/html-5-insercion-de-video-o-audio-en-la-web.html</link>
			<guid>http://www.imaginanet.com/blog/html-5-insercion-de-video-o-audio-en-la-web.html</guid>
			<comments>http://www.imaginanet.com/blog/html-5-insercion-de-video-o-audio-en-la-web.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue, 17 Jan 2012 14:02:32 +0100</pubDate>
					<category><![CDATA[HTML5]]></category>
					<category><![CDATA[Web 2.0]]></category>
					<category><![CDATA[Navegadores]]></category>
					<description><![CDATA[Siempre hay ocasiones en las que es necesario insertar un video o un fichero de audio para que se reproduzca de forma integrada en la web sin neesidad de descargarlo a tu disco duro y abrirlo con tu reproductor habitual.
Hasta ahora esto se ha hecho siempre mediante la inserci&oacute;n de macros a trav&eacute;s de la etiqueta html...]]></description>
			<content:encoded><![CDATA[><p>Siempre hay ocasiones en las que es necesario insertar un <em>video </em>o un fichero de <em>audio </em>para que se reproduzca de forma integrada en la web sin neesidad de descargarlo a tu disco duro y abrirlo con tu reproductor habitual.</p>
<p>Hasta ahora esto se ha hecho siempre mediante la inserci&oacute;n de macros a trav&eacute;s de la etiqueta html <strong><em>iframe </em></strong>o mediante un <em><strong>reproductor flash</strong></em>. Esto tiene dos inconvenientes:</p>
<p>El primero de ellos es que para que todo cuadre en la web. El que lo inserta debe saber el suficiente html para que ajuste el tama&ntilde;o a la proporci&oacute;n adecuada de tal forma que todo se ajuste a la maqueta como deber&iacute;a.</p>
<p>El segundo de los inconvenientes es que la inserci&oacute;n de macros siempre es un problema en cuanto a seguridad, ya que se est&aacute; cargando contenido de otra web en la nuestra, lo cual puede provocar que nuestra web sea portadora de virus si no se utiliza con cuidado.</p>
<p>El flash por su parte, en funci&oacute;n de los navegadores, puede generar graves problemas de rendimiento (Especialmente en Internet Explorer). Adem&aacute;s del hecho de que no es posible reproducir flash en ciertos dispositivos, como los de Apple, en&oacute;rmemente extendidos ha d&iacute;a de hoy.</p>
<p>En el caso de que la web no est&eacute; pensada para ser visualizada en dispositivos m&oacute;viles o tablets, en principio, de esta forma se puede obtener un reproductor de audio o de video muy facilmente. A continuaci&oacute;n vemos unos ejemplos de c&oacute;mo insertar videos flv en la web con un <a href="http://flv-player.net/">reproductor flash</a>,</p>
<p>&lt;object type="application/x-shockwave-flash" data="http://flv-player.net/medias/player_flv.swf" width="300" height="220"&gt;<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;param name="movie" value="http://flv-player.net/medias/player_flv.swf" /&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="allowFullScreen" value="true" /&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="FlashVars" value="flv=http://www.miweb.es/video.flv" /&gt;<br />&lt;/object&gt;</p>
<p>Con este c&oacute;digo cargaremos un reproductor de video flash que nos permitir&aacute; ver videos flv en nuestra web insert&aacute;ndolo all&iacute; donde queramos que se reproduzca el video. Sin embargo, los sitios como youtube o vimeo, no permiten reproducir los videos de forma directa a traves del reproductor flash, porque ya tienen su propio sistema. En estos casos, debemos, o bien insertar dir&eacute;ctamente le c&oacute;digo iframe que nos ofrece youtube o vimeo para que todo funcione corr&eacute;ctamente ajustando los par&aacute;metros de anchura y altura del iframe que nos dan para que cuadre en donde lo queramos poner. A continuaci&oacute;n se muestra un ejemplo de youtube:</p>
<p>&lt;iframe width="560" height="315" src="http://www.youtube.com/embed/bxP0VnbHSxE" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;</p>
<p>Existe una alternativa que, aunque tambien pasa por los iframes, facilita mucho la labor para alguien que no sabe HTML. Tanto Youtube como Vimeo, tienen un c&oacute;digo asociado a cada uno de sus videos que acompa&ntilde;a a la url mediante par&aacute;metros get. De cara al porgramador es algo m&aacute;s laborioso, porque debe procesar el enlace por php, extraer el c&oacute;digo citado de youtube o vimeo, y acoplarlo a un enlace de tipo embed de la web que corresponda (Youtube o Vimeo). B&aacute;sicamente, se trata de montar nuestro propio iframe sabiendo cual es el formato de los enlacess embed de Vimeo y de Youtube, los cuales podemos ver facilmente en los iframes para insertar un video que nos proporcionan dichas webs.</p>
<p>En el caso del audio, tambien se usa un c&oacute;digo flash que carga el reproductor instalado por defecto en nuestro navegador. El m&aacute;s utilizado suele ser Windows media player, debido a al gran expansi&oacute;n de los sistemas operativos Windows.</p>
<p>&nbsp;</p>
<h3>Etiquetas audio y video de HTML 5</h3>
<p>En HTML 5 tenemos la posibilidad de reproducir audio y video dir&eacute;ctamente mediante el uso de las etiquetas <strong>audio</strong> y <strong>video</strong>.</p>
<h3>La etiqueta Audio</h3>
<p>Nos permite insertar un fichero de audio con un reproductor en nuestra web, que nos permitira escucharlo sin necesidad de tener instalado ning&uacute;n programa adicional para dicho fin. Un ejemplo de sintaxis de esta etiqueta ser&iacute;a el siguiente:</p>
<p>&lt;audio src=&rdquo;audio.mp3&Prime; type=&rdquo;audio/mp3&Prime; controls autoplay /&gt;</p>
<p>A continuaci&oacute;n se expone una breve descripci&oacute;n de algunos de los atributos disponibles para esta etiqueta.</p>
<p><em><strong>src</strong></em>. Indica la ruta del archivo a reproducir.</p>
<p><em><strong>autoplay</strong></em>. Permite que la reproducci&oacute;n comience de forma autom&aacute;tica sin previo aviso. En ocasiones no se recomienda su uso para dejar que el usuario decida cuando reproducir audio cuando lo desee.</p>
<p><em><strong>autobuffer</strong></em>. Nos permite cargar de forma autom&aacute;tica el archivo para que sea m&aacute;s r&aacute;pida su reproducci&oacute;n a posteriori y reducir a&iacute; tiempos de espera para el usuario.</p>
<p><em><strong>width </strong></em>y height. Definen respectivamente la anchura y la altura que debera&aacute; tener la etiqueta de audio.</p>
<p><em><strong>loop</strong></em>. Ejecuta la reproducci&oacute;n en bucle de forma que al finalizar vuelve a empezar.</p>
<p><em><strong>controls</strong></em>. Muestra los controles de reproducci&oacute;n.</p>
<p><em><strong>type</strong></em>. Define el tipo de archivo a reproducir y su extensi&oacute;n (video, audio...)/(mp3, ogg...).</p>
<h3>La etiqueta Video</h3>
<p>En el caso de la etiqueta de video, atributos son muy similares a los de la etiqueta audio. Aqu&uacute; un ejemplo de su sint&aacute;xis.</p>
<p>&lt;video src=&rdquo;video.ogg&rdquo;&gt;<br /> &lt;!&ndash; C&oacute;digo a mostrar en navegadores que no soportan HTML 5 &ndash;&gt;<br /> &lt;/video&gt;</p>
<p>Para m&aacute;s informaci&oacute;n pod&eacute;is consultar <a href="http://dev.w3.org/html5/spec/Overview.html#the-audio-element">este enlace</a>.<em>&nbsp;</em></p>
<p><em>El inconveniente de utilizar estas etiquetas es que hay navegadores que no soportan corr&eacute;ctamente todas las funcionalidades de html5 y por ese motivo no se utilizan todav&iacute;a de forma habitual.<br /></em></p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=92</wfw:commentRss>
			<slash:comments>1</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/html-5-insercion-de-video-o-audio-en-la-web.html</feedburner:origLink>
		</item>
				
		<item>
			<title>El Proyecto FFMPEG</title>
			<link>http://www.imaginanet.com/blog/el-proyecto-ffmpeg.html</link>
			<guid>http://www.imaginanet.com/blog/el-proyecto-ffmpeg.html</guid>
			<comments>http://www.imaginanet.com/blog/el-proyecto-ffmpeg.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Fri, 30 Dec 2011 17:02:12 +0100</pubDate>
					<category><![CDATA[Android]]></category>
					<category><![CDATA[Linux]]></category>
					<category><![CDATA[Rendimiento]]></category>
					<description><![CDATA[FFMPEG es un r&aacute;pido sistema de conversi&oacute;n de v&iacute;deo y audio, que adem&aacute;s de permitir la conversi&oacute;n entre muchos de los formatos conocidos como MP4, MPEG para v&iacute;deo y mp3 o amr para audio, entre otros.
FFServer nos permite transmitir v&iacute;deo y audio que haya sido previamente convertido a...]]></description>
			<content:encoded><![CDATA[><p>FFMPEG es un r&aacute;pido sistema de conversi&oacute;n de v&iacute;deo y audio, que adem&aacute;s de permitir la conversi&oacute;n entre muchos de los formatos conocidos como MP4, MPEG para v&iacute;deo y mp3 o amr para audio, entre otros.</p>
<p>FFServer nos permite transmitir v&iacute;deo y audio que haya sido previamente convertido a alguno de los formatos soportados por FFMPEG adem&aacute;s de hacerlo tambi&eacute;n en tiempo real combin&aacute;ndolo con FFMPEG, mediante flujos FFM.</p>
<p>FFPlay es un reproductor de medios muy sencillo que utiliza las librer&iacute;as de FFMPEG y SDL. Normalmente, se utiliza como sistema de testeo cuando se trabaja con FFMPEG.</p>
<p>Ahora que ya conocemos las distintas herramientas que vamos a utilizar, podemos empezar a analizarlas con un poco m&aacute;s de profundidad.</p>
<p>&nbsp;</p>
<h3>Herramientas de conversi&oacute;n FFMPEG</h3>
<p><strong><em><span style="text-decoration: underline;">Funcionamiento</span></em></strong></p>
<p>FFMPEG, funciona por l&iacute;nea de comandos. La forma general de invocar a FFMPEG es la siguiente:</p>
<p>ffmpeg [[Opciones para el fichero de entrada][-i Fichero de entrada]]&hellip;{[Opciones para el fichero de salida] Fichero de salida}.</p>
<p>Mediante esta estructura general tan sencilla, FFMPEG no s&oacute;lo nos permite convertir ficheros que se encuentren en nuestro PC, sino que podemos capturar el v&iacute;deo o el audio, en funci&oacute;n de lo que nos interese, desde cualquier fuente, ya sea una tarjeta capturadora de v&iacute;deo o una direcci&oacute;n IP de una m&aacute;quina local o remota en la que se encuentre el fichero de audio o v&iacute;deo a convertir.</p>
<p>A continuaci&oacute;n veremos las opciones de FFMPEG m&aacute;s importantes y que se suelen usar con m&aacute;s frecuencia.</p>
<p><strong><em><span style="text-decoration: underline;">Opciones Principales</span></em></strong></p>
<p><strong>-h</strong></p>
<p>Nos muestra la ayuda del programa, es decir, nos muestra cuales son las diferentes opciones que FFMPEG acepta como argumento.</p>
<p><strong>-formats</strong></p>
<p>Nos muestra una lista de los formatos que soporta el programa tanto de entrada como de salida. Los campos que preceden al nombre del formato nos dicen si ese formato es aceptado como par&aacute;metro de entrada o como par&aacute;metro de salida.</p>
<p><em><span style="text-decoration: underline;">&lsquo;D&rsquo;</span></em> (<em>Decoding Available</em>). Si el nombre de un formato viene precedido de este campo, nos dice que es posible decodificar dicho formato, es decir, que FFMPEG lo puede recibir como par&aacute;metro de entrada.</p>
<p><em><span style="text-decoration: underline;">&lsquo;E&rsquo;</span></em> (<em>Encoding available</em>). Este campo por su parte, no informa sobre la posibilidad de codificar este formato, lo que nos indica que se puede utilizar como par&aacute;metro de salida de FFMPEG.</p>
<p><strong>-codecs</strong></p>
<p>Esta opci&oacute;n nos permite saber cuales de los codecs (codificadores, decodificadores o ambos) est&aacute;n disponibles en el programa. Los campos que preceden al nombre de del c&oacute;dec, nos dicen si el codificador o el decodificador est&aacute;n disponibles y si lo est&aacute;n para audio o v&iacute;deo.</p>
<p><em><span style="text-decoration: underline;">&lsquo;D&rsquo;</span></em>&nbsp; (<em>Decoding Available</em>). Nos indica si el decodificador est&aacute; disponible para ese c&oacute;dec.</p>
<p><em><span style="text-decoration: underline;">&lsquo;E&rsquo;</span></em> (<em>Encoding Available</em>). Si este campo est&aacute; presente, nos dice que el codificador est&aacute; disponible para el c&oacute;dec a cuyo nombre precede.</p>
<p><em><span style="text-decoration: underline;">V/A/S</span></em>. Nos indica si el c&oacute;dec est&aacute; disponible para audio, v&iacute;deo o subt&iacute;tulos.</p>
<p><em><span style="text-decoration: underline;">&lsquo;S&rsquo;</span></em>. Es lo que nos indica si el c&oacute;dec soporta cortes.</p>
<p><em><span style="text-decoration: underline;">&lsquo;D&rsquo;</span></em>. El c&oacute;dec soporta renderizado directo.</p>
<p><em><span style="text-decoration: underline;">&lsquo;T&rsquo;</span></em>. El c&oacute;dec es capaz de manejar v&iacute;deos a la entrada que est&eacute;n truncados aleatoriamente en lugar de en los l&iacute;mites de en los frames &uacute;nicamente.</p>
<p><strong>-f formato</strong></p>
<p>La opci&oacute;n &lsquo;-f &rsquo;, nos permite especificar el formato que tiene nuestro v&iacute;deo de entrada y el que tendr&aacute; el v&iacute;deo a la salida.</p>
<p><strong>-i</strong></p>
<p>Esta opci&oacute;n es la que nos permite especificar la fuente de la que se extraer&aacute; el v&iacute;deo, ya sea local o remota.</p>
<p>Si la fuente es local, tendremos sentencias como esta: ffmpeg &ndash;i video.yuv.</p>
<p>Si por el contrario, la fuente es remota podremos encontrarnos con sentencias como esta: ffmpeg &ndash;i tcp://192.168.3.25:5432.</p>
<p>&nbsp;</p>
<p><strong>-target type</strong></p>
<p>Transforma el fichero de la entrada al formato que se indica en el campo &lsquo;type&rsquo;, ajustando autom&aacute;ticamente opciones como el bitrate, el c&oacute;dec, o el tama&ntilde;o del buffer.</p>
<p><strong><em><span style="text-decoration: underline;">Opciones de Video</span></em></strong></p>
<p><strong>-b &lsquo;bitrate&rsquo;</strong></p>
<p>Nos permite modificar el ratio de bits (en Kbps) que se usar&aacute; para nuestro video tanto a la entrada como a la salida.</p>
<p><strong>-r &lsquo;fps&rsquo;</strong></p>
<p>Nos permite modificar el n&uacute;mero de im&aacute;genes por segundo que se mostrar&aacute;n en nuestro video.</p>
<p><strong>-s &lsquo;size&rsquo;</strong></p>
<p>Con esta opci&oacute;n podemos establecer la resoluci&oacute;n, ya sea manualmente introduciendo los valores&nbsp; de la forma &lsquo;WxH&rsquo;, donde &lsquo;W&rsquo; es el ancho y &rsquo;H&rsquo; la altura, o bien usando alguna de las abreviaturas&nbsp; que reconoce el programa para establecer alguna resoluci&oacute;n est&aacute;ndar como por ejemplo HD a 1080p que se puede especificar como &lsquo; ffmpg &ndash;i video.avi &ndash;s hd1080 videohd.mpeg&rsquo;.</p>
<p><strong>-aspect &lsquo;aspect&rsquo;</strong></p>
<p>Incluyendo esta opci&oacute;n, podremos especificar el formato de pantalla en el que se va a visualizar el video, y por tanto lo adaptaremos a dicho formato de pantalla. Los m&aacute;s conocidos son el formato &lsquo;4 : 3&rsquo; y el formato &lsquo;16 : 9&rsquo; (pantalla panor&aacute;mica).</p>
<p><strong>-vcodec &lsquo;codec&rsquo;</strong></p>
<p>Nos permite establecer un c&oacute;dec determinado para realizar la conversi&oacute;n de v&iacute;deo.</p>
<p><strong><em><span style="text-decoration: underline;">Opciones de Audio</span></em></strong></p>
<p><strong>-ar&nbsp; &lsquo;freq&rsquo;</strong></p>
<p>Con esta opci&oacute;n podemos seleccionar la frecuencia de muestreo para nuestro fichero de audio.</p>
<p><strong>-ab &lsquo;bitrate&rsquo;</strong></p>
<p>Esto nos permite seleccionar el n&uacute;mero de bits por segundo en el fichero de audio en Kilobits por segundo, donde sus valores m&aacute;s frecuentes son 64 Kbps, 128 Kbps o 192 Kbps.</p>
<p><strong>-ac &lsquo;chanels&rsquo;</strong></p>
<p>Nos permite decidir a qu&eacute; tipo de sonido se adaptar&aacute; nuestro fichero de audio, mono (opci&oacute;n &lsquo;1&rsquo;) o est&eacute;reo (opci&oacute;n &lsquo;2&rsquo;).</p>
<p>Adem&aacute;s de las citadas en este documento, FFMPEG, ofrece una amplia gama de opciones que nos permiten realizar m&uacute;ltiples cambios en los ficheros a la entrada y a la salida, ya sean de audio o de v&iacute;deo, e independiente mente, de si su fuente es un fichero propiamente dicho o una tarjeta capturadora de televisi&oacute;n o una dispositivo externo de v&iacute;deo digital como por ejemplo una c&aacute;mara que grabe en formato dv1.</p>
<p>Para tener una visi&oacute;n m&aacute;s completa sobre el funcionamiento de FFMPEG, conviene revisar la documentaci&oacute;n oficial del proyecto que se puede encontrar en <a href="http://www.ffmpeg.org/">www.ffmpeg.org</a> o bien, si ya tenemos instalado FFMPEG en el equipo, usar el comando &lsquo;man&rsquo; para acceder a la ayuda del mismo.</p>
<p><strong><em><span style="text-decoration: underline;">Algunos Ejemplos de Aplicaci&oacute;n</span></em></strong></p>
<p>Ahora que ya hemos visto algunas de las opciones m&aacute;s importantes de FFMPEG de cara al proyecto, para una mejor comprensi&oacute;n nos valdremos de algunos ejemplos que servir&aacute;n para tener una idea gr&aacute;fica de lo que hacen las opciones y de c&oacute;mo se pueden combinar.</p>
<p>Por ejemplo podemos convertir un fichero&nbsp; YUV420P a un&nbsp; .avi con la siguiente sentencia:</p>
<p><em>ffmpeg -i /home/prueba.yuv /home/salida.avi</em>.</p>
<p>Tambi&eacute;n podemos realizar el proceso contrario, obteniendo como resultado un fichero de video puro (YUV420P).</p>
<p><em>ffmpeg &ndash;i /home/video.avi videoPuro.yuv.</em></p>
<p>Tambi&eacute;n podemos establecer m&aacute;s de un fichero a la entrada cuando queremos que estos se conviertan a un mismo formato de esta forma.</p>
<p><em>ffmpeg &ndash;i /tmp/a.wav &ndash;s 640x480 &ndash;i /tmp/a.yuv /tmp/a.mpg.</em></p>
<p>De esta forma convertiremos los dos ficheros tanto el de v&iacute;deo como el de audio a mpeg. Tendremos dos ficheros nombrados exactamente igual, pero en el uno habr&aacute; audio y en el otro v&iacute;deo.</p>
<p>Si se necesitan m&aacute;s ejemplos se puede acudir a <a href="http://www.ffmpeg.org/">www.ffmpeg.org</a> y consultar la secci&oacute;n de documentaci&oacute;n para tener todos los ejemplos de conversi&oacute;n entre formatos, ya sean de audio o de v&iacute;deo.</p>
<p>&nbsp;</p>
<h3><strong>Streaming de v&iacute;deo y audio con FFSERVER</strong></h3>
<p>FFServer es un sistema que nos permite transmitir ficheros de audio o v&iacute;deo en tiempo real o con ficheros previamente convertidos. Este programa funciona mediante un fichero de configuraci&oacute;n denominado <em>ffserver.conf</em>, situado en /etc.</p>
<p>Se puede ejecutar de forma individual utilizando la siguiente sintaxis:</p>
<p>ffserver [Opciones].</p>
<p>Tambi&eacute;n podemos arrancarlo cuando ejecutamos FFMPEG solicit&aacute;ndole una fuente o un destino remoto.</p>
<p>A continuaci&oacute;n veremos las principales opciones que FFServer nos proporciona para su ejecuci&oacute;n por l&iacute;nea de comandos.</p>
<p><strong><em><span style="text-decoration: underline;">Opciones</span></em></strong></p>
<p><strong>-L</strong></p>
<p>Nos muestra la licencia del programa.</p>
<p><strong>-version</strong></p>
<p>Nos indica la versi&oacute;n que tenemos instalada en nuestro equipo.</p>
<p><strong>-formats</strong></p>
<p>Nos muestra una lista de los formatos, codecs y protocolos que soporta FFServer, entre otros.</p>
<p><strong>-f </strong>&lsquo;Fichero de Configuraci&oacute;n.</p>
<p>Nos permite especificar un fichero de configuraci&oacute;n alternativo al existente en /etc/ffserver.conf.</p>
<p><strong>-n</strong></p>
<p>Esta opci&oacute;n anula todas las directivas de ejecuci&oacute;n que permiten al programa ejecutar FFMPEG de forma autom&aacute;tica. De este modo, el usuario tendr&aacute; que ejecutar FFMPEG de forma manual.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=91</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/el-proyecto-ffmpeg.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Cómo visualizar videos FLV en fancybox</title>
			<link>http://www.imaginanet.com/blog/como-visualizar-videos-flv-en-fancybox.html</link>
			<guid>http://www.imaginanet.com/blog/como-visualizar-videos-flv-en-fancybox.html</guid>
			<comments>http://www.imaginanet.com/blog/como-visualizar-videos-flv-en-fancybox.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Fri, 23 Dec 2011 14:37:57 +0100</pubDate>
					<category><![CDATA[Flash]]></category>
					<category><![CDATA[JavaScript]]></category>
					<description><![CDATA[Es muy com&uacute;n a d&iacute;a de hoy colocar videos en nuestras p&aacute;ginas web. Para ello tenemos dos alternativas utilizar alg&uacute;n proveedor de videos que nos preste su ancho de banda (youtube, vimeo, &hellip;) o utilizar el de nuestro servidor. Hay casos en los que elegir nuestro servidor puede ser debido a motivos...]]></description>
			<content:encoded><![CDATA[><p>Es muy com&uacute;n a d&iacute;a de hoy colocar videos en nuestras p&aacute;ginas web. Para ello tenemos dos alternativas utilizar alg&uacute;n proveedor de videos que nos preste su ancho de banda (youtube, vimeo, &hellip;) o utilizar el de nuestro servidor. Hay casos en los que elegir nuestro servidor puede ser debido a motivos de privacidad de los contenidos.</p>
<p>Sea como sea, si lo que te interesa es subir un video FLV a tu propio servidor y adem&aacute;s utilizarlo con el plugin Fancybox, entonces puedes seguir leyendo. Lo primero es tener un reproductor de FLV para web. Hay cientos de reproductores disponibles, tanto gratuitos como de pago, tan solo hay que buscar flv player en google. Podeis utilizar por ejemplo el de flv-player.net que tiene varias versiones (completas o m&aacute;s ligeras sin algunas funcionalidades).</p>
<p>Una vez tenemos el archivo flv y el reproductor flv (es un archivo swf), ya solo nos falta descargar Fancybox. Suponemos que sabemos utilizar fancybox, por tanto montamos una p&aacute;gina sencilla que requiera los archivos javascript necesarios as&iacute; como sus hojas de estilos.</p>
<p>En est&aacute; pagina a&ntilde;adimos un enlace:</p>
<pre class="code"><a class="&rdquo;video_flv&rdquo;" href="/imaginanet/&rdquo;#flv&rdquo;">Ver video</a>
</pre>
<p>Si nos fijamos en el href le hemos colocado un id. De esta forma fancybox cargar&aacute; el contenido de dicho identificador en el popup que abra. Por tanto ahora solo nos falta definir dicho identificador.</p>
<pre class="code"><div style="display: none;">
	<div id="flv">
              <object width="680" height="495" data="/player_flv_maxi.swf" type="application/x-shockwave-flash"><param name="data" value="/player_flv_maxi.swf" /><param name="FlashVars" value="flv=mi_video.flv&amp;showstop=1&amp;showvolume=1&amp;showtime=1&amp;showfullscreen=1" /><param name="src" value="/player_flv_maxi.swf" /></object>								
        </div>
</div>	
</pre>
<p>Hemos introducido la capa con identificador &ldquo;flv&rdquo; dentro de otra capa con &ldquo;display&rdquo; &ldquo;none&rdquo;, de esta manera al entrar en la p&aacute;gina no aparecer&aacute; el video directamente. Dentro de la capa &ldquo;flv&rdquo; tenemos la etiqueta &ldquo;object&rdquo; que lleva el reproductor de FLV (player_flv_maxi.swf) y una serie de parametros para configurar el reproductor donde el m&aacute;s importante es el que define el video a reproducir y cuyo nombre es &ldquo;flv&rdquo;. En el ejemplo vemos como le asignamos mi_video.flv como video a reproducir.</p>
<p>Finalmente solo nos falta el c&oacute;digo javascript que va a hacer que al hacer click en nuestro enlace se abra Fancybox con nuestro video.</p>
<pre class="code">$("a.video_flv").fancybox({
'overlayOpacity': 0,
	'hideOnContentClick': false,
	'padding': 0,
	'autoScale': false,
	'autoDimensions': false,
	'width': 680,
	'height': 495,								
	'titleShow': false,
	'overlayColor': '#000'
});
</pre>
<p>Estamos utilizando un selector con jquery para a&ntilde;adirle el evento de fancybox con una configuraci&oacute;n donde cabe destacar el autoscale y autodimensions desactivados para asi fijar el tama&ntilde;o del popup a abrir. De esta forma conseguimos ver nuestro video flv en fancybox.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=90</wfw:commentRss>
			<slash:comments>1</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/como-visualizar-videos-flv-en-fancybox.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Maquetación en HTML5</title>
			<link>http://www.imaginanet.com/blog/maquetacion-en-html5.html</link>
			<guid>http://www.imaginanet.com/blog/maquetacion-en-html5.html</guid>
			<comments>http://www.imaginanet.com/blog/maquetacion-en-html5.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue, 13 Dec 2011 16:35:26 +0100</pubDate>
					<category><![CDATA[Web 2.0]]></category>
					<category><![CDATA[CSS]]></category>
					<category><![CDATA[HTML5]]></category>
					<description><![CDATA[HTML5 nos brinda la posibilidad de poder a&ntilde;adir m&aacute;s sem&aacute;ntica a nuestras webs,  	pudiendo hacer distinciones entre bloques de contenido utilizando etiquetas  	como &lt;ARTICLE&gt;, &lt;SECTION&gt;, &lt;HEADER&gt;, &lt;FOOTER&gt;, &hellip; en lugar de poder distinguir &uacute;nicamente  	por estructura entre...]]></description>
			<content:encoded><![CDATA[><p><strong>HTML5</strong> nos brinda la posibilidad de poder a&ntilde;adir m&aacute;s sem&aacute;ntica a nuestras webs,  	pudiendo hacer distinciones entre bloques de contenido utilizando etiquetas  	como <strong>&lt;ARTICLE&gt;</strong>, <strong>&lt;SECTION&gt;</strong>, <strong>&lt;HEADER&gt;</strong>, <strong>&lt;FOOTER&gt;</strong>, &hellip; en lugar de poder distinguir &uacute;nicamente  	por estructura entre elementos de bloque o elementos en l&iacute;nea.</p>
<p>Como siempre, el principal problema al que nos enfretamos es la retrocompatibilidad con los navegadores ya que  	las versiones m&aacute;s antiguas de estos no entienden estas estructuras y no las  	representan de forma correcta.</p>
<p>Lo bueno es que, gracias a un poco de <strong>CSS</strong> y <strong>Javascript</strong> podemos "<em>ayudar</em>" a dichos navegadores a  	"<em>entender</em>" dichas etiquetas.</p>
<h3>Estructura de p&aacute;gina en HTML5. Olvid&aacute;ndonos del DOCTYPE</h3>
<p>La declaraci&oacute;n de una p&aacute;gina en HTML5 es mucho m&aacute;s sencilla que en las versiones anteriores:</p>
<pre class="code">&lt;!DOCTYPE html&gt;
&lt;html lang="es"&gt;
	&lt;head&gt;
		&lt;!-- Title --&gt;
		&lt;title&gt;{title}&lt;/title&gt;


		&lt;!-- Meta data --&gt;
		&lt;meta charset="UTF-8"&gt;
		&lt;meta name="description" content="{meta_descripcion}" /&gt; 
		&lt;meta name="keywords" content="{meta_keywords}" /&gt; 
		&lt;meta name="robots" content="index,all" /&gt;

		&lt;!--[if lte IE 8]&gt;
		&lt;script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"&gt;&lt;/script&gt;
		&lt;![endif]--&gt;		

		&lt;!-- Stylesheets --&gt;
		&lt;link rel="stylesheet" href="style/style.css"&gt;

		&lt;!-- Javascripts --&gt;
		&lt;script type="text/javascript" src="js/jquery.js"&gt;&lt;/script&gt;
	&lt;/head&gt;

	&lt;body&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
De todo esto, nos tiene que haber llamado la atenci&oacute;n una cosa:
<pre class="code">	&lt;!--[if lte IE 8]&gt;
	&lt;script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"&gt;&lt;/script&gt;
	&lt;![endif]--&gt;	
</pre>
<p>Esta l&iacute;nea indica que si nuestra versi&oacute;n de navegador es m&aacute;s peque&ntilde;o o igual que Internet Explorer 8, entonces hay que cargar el fichero html5.js que informar&aacute; al navegador de los nuevos elementos.</p>
<h3>Maquetaci&oacute;n de los nuevos elementos</h3>
<p>Al inicio de nuestra hoja de estilos, normalmente aplicamos una serie de estilos que sirven para "<em>resetear</em>"  	las hojas de estilos propias del navegador y as&iacute; intentar dar uniformidad a como se visualiza la p&aacute;gina en distintos  	navegadores y sistemas operativos.</p>
<p>Este ser&iacute;a un ejemplo de dichas reglas:</p>
<pre class="code">/* Reset the stylesheet */
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
dl, dt, dd, ol, ul, li,
fieldset, textarea, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
address, article, aside, audio, canvas, command, datalist, 
details, dialog, figure, figcaption, footer, header, hgroup,
keygen, mark, meter, menu, nav, progress,
ruby, section, time, video {
  margin: 0;
  padding: 0;
  border: 0;
  outline: 0;
  font-weight: inherit;
  font-style: inherit;
  font-size: 100%;
  font-family: inherit;
  vertical-align: baseline;
}
</pre>
<p>Como vemos, hemos incluido adem&aacute;s de las etiquetas t&iacute;picas de XHTML1.1 y HTML 4.1, las nuevas etiquetas de 	<em>address, article, aside, audio, canvas, command, datalist, details, dialog, figure, figcaption,  	footer, header, hgroup, keygen, mark, meter, menu, nav, progress, ruby, section, time, video.</em></p>
<p>Adem&aacute;s, con esta regla, vamos a especifcar cu&aacute;les de dichos elementos queremos que sean tratados como elementos de bloque.</p>
<pre class="code">/* HTML5 elements that are blocks */
aside, header, footer, article, section, 
nav, figure, figcaption {
	display: block;
}
</pre>
<p>Gracias a estos sencillos pasos podemos empezar a maquetar nuestras webs utilizando las ventajas de HTML5 ya que permitir&aacute;n que los resultados de motores de b&uacute;squeda sean m&aacute;s precisos con nuestros resultados adem&aacute;s de permitir, de forma sencilla, la sindicaci&oacute;n de contenidos o la publicaci&oacute;n de art&iacute;culos en las redes sociales.</p>
<p>Para m&aacute;s informaci&oacute;n sobre HTML5 puede leer la entrada <a href="http://www.imaginanet.com/blog/como-usar-html-5.html">C&oacute;mo usar HTML5</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=89</wfw:commentRss>
			<slash:comments>2</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/maquetacion-en-html5.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Programando un pasador o slider con jQuery y CSS</title>
			<link>http://www.imaginanet.com/blog/programando-un-pasador-o-slider-con-jquery-y-css.html</link>
			<guid>http://www.imaginanet.com/blog/programando-un-pasador-o-slider-con-jquery-y-css.html</guid>
			<comments>http://www.imaginanet.com/blog/programando-un-pasador-o-slider-con-jquery-y-css.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue, 13 Dec 2011 13:46:53 +0100</pubDate>
					<category><![CDATA[jQuery]]></category>
					<category><![CDATA[CSS]]></category>
					<description><![CDATA[La construcci&oacute;n de Sliders es una tarea que se ha simplificado mucho desde el surgimiento de  	frameworks y librer&iacute;as javascript como jQuery o Prototype. Lo que antes era una tarea ardua  	y pesada ahora es tarea de unas pocas l&iacute;neas de c&oacute;digo.
Para un ingeniero de Software, la tarea es ahora de...]]></description>
			<content:encoded><![CDATA[><p>La construcci&oacute;n de <strong>Sliders</strong> es una tarea que se ha simplificado mucho desde el surgimiento de  	frameworks y librer&iacute;as javascript como <strong>jQuery</strong> o <strong>Prototype</strong>. Lo que antes era una tarea ardua  	y pesada ahora es tarea de unas pocas l&iacute;neas de c&oacute;digo.</p>
<p>Para un ingeniero de Software, la tarea es ahora de encontrar una forma est&aacute;ndar de desarrollar dichos pasadores de forma  	que su soluci&oacute;n se aplique a la mayor&iacute;a (<em>sino a todos</em>) de los casos posibles de forma que no tenga pr&aacute;cticamente  	que modificar el c&oacute;digo generado ante cambios de dise&ntilde;o, como n&uacute;mero de elementos, paginadores, &hellip;</p>
<p>En el presente art&iacute;culo vamos a estudiar los elementos que contiene un slider, unos principios b&aacute;sicos de  	funcionamiento y una serie de pr&aacute;cticas &uacute;tiles en su programaci&oacute;n.</p>
<h3>Elementos del pasador</h3>
<p>Podemos distinguir entre los siguientes elementos dentro de un Slider:</p>
<ul>
<li><strong>Contenedor principal</strong>: Sirve para agrupar todos los elementos del Slider.</li>
<li><strong>Men&uacute; de navegaci&oacute;n</strong>. Contiene el men&uacute; que nos va a permitir navegar por los elementos. Pueden ser botones de anterior y siguiente o un paginador, por ejemplo.</li>
<li><strong>Capa contenedora</strong>. Este elemento sirve para determinar cual es el &aacute;rea visible que se a ver en pantalla. El truco consiste en ponerle unas dimensiones fijas y la propiedad overflow a hidden, para ocultar todo el contenido que se salga de su interior. Adem&aacute;s, tiene que tener posicionamiento relativo para poder especificar el posicionamiento absoluta del listado de elementos.</li>
<li><strong>Listado de elementos: </strong>Este elemento est&aacute; dentro de la capa contenedora y tiene un tama&ntilde;o que excede a su padre. Adem&aacute;s, tiene posicionamiento absoluto para poder animar la posici&oacute;n del listado respecto a la capa contenedora.</li>
</ul>
<p>Un ejemplo de este funcionamiento ser&iacute;a esto:</p>
<p><img src="http://www.imaginanet.com/ftp/blog/articulo-slider/funcionamiento-slider.png" alt="Ejemplo de funcionamiento" /></p>
<h3>Maquetaci&oacute;n del slider</h3>
<p>La maquetaci&oacute;n de los elementos anteriormente descritos podr&iacute;a ser as&iacute;:</p>
<pre class="code">	&lt;!-- Slider --&gt;
	&lt;div class=&rdquo;slider&rdquo;&gt;

		 &lt;!-- Capa contenedora --&gt;
		 &lt;div class=&rdquo;contenedor&rdquo;&gt;

	&lt;!-- Listado de elementos --&gt;
				&lt;ul&gt;
					 &lt;li&gt;&lt;img src=&rdquo;images/img1.jpg&rdquo; alt=&rdquo;image 1&rdquo;&gt;&lt;/li&gt;
					 &lt;li&gt;&lt;img src=&rdquo;images/img2.jpg&rdquo; alt=&rdquo;image 2&rdquo;&gt;&lt;/li&gt;
					 &lt;li&gt;&lt;img src=&rdquo;images/img3.jpg&rdquo; alt=&rdquo;image 3&rdquo;&gt;&lt;/li&gt;
				&lt;/ul&gt;
		 &lt;/div&gt;

		 &lt;!-- Menu --&gt;
		 &lt;div class=&rdquo;menu&rdquo;&gt;
				&lt;ul&gt;
					 &lt;li&gt;&lt;a href=&rdquo;#&rdquo;&gt;Prev&lt;/a&gt;&lt;/li&gt;
					 &lt;li&gt;&lt;a href=&rdquo;#&rdquo;&gt;Next&lt;/a&gt;&lt;/li&gt;
				&lt;/ul&gt;
		 &lt;/div&gt;
	&lt;/div&gt;

</pre>
<p>A continuaci&oacute;n, vamos a destacar una serie de consejos que deber&iacute;an de cumplir todos los SLIDERs.</p>
<h3>Programaci&oacute;n en jQuery</h3>
<p>Utlizando clases en lugar de IDs para referenciar a los SLIDERs podemos utilizar la siguiente t&eacute;cnica en jQuery para automatizar el comportamiento de todos ellos.</p>
<pre class="code">// Slider
$('.slider').each (function ())
{
	// Declaraci&oacute;n de variables
	var slider = this ;


	// C&oacute;digo del Slider
	// &hellip;
}
</pre>
<p>Esto nos permite dise&ntilde;ar el comportamiento b&aacute;sico de todos ellos sin tener que programarlos uno a uno.</p>
<h3>Utilizando el .animate de jQuery</h3>
<p>El m&eacute;todo de animaci&oacute;n m&aacute;s recomendado es animar el posicionamiento del elemento respecto al contenedor. (<em>la posici&oacute;n left o top, cuando sea un slider horizontal o vertical, respectivamente</em>).</p>
<p>L&oacute;gicamente, para esto, nuestro contenedor tiene que tener posicionamiento relativo y el listado posicionamiento absoluto.</p>
<pre class="code">.slider .contendor {
	 position: relative;
}

.slider .contenedor ul {
	position: absolute;
	top: 0;
	left: 0;

	/* 
	 * Valor muy alto para permitir almacenar todos los elementos 
	 * Este valor deber&iacute;a ser height para sliders verticales 
	 */
	width: 10000px;
}
</pre>
<blockquote style="background-color: #ccc; border: 1px solid #333; margin: 7px; font-style: italic;">Para m&aacute;s informaci&oacute;n sobre posicionamiento, consulte <a href="http://www.librosweb.es/css/capitulo5.html" target="_blank">este art&iacute;culo</a></blockquote>
<p>En el caso de sliders horizontales o verticales de tama&ntilde;o fijo, donde cada item tiene el mismo tama&ntilde;o, la forma m&aacute;s sencilla de animar es la siguiente:</p>
<ol>
<li> <strong>Sacar el n&uacute;mero de elementos en total</strong>
<pre class="code">			var numElementos = $(slider).find ('.contenedor ul li').size () ;
		</pre>
</li>
<li> <strong>Calcular la distancia entre dos elementos</strong><br /> El mejor m&eacute;todo para calcular esto es calcular la diferencia de posicionamiento entre el segundo elemento y el primero
<p>De esta forma, tenemos la distancia absoluta, sin tener que preocuparnos de m&aacute;rgenes, rellenos y la diferencia de c&oacute;mo se interpretan estos valores dependiendo del navegador.</p>
<pre class="code">			var distancia = 
				$(slider).find ('li:first-child + li').position().left - 
				$(slider).find ('li:first-child').position().left ;
		</pre>
<p><strong style="color: red;">&iexcl;Atenci&oacute;n!</strong> Si nos fijamos bien, es posible que el c&oacute;digo anterior nos de un  			error en el caso de que haya menos de 2 elementos. Afortunadamente, en este caso, la l&oacute;gica nos indica que un  			SLIDER no tiene ninguna funci&oacute;n en este caso, por lo que lo m&aacute;s l&oacute;gico es desactivarlo antes.</p>
<pre class="code">			// Slider
			$('.slider').each (function ())
			{
				// Declaraci&oacute;n de variables
				var slider = this ;
				var numElementos = 
				$(slider).find ('.contenedor ul li').size () ;


				// &iquest;Es necesario un Slider?
				if (numElementos &lt; 2)
				{
					return ;
				}


				// C&oacute;digo del slider
				// ...
			}
		</pre>
</li>
<li> <strong>Calcular el n&uacute;mero de elementos visibles. </strong><br /> Que se puede calcular dividiendo el ancho (o alto) del contenedor entre la distancia entre los elementos. </li>
<li> <strong>Inicializar el paginador a 1</strong> </li>
</ol>
<p>Cada vez que el usuario pulse sobre los botones de anterior y siguiente, entonces se calcula la posici&oacute;n left multiplicando la p&aacute;gina actual por el ancho. Adem&aacute;s, hay que actualizar el paginador aument&aacute;ndolo o disminuy&eacute;ndolo en una unidad seg&uacute;n avancemos o retrodedamos.</p>
<p>Un ejemplo de la animaci&oacute;n del listado de elementos es el siguiente:</p>
<pre class="code">// &hellip;

// Siguiente
$(this).find ('.next').click (function (e)
{
	// Evitamos el comportamiento del enlace
	e.preventDefault () ;
				

// Si hay m&aacute;s elementos a la derecha
	if (page &lt; (numItems - numItemsVisible))
	{
		page++;
		$(slider).find ('ul').stop().animate ({left:"-" + (myWidth * (page - 1) + 'px')}, velocity) ;	
	}
}) ;
			
			
// Anterior
$(this).find ('.prev').click (function (e)
{
	// Evitamos el comportamiento del enlace
	e.preventDefault () ;
				
		
	// S&oacute;lo si hay elementos a la izquierda
	if (page &gt; 1)
	{
		page--;
		$(slider).find ('ul').stop().animate ({left: "-" + (myWidth * (page - 1) + 'px')}, velocity) ;	
	}
}) ;	

// &hellip;
</pre>
<p>Otra cosa importante a tener en cuanta cuando realizamos la animaci&oacute;n es la siguiente. Como estamos indicando la nueva posici&oacute;n del elemento de forma absoluta podemos realizar lo siguiente:</p>
<pre class="code">	$(slider).find ('ul').stop().animate ({ &hellip; }) ;
</pre>
<p>Con <strong>STOP</strong> estamos indicando que cualquier animaci&oacute;n que hubiera previamente debe detenerse y s&oacute;lo hacer caso a la nueva, de forma que no se van quedando las animaciones en cola y s&oacute;lo tiene valor la &uacute;ltima que ha pulsado el usuario.</p>
<h3>Desactivar el men&uacute; si no hay elementos suficientes para realizar la animaci&oacute;n</h3>
<p>Una buena pr&aacute;ctica es desactivar el men&uacute; de navegaci&oacute;n cuando el n&uacute;mero de elementos totales es inferior o igual al n&uacute;mero de elementos visibles.</p>
<pre class="code">if (numElementos &lt;= numVisible)
{
	$(slider).find (".menu").hide () ;
}
</pre>
<h3>Comportamiento autom&aacute;tico</h3>
<p>Con el plugin de <a href="http://jquery.offput.ca/every/" target="_blank">timer.js</a> es posible hacer que el slider avance  	autom&aacute;ticamente Utilizando adem&aacute;s atributos &ldquo;data-&rdquo; de HTML podemos especificar atributos al Slider para que se  	desactive este comportamiento autom&aacute;tico una vez que el usuario realiza una acci&oacute;n manual sobre el Slider.</p>
<p>Por ejemplo&hellip; podemos a&ntilde;adir un atributo al comenzar cada Slider</p>
<pre class="code">$('.slider').each (function ())
{
	// Vars
	var slider = this ;

	// Definir la acci&oacute;n del men&uacute;
	$(slider).attr ('data-automatic', 1); 


	// Comportamiento autom&aacute;tico
	$(slider).everyTime (5000, function() 
	{
		// &iquest;Est&aacute; activado el comportamiento autom&aacute;tico?
		if ($(slider).attr ('data-automatic') == '1')
		{
			// C&oacute;digo de animaci&oacute;n
		}
 	}
 
	// En las acciones del men&uacute; lo desactivamos
	$(slider).find ('menu a').click (function (e)
	{
		$(slider).attr ('data-automatic', 0); 
	}) ;
}
</pre>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=88</wfw:commentRss>
			<slash:comments>3</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/programando-un-pasador-o-slider-con-jquery-y-css.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Diferencias entre JOIN, LEFT JOIN y RIGHT JOIN</title>
			<link>http://www.imaginanet.com/blog/diferencias-entre-join-left-join-y-right-join.html</link>
			<guid>http://www.imaginanet.com/blog/diferencias-entre-join-left-join-y-right-join.html</guid>
			<comments>http://www.imaginanet.com/blog/diferencias-entre-join-left-join-y-right-join.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Thu,  1 Dec 2011 01:56:08 +0100</pubDate>
					<category><![CDATA[MySQL]]></category>
					<description><![CDATA[Suele ser muy com&uacute;n confundirse con las distintas combinaciones que se pueden realizar entre tablas, por ello vamos a aclarar las diferencias entre cada una.
Existen las combinaciones internas de tablas donde cada registro de la tabla A se combina con otro de la tabla B que cumpla las condiciones.Ej: Obtener los empleados...]]></description>
			<content:encoded><![CDATA[><p>Suele ser muy com&uacute;n confundirse con las distintas combinaciones que se pueden realizar entre tablas, por ello vamos a aclarar las diferencias entre cada una.</p>
<p>Existen las <strong>combinaciones internas</strong> de tablas donde cada registro de la tabla A se combina con otro de la tabla B que cumpla las condiciones.<br /><em>Ej: Obtener los empleados del departamento de recursos humanos:</em></p>
<pre class="code">select * from empleados a, departamentos b where a.id_departamento=b.id</pre>
<p>Esta consulta anterior se podr&iacute;a haber expresado de forma explic&iacute;ta as&iacute;:</p>
<pre class="code">select * from empleados a inner join departamentos b on a.id_departamento=b.id</pre>
<p>Este tipo de combinaciones de tabas suele ser la m&aacute;s utilizada, pero si por ejemplo queremos un listado de todos los empleados, que tengan o no departamento asignado, entonces debemos realizar lo que se llama una <strong>combinaci&oacute;n externa</strong>.<br /><em>Ej: Obtener todos los empleados tengan o no departamento asignado:</em></p>
<pre class="code">select * from empleados a left join departamentos b on a.id_departamento=b.id</pre>
<p>De esta forma se realizada un outer join por la izquierda, es decir nos traemos todos los registros de la tabla izquierda tengan o no correspondencia con la tabla derecha. Por el lado contrario un right join hace lo mismo pero trayendo todos los registros de la tabla derecha tengan o no correspondencia con la de la izquierda. Aquellos registros sin correspondencia entren para el campo correspondiente un valor NULL, es decir si un empleado no tiene departamento, entonces su valor es null.</p>
<p>Los ejemplos que hemos visto hasta ahora se pueden aplicar en MySQL y otros compatibles, pero en Oracle para realizar los outer join se realizan as&iacute;:</p>
<pre class="code">select * from empleados a, departamentos b where a.id_departamento(+)=b.id</pre>
<p>Es decir se coloca el (+) en el lado que queramos (left o right).</p>
<p>En los left o right join se puede ademas aplicar otras condiciones.<br />Ej: Obtener los empleados de los departamentos que tengan hipoteca:</p>
<pre class="code">select * from empleados a left join departamentos b on a.id_departamento=b.id where a.hipoteca=1</pre>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=87</wfw:commentRss>
			<slash:comments>14</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/diferencias-entre-join-left-join-y-right-join.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Crear certificados digitales con OpenSSL</title>
			<link>http://www.imaginanet.com/blog/crear-certificados-digitales-con-openssl.html</link>
			<guid>http://www.imaginanet.com/blog/crear-certificados-digitales-con-openssl.html</guid>
			<comments>http://www.imaginanet.com/blog/crear-certificados-digitales-con-openssl.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed, 30 Nov 2011 18:23:05 +0100</pubDate>
					<category><![CDATA[Servidores y Seguridad]]></category>
					<category><![CDATA[Java]]></category>
					<category><![CDATA[PHP]]></category>
					<description><![CDATA[Cuando queremos programar o usar alguna aplicaci&oacute;n que requiera autenticaci&oacute;n y encriptaci&oacute;n podemos hacer uso de certificados digitales. Para obtenerlo podemos hacer uso de un certificado obtenido mediante VeriSign, DNI electr&oacute;nico o crear nosotros uno mismo.
En esta entrada de blog vamos a hacer esta...]]></description>
			<content:encoded><![CDATA[><p>Cuando queremos programar o usar alguna aplicaci&oacute;n que requiera autenticaci&oacute;n y encriptaci&oacute;n podemos hacer uso de certificados digitales. Para obtenerlo podemos hacer uso de un certificado obtenido mediante VeriSign, DNI electr&oacute;nico o crear nosotros uno mismo.</p>
<p>En esta entrada de blog vamos a hacer esta &uacute;ltima opci&oacute;n, que aunque  no  podr&aacute; ser verificado por ninguna Autoridad Certificadora (CA), nos   servir&aacute; perfectamente mientras realizamos el desarrollo.</p>
<p>Antes de empezar, vamos a suponer que tenemos claros los conceptos del certificado digital, tales como:</p>
<ul>
<li><a title="Criptograf&iacute;a asim&eacute;trica" href="http://es.wikipedia.org/wiki/Criptograf%C3%ADa_asim%C3%A9trica" target="_blank">Concepto de clave p&uacute;blica privada </a></li>
<li><a title="Certificado digital" href="http://es.wikipedia.org/wiki/Certificado_digital" target="_blank">Certificado digital</a></li>
<li><a title="Autoridad certificadora" href="http://es.wikipedia.org/wiki/Autoridad_de_certificaci%C3%B3n">Autoridad certificadora</a></li>
</ul>
<p>Tambi&eacute;n ser&aacute; necesario tener claro algunos conceptos muy b&aacute;sicos de Linux como moverse por archivos, permisos, edici&oacute;n, etc.</p>
<ul>
</ul>
<h3>Instalar OpenSSL</h3>
<p>Para empezar, necesitaremos OpenSSL instalado a ser posible la  versi&oacute;n m&aacute;s actualizada posible, ya que si no, puede ser que alguno de  los pasos no funcione correctamente.</p>
<p>En Windows lo descargaremos y descomprimiremos y en Linux para Ubuntu/Debian:</p>
<pre class="code">sudo apt-get install openssl</pre>
<p>o para RedHat / CentOS:</p>
<pre class="code">yum install openssl</pre>
<p>lo tendremos instalado.</p>
<h3>Crear autoridad certificadora de certificados X.509</h3>
<p>Prepararemos el entorno:</p>
<pre class="code">cd $HOME
mkdir CA
cd CA
mkdir certificados
mkdir privado
echo '01' &gt; contador
touch certindex</pre>
<p>Ahora generaremos el archivo de configuraci&oacute;n OpenSSL</p>
<pre class="code">nano openssl.cnf
</pre>
<p>El contenido deber&iacute;a ser algo as&iacute;:</p>
<pre class="code"># -----------------------
# Configuraci&oacute;n inicial
# -----------------------

dir           = .    # Directorio de trabajo

[ ca ]
default_ca    = CA_default

[ CA_default ]
serial        = $dir/contador          # Contador de n&uacute;meros de serie
database      = $dir/certindex         # Listado de certificados
new_certs_dir = $dir/certificados      # Directorio para los certificados generados
certificate   = $dir/cacert.pem        # Certificado ra&iacute;z
private_key   = $dir/privado/cakey.pem # Clave privada del certificado ra&iacute;z
default_md    = sha1                   # Digest usado
preserve      = no                     # Preserva el orden de los campos del DN
nameopt       = default_ca             # Muestra detalles del certificado
certopt       = default_ca             # Muestra detalles del certificado
policy        = policy_match           # Indica si los campos obligatorios  y/o
                                       # opcionales deben ser iguales al 
                                       # certificado ra&iacute;z

# Pol&iacute;tica de recolecci&oacute;n de datos frente al ra&iacute;z
[ policy_match ]
countryName                 = match        
stateOrProvinceName         = match          
organizationName            = match
organizationalUnitName      = optional      
commonName                  = supplied     
emailAddress                = optional

# Configuraci&oacute;n de certificados
[ req ]
default_bits       = 2048           # Tama&ntilde;o de la clave en bits
default_keyfile    = key.pem        # Fichero de la clave privada
default_md         = sha1           # Digest
string_mask        = nombstr        # Caracteres permitidos en la clave
distinguished_name = req_distinguished_name  # Secci&oacute;n para el nombre DN
req_extensions     = v3_req         # Secci&oacute;n con mas extensiones que se 
                                    # a&ntilde;aden a la petici&oacute;n del 
                                    # certificado

# Distinguished Name. Datos p&uacute;blicos del certificado X.509 que identifican al propietario.
[ req_distinguished_name ]
0.organizationName          = Nombre de la organizaci&oacute;n
0.organizationName_default  = Imaginanet
organizationalUnitName      = Departamento
emailAddress                = Correo electr&oacute;nico
emailAddress_max            = 40
localityName                = Ciudad
stateOrProvinceName         = Estado o provincia
countryName                 = C&oacute;digo ISO del pais (dos letras)
countryName_default         = ES
countryName_min             = 2
countryName_max             = 2
commonName                  = Nombre com&uacute;n (nombre del host o IP)
commonName_max              = 64

# Si se indica la opcion -x509 indica que se trata de un certificado CA ra&iacute;z
# con autoridad para firmar o revocar otros certificados
[ v3_ca ]
basicConstraints       = CA:TRUE  
                                 
subjectKeyIdentifier   = hash     
authorityKeyIdentifier = keyid:always,issuer:always  

[ v3_req ]
basicConstraints            = CA:FALSE
subjectKeyIdentifier        = hash 
</pre>
<br />Finalmente ejecutamos<br />
<pre class="code">openssl req -new -x509 -extensions v3_ca -keyout privado/cakey.pem  -out cacert.pem -days 3650 -config ./openssl.cnf
</pre>
<h3>Creando un certificado digital X.509 en base a nuestra autoridad certificadora</h3>
<pre class="code">openssl req -new -nodes -out imaginanet-cert.pem -config ./openssl.cnf

openssl ca -out certificado-imaginanet.pem -config ./openssl.cnf -days 3650  -infiles imaginanet-cert.pem
</pre>
<p>Donde el archivo <em>imaginanet-cert.pem</em> corresponde a nuestra clave privada y <em>certificado-imaginanet.pem</em> a la p&uacute;blica.</p>
<h3>Utilidades</h3>
<p>No debemos olvidar que los certificados generados no ser&aacute;n validos en un entorno real de producci&oacute;n ya que nuestra CA no ser&aacute; reconocida por los navegadores o el KeyStore de Java, pero si que nos vendr&aacute; bien como entorno de desarrollo para:</p>
<ul>
<li>Poner un servidor web en modo seguro HTTPS</li>
<li>Realizar firmas sobre ficheros o correos mediante cualquier lenguaje de programaci&oacute;n</li>
</ul>
<h3>A&ntilde;adiendo la autoridad certificadora y nuestro certificado digital a nuestro navegador: Firefox</h3>
<p>Supongamos que hemos puesto en marcha nuestro servidor web Apache con HTTPS y el certificado digital creado. Para que el navegador nos confirme que es una p&aacute;gina v&aacute;lida deberemos <span style="text-decoration: underline;">a&ntilde;adir la autoridad certificadora</span> a la lista de autoridades certificadoras v&aacute;lidas. En el caso de Firefox:</p>
<p><em>Editar -&gt; Preferencias -&gt; Avanzado -&gt; Cifrado -&gt; Ver certificados -&gt; Autoridades -&gt; Importar</em></p>
<p>y seleccionaremos el archivo <em>cacert.pem</em></p>
<p>Si por el contrario quisi&eacute;ramos firmar digitalmente con el certificado creado, deberemos <span style="text-decoration: underline;">a&ntilde;adir el certificado digital</span> yendo a:</p>
<p><em>Editar -&gt; Preferencias -&gt; Avanzado -&gt; Cifrado -&gt; Ver certificados -&gt; Sus certificados -&gt; Importar</em></p>
<p>y seleccionar la clave privada <em>imaginanet-cert.pem</em> e introducir la contrase&ntilde;a para ser guardada en el KeyStore de Firefox.<em></em></p>
<p>Todo documento firmado con este certificado ser&aacute; no v&aacute;lido ya que el servidor que lo firme no reconocer&aacute; a la autoridad certificadora, pero podemos a&ntilde;adir dicho certificado al KeyStore del lado del servidor, cosa que veremos en pr&oacute;ximas entradas del blog.<em><br /></em></p>
<ul>
</ul>
<h3>Convertir certificados .pem / .cert (X.509) a .pfx (PKCS12)</h3>
<p>En ocasiones es necesario el uso de certificados en formato PKCS12 de extensi&oacute;n PFX, como por ejemplo para la librer&iacute;a <a title="Librer&iacute;a PDF para Java / C#" href="http://itextpdf.com/" target="_blank">iText</a> para Java / C#. Lo podemos hacer mediante el siguiente comando con OpenSSL 0.9.8k (si tenemos una versi&oacute;n inferior deberemos actualizar ya que no funciona en todas las aplicaciones el fichero generado):</p>
<pre class="code">openssl pkcs12 -inkey private_key.pem -in public_cert.cert -export -out cert.pfx
</pre>
<h3>Referencias</h3>
<p>Parte de este art&iacute;culo se ha basado en <a href="http://www.linuxtotal.com.mx/ssl_apache.html" target="_blank">http://www.linuxtotal.com.mx/ssl_apache.html</a></p>
<p>M&aacute;s informaci&oacute;n:</p>
<ul>
<li><a title="X.509" href="http://es.wikipedia.org/wiki/X.509">X.509</a></li>
<li><a title="PKCS" href="http://en.wikipedia.org/wiki/PKCS">PKCS7</a></li>
<li><a title="PKCS12" href="http://en.wikipedia.org/wiki/PKCS12">PKCS12</a></li>
<li><a href="http://www.imaginanet.com/blog/anadir-la-autoridad-de-validacion-fnmt-para-el-dni-electronico-al-keystore-de-java.html">A&ntilde;adir un certificado al KeyStore de Java</a></li>
<li><a href="http://www.imaginanet.com/blog/firmar-y-verificar-firma-digital-en-pdfs-mediante-java-con-itext.html">Firmar y validar firmas digitales en documentos PDF en Java</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=86</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/crear-certificados-digitales-con-openssl.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Centrar verticalmente contenidos con CSS</title>
			<link>http://www.imaginanet.com/blog/centrar-verticalmente-contenidos-con-css.html</link>
			<guid>http://www.imaginanet.com/blog/centrar-verticalmente-contenidos-con-css.html</guid>
			<comments>http://www.imaginanet.com/blog/centrar-verticalmente-contenidos-con-css.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon,  1 Aug 2011 09:11:30 +0100</pubDate>
					<category><![CDATA[XHTML]]></category>
					<category><![CDATA[CSS]]></category>
					<description><![CDATA[A veces no resulta tan trivial conseguir que nuestros contenidos se centren verticalmente, es por ello que vamos a explicar como llevar dicha a cabo dicha tarea de una forma sencilla.  Antes de nada repasemos como funciona el centrado de contenidos horizontalmente: Al elemento contenedor le ponemos la propiedad...]]></description>
			<content:encoded><![CDATA[>A veces no resulta tan trivial conseguir que nuestros contenidos se centren verticalmente, es por ello que vamos a explicar como llevar dicha a cabo dicha tarea de una forma sencilla.<br /> <br /> Antes de nada repasemos como funciona el <em>centrado de contenidos horizontalmente</em>:<br /> Al elemento contenedor le ponemos la propiedad &ldquo;text-align&rdquo; con valor &ldquo;center&rdquo; y los elementos interiores se centran. Ahora bien este centrado solo funciona con elementos inline, si lo que queremos es centrar bloques, entonces debemos utilizar la propiedad &ldquo;margin&rdquo; con valores &ldquo;0 auto&rdquo; en los elementos interiores, es decir no en el elemento contenedor como en el caso anterior. De esta forma conseguimos el centrado horizontal para elementos con &ldquo;display&rdquo; con valor &ldquo;block&rdquo;.<br /> <br /> En el caso del <em>centrado vertical</em> no nos vale la propiedad margin con valores auto como en el caso horizontal. Por ejemplo si lo que queremos es centrar un texto dentro de un elemento contenedor que tiene altura 20px, entonces una solucion sencilla es indicar que dicho texto tiene una altura de linea de 20px. Es decir poner la propiedad &ldquo;line-height&rdquo; con valor &ldquo;20px&rdquo;.<br /> <br /> Ahora bien imaginemos que queremos centrar verticalmente una foto dentro de un elemento contenedor, como puede ser una etiqueta &ldquo;div&rdquo;. La foto tiene 100px de altura, y el contenedor 300px. Bien para lograr que la foto se centre verticalmente, debemos a&ntilde;adir un elemento dentro de la capa contenedora. Dicho elemento va a tener una altura de 300px (la misma que la capa contenedora), una anchura de 1px, un margen derecho de -1px, un display de bloque en l&iacute;nea, y una alineaci&oacute;n vertical media. A su vez la imagen va a tener una alineaci&oacute;n vertical media.<br /><br />
<pre class="code"><div style="background: cyan; height: 400px;">
&lt; span style=" display: inline-block; margin-right: -1px; vertical-align: middle; height:
400px; width: 1px; "&gt;&lt; /span&gt;<img alt="" />
</div>
</pre>
Como conclusi&oacute;n decir, que para centrar verticalmente necesitamos tener dos elementos dentro de la capa contenedora, para que se centren uno respecto del otro.]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=85</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/centrar-verticalmente-contenidos-con-css.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Bases de datos NOSQL y PHP</title>
			<link>http://www.imaginanet.com/blog/bases-de-datos-nosql-y-php.html</link>
			<guid>http://www.imaginanet.com/blog/bases-de-datos-nosql-y-php.html</guid>
			<comments>http://www.imaginanet.com/blog/bases-de-datos-nosql-y-php.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Sat, 30 Jul 2011 23:10:20 +0100</pubDate>
					<category><![CDATA[PHP]]></category>
					<category><![CDATA[Internet]]></category>
					<category><![CDATA[Redes Sociales]]></category>
					<category><![CDATA[Web 2.0]]></category>
					<description><![CDATA[El t&eacute;rmino NOSQL aplicado a bases de datos no se refiere a que no se utilice el lenguaje sql, si no que significa "not only sql". Estas bases de datos son no relacionales y no proporcionan garant&iacute;as ACID, tampoco suelen tener esquemas fijos de tablas ni sentencias join. El t&eacute;rmino ACID hace referencia a un...]]></description>
			<content:encoded><![CDATA[><p>El t&eacute;rmino NOSQL aplicado a bases de datos no se refiere a que no se utilice el lenguaje sql, si no que significa "not only sql". Estas bases de datos son no relacionales y no proporcionan garant&iacute;as ACID, tampoco suelen tener esquemas fijos de tablas ni sentencias join. El t&eacute;rmino ACID hace referencia a un conjunto de caracter&iacute;sticas requeridas para que una serie de instrucciones puedan ser consideradas como una transacci&oacute;n.</p>
<p>Estas bases de datos tienen la ventaja de su rapidez y escalabilidad horizontal y los inconvenientes de que no garantizan las transacciones. Dependiendo del tipo de proyecto, puede que se adapte mejor una base de datos de este tipo o una relacional, todo depende de las necesidades del proyecto.</p>
<p>En PHP nos encontramos con distintos productos que utilizan esta tecnolog&iacute;a, las m&aacute;s conocidas son de tipo documental y de tipo clave-valor. Bases de datos documentales tenemos por ejemplo CouchDB y MongoDB, en cuando a bases de datos de tipo clave-valor quiz&aacute;s la m&aacute;s conocida sea Cassandra, creada por y para Facebook. Todas estos ejemplos son de c&oacute;digo abierto.</p>
<p>En este art&iacute;culo nos centraremos en MongoDB, una bases de datos de tipo documental en la que los datos se guardan en disco en formato BSON (JSON binario). Es muy sencillo trabajar con ella, al no tener que definir esquemas fijos, la l&oacute;gica del modelo es la que establece como se guardan los datos. En una misma tabla podemos tener datos con distintos formatos, lo que demuestra la potencia de esta tecnolog&iacute;a. Otra de sus virtudes es la facilidad con la que se puede escalar sin apenas configurar nada, simplemente a&ntilde;adiendo nodos nuevos. Si se prev&eacute; que una aplicaci&oacute;n vaya a ser usada por multitud de usuarios a la vez y las transacciones no sean un problema, seguramente esta sea la soluci&oacute;n adecuada.</p>
<p>Veamos un ejemplo de utilizaci&oacute;n del driver de mongodb para php, con las operaciones b&aacute;sicas.</p>
<pre class="code php">	$m = new Mongo(); // connect
	$db = $m-&gt;selectDB("example");
	$collection = $db-&gt;users;

	// A&ntilde;adir un registro
	$obj = array( "username" =&gt; "Pedro", "password" =&gt; md5("mipassword") );
	$collection-&gt;insert($obj);


	// A&ntilde;adir otro registro con un esquema diferente
	$obj = array( "username" =&gt; "Juan", "password" =&gt; md5("otropassword"), "year" =&gt; "1960" );
	$collection-&gt;insert($obj);

	// Buscar todos los elementos de la coleccion
	$cursor = $collection-&gt;find();

	// Iterar a trav&eacute;s de los resultados
	foreach ($cursor as $obj) {
		echo $obj["username"] . "\n";
	}

	// Buscar el usuario con nombre Juan
	$user = $collection-&gt;findOne(array('username' =&gt; 'Juan')));

	// Buscar usuarios con el campo a&ntilde;o  &gt; 1950
	$users = $collection-&gt;find(array('year' =&gt; array( '$gt' =&gt; 1950)));


	// Usar javascript para reducir un resultado, conseguiremos los usuarios que se llamen juan o que su a&ntilde;o sea &lt; 1950
	$js = "function() {
		return this.username == 'Juan' || this.year &lt; 1950;
	}";
	$users = $collection-&gt;find(array('$where' =&gt; $js));

</pre>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=84</wfw:commentRss>
			<slash:comments>1</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/bases-de-datos-nosql-y-php.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Crear thumbnails (miniaturas) con php al vuelo.</title>
			<link>http://www.imaginanet.com/blog/crear-thumbnails-miniaturas-con-php-al-vuelo.html</link>
			<guid>http://www.imaginanet.com/blog/crear-thumbnails-miniaturas-con-php-al-vuelo.html</guid>
			<comments>http://www.imaginanet.com/blog/crear-thumbnails-miniaturas-con-php-al-vuelo.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 11 Jul 2011 21:45:36 +0100</pubDate>
					<category><![CDATA[PHP]]></category>
					<category><![CDATA[XHTML]]></category>
					<description><![CDATA[Para reducir el ancho de banda en nuestro servidor, a costa de cargar la cpu un poco más, podemos redimensionar las imágenes que estamos sirviendo con un sencillo script de PHP. Vamos a ver dos métodos, uno con la librería gd y otro llamando a imagemagick.
Librería GD:
Usaremos un archivo php para hacer la carga de las...]]></description>
			<content:encoded><![CDATA[><p>Para reducir el ancho de banda en nuestro servidor, a costa de cargar la cpu un poco más, podemos redimensionar las imágenes que estamos sirviendo con un sencillo script de PHP. Vamos a ver dos métodos, uno con la librería gd y otro llamando a imagemagick.</p>
<h2>Librería GD:</h2>
<p>Usaremos un archivo php para hacer la carga de las imágenes, lo llamaremos thumb.php y lo colocaremos en la raíz de nuestra web. Lo llamaremos de la siguiente forma:</p>
<pre class="code php">
        &lt;img src="/thumb.php?file=/public/image1.png&amp;width=100" alt="miniatura" /&gt;
</pre>
<p>Le pasamos 2 parámetros al script:</p>
<p><strong>file</strong>: la ruta a la imagen que queremos redimensionar.</p>
<p><strong>width</strong>: la nueva anchura.</p>
<p>Lo primero que tenemos que hacer el calcular las nuevas dimensiones de la imagen, en nuestro ejemplo estamos marcando la anchura, y la altura se calcula a partir de ésta. Cuando ya tenemos las nuevas dimensiones vemos en qué formato está y luego escribimos las cabeceras correspondientes y la mostramos. El código del archivo thumb.php sería el siguiente:</p>
<pre class="code php">
        $file = $_GET["file"];
        $width = $_GET["width"];

        // Ponemos el . antes del nombre del archivo porque estamos considerando que la ruta está a partir del archivo thumb.php
        $file_info = getimagesize("." . $file);
        // Obtenemos la relación de aspecto
        $ratio = $file_info[0] / $file_info[1];

        // Calculamos las nuevas dimensiones
        $newwidth = $width;
        $newheight = round($newwidth / $ratio);
        
        // Sacamos la extensión del archivo
        $ext = explode(".", $file);
        $ext = strtolower($ext[count($ext) - 1]);
        if ($ext == "jpeg") $ext = "jpg";

        // Dependiendo de la extensión llamamos a distintas funciones
        switch ($ext) {
                case "jpg":
                        $img = imagecreatefromjpeg("." . $file);
                break;
                case "png":
                        $img = imagecreatefrompng("." . $file);
                break;
                case "gif":
                        $img = imagecreatefromgif("." . $file);
                break;
        }
        // Creamos la miniatura
        $thumb = imagecreatetruecolor($newwidth, $newheight);
        // La redimensionamos
        imagecopyresampled($thumb, $img, 0, 0, 0, 0, $newwidth, $newheight, $file_info[0], $file_info[1]);
        // La mostramos como jpg
        header("Content-type: image/jpeg");
        imagejpeg($thumb, null, 80);
</pre>
<br />
<h2>Imagemagick</h2>
<p>Si usamos imagemagick tenemos las ventajas de ahorrar consumo de memoria y los inconvenientes de que tenemos que tenerlo instalado en nuestro servidor. En caso de tenerlo disponible, el script resultante sería muy parecido al anterior</p>
<pre class="code php">
        $file = $_GET["file"];
        $width = $_GET["width"];

        // Ponemos el . antes del nombre del archivo porque estamos considerando que la ruta está a partir del archivo thumb.php
        $file_info = getimagesize("." . $file);
        // Obtenemos la relación de aspecto
        $ratio = $file_info[0] / $file_info[1];

        // Calculamos las nuevas dimensiones
        $newwidth = $width;
        $newheight = round($newwidth / $ratio);

        // No necesitamos sacar la extensión ya que el comando convert ya detecta el formato
        header("Content-type: image/jpeg");
        passthru("convert -scale ".($newwidth)."x".($newheight)."! "./".$file."" JPG:-");
</pre>
<br /><br />]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=83</wfw:commentRss>
			<slash:comments>6</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/crear-thumbnails-miniaturas-con-php-al-vuelo.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Cambio de divisas mediante el Banco Central Europeo</title>
			<link>http://www.imaginanet.com/blog/cambio-de-divisas-mediante-el-banco-central-europeo.html</link>
			<guid>http://www.imaginanet.com/blog/cambio-de-divisas-mediante-el-banco-central-europeo.html</guid>
			<comments>http://www.imaginanet.com/blog/cambio-de-divisas-mediante-el-banco-central-europeo.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 11 Jul 2011 11:15:45 +0100</pubDate>
					<category><![CDATA[Comercio electrónico]]></category>
					<category><![CDATA[PHP]]></category>
					<description><![CDATA[Si hacemos uso de distintas monedas en nuestra p&aacute;gina web para mostrar precios orientativos, necesitaremos mantener actualizado el cambio de moneda por la fluctuaci&oacute;n diaria entre euros, d&oacute;lares, yenes, etc.
El Banco Central Europeo genera un archivo XML que es actualizado a diario. Este XML lo podemos...]]></description>
			<content:encoded><![CDATA[><p>Si hacemos uso de distintas monedas en nuestra p&aacute;gina web para mostrar precios orientativos, necesitaremos mantener actualizado el cambio de moneda por la fluctuaci&oacute;n diaria entre euros, d&oacute;lares, yenes, etc.</p>
<p>El Banco Central Europeo genera un archivo XML que es actualizado a diario. Este XML lo podemos procesar y actualizar nosotros para guardarlo en un archivo de configuraci&oacute;n o base de datos mediante SimpleXML y una tarea programada / cron.</p>
<p>El c&oacute;digo PHP haciendo uso de SimpleXML ser&iacute;a el siguiente:</p>
<pre class="code php">$xml = simplexml_load_file("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml");
foreach ($xml-&gt;Cube-&gt;Cube-&gt;Cube as $c) {
	$attr = $c-&gt;attributes();
	echo "Un euro equivale a ".$attr[1]." ".$attr[0]."<br />";
}
</pre>
<p>Donde la variable $attr[0] equivale el c&oacute;digo ISO de la moneda y $attr[1] equivale al valor de un euro en dicha moneda.<br /><br />A partir de aqu&iacute;, deberemos procesar el valor de la moneda como nos interese.</p>
<p><strong>M&aacute;s informaci&oacute;n:</strong></p>
<ul>
<li><a title="Cambio de divisas" href="http://www.ecb.int/stats/exchange/eurofxref/html/index.en.html" target="_blank">Informaci&oacute;n para desarrolladores del Banco Central Europeo</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=82</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/cambio-de-divisas-mediante-el-banco-central-europeo.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Redireccionar dominios con .htaccess</title>
			<link>http://www.imaginanet.com/blog/redireccionar-dominios-con-htaccess.html</link>
			<guid>http://www.imaginanet.com/blog/redireccionar-dominios-con-htaccess.html</guid>
			<comments>http://www.imaginanet.com/blog/redireccionar-dominios-con-htaccess.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon,  4 Jul 2011 12:23:24 +0100</pubDate>
					<category><![CDATA[SEO]]></category>
					<category><![CDATA[Buscadores]]></category>
					<description><![CDATA[Suele ser com&uacute;n que una web tenga varios dominios apuntando a ella, como .es, .com, .net, etc. y que solo nos interese mostrar siempre el mismo dominio, independientemente del que teclee el usuario, por ejemplo el .com (o cualquier otro), o que a su vez google solo indexe direcciones del dominio elegido.  Suponemos que...]]></description>
			<content:encoded><![CDATA[>Suele ser com&uacute;n que una web tenga varios dominios apuntando a ella, como .es, .com, .net, etc. y que solo nos interese mostrar siempre el mismo dominio, independientemente del que teclee el usuario, por ejemplo el .com (o cualquier otro), o que a su vez google solo indexe direcciones del dominio elegido.<br /> <br /> Suponemos que nuestra web se encuentra alojada en un servidor con apache y con el mod-rewrite activo, y que por tanto podemos editar el fichero .htaccess que se encuentra en la ra&iacute;z de nuestra web.<br /> <br /> Lo primero es a&ntilde;adir la siguiente l&iacute;nea a nuestro .htaccess, para activar el motor de reescritura de direcciones:<br />
<pre class="code">RewriteEngine On
</pre>
Ahora vamos a ir explicando cada caso particular con ejemplos, donde nuestro dominio principal sera &ldquo;midominio.com&rdquo;. Por ejemplo si lo que queremos es que cualquier persona que teclee nuestro dominio sin la triple w (como midominio.com), le aparezca autom&aacute;ticamente la direcci&oacute;n con las tres w (www.midominio.com), debemos hacer lo siguiente:<br />
<pre class="code">RewriteCond %{HTTP_HOST} ^midominio.com$ [NC]
RewriteRule ^(.*)$ http://www.midominio.com/ [R=301,L]
</pre>
De esta forma indicamos una condici&oacute;n con la sentencia RewriteCond, para que cuando el dominio recibido, indicado por la variable de servidor HTTP_HOST, se corresponda con midominio.com, siendo la comprobaci&oacute;n insensitiva, es decir ignorando may&uacute;sculas o min&uacute;sculas, entonces se ejecute las reglas siguientes indicadas por sentencias RewriteRule. Es decir, cuando se cumple una condici&oacute;n se ejecutan todas las reglan que la preceden hasta encontrar una regla que lleve el flag L, el cu&aacute;l indica que es la &uacute;ltima regla. En nuestro caso solo necesitamos una regla, por ello le incluimos el flag L, y lo que hace dicha regla es cambiar la direcci&oacute;n recibida por http://www.midominio.com, con una redirecci&oacute;n de tipo 301.<br /> <br /> Optamos por una redirecci&oacute;n 301, puesto que es la forma m&aacute;s eficiente de indicar a los motores de busqueda que la ruta especificada ha sido movida de forma permanente. Sin que dicha redirecci&oacute;n afecte a los rankins de nuestra p&aacute;gina, por tanto se realiza de forma transparente.<br /> <br /> Ahora para lograr redireccionar cualquier dominio a nuestro dominio principal (en este caso el .com), hacemos lo siguiente (suponiendo que tenemos registrados el .es y .net tambi&eacute;n):<br />
<pre class="code">RewriteCond %{HTTP_HOST} ^www.midominio.es$ [NC]
RewriteRule ^(.*)$ http://www.midominio.com/ [R=301,L]
RewriteCond %{HTTP_HOST} ^midominio.es$ [NC]
RewriteRule ^(.*)$ http://www.midominio.com/ [R=301,L]

RewriteCond %{HTTP_HOST} ^www.midominio.net$ [NC]
RewriteRule ^(.*)$ http://www.midominio.com/ [R=301,L]
RewriteCond %{HTTP_HOST} ^midominio.net$ [NC]
RewriteRule ^(.*)$ http://www.midominio.com/ [R=301,L]
</pre>
Siendo las 4 primeras l&iacute;neas para el dominio .es, y las &uacute;ltimas 4 para el dominio .net. Las 2 primeras de la parte del dominio.es se encargan del dominio con la triple w, y las dos siguiente del dominio sin la triple w.<br /> <br /> Finalmente si lo que queremos es redireccionar una p&aacute;gina antigua a una nueva, lo que tenemos que hacer es:<br />
<pre class="code">redirect 301 /antiguo/antiguo.html http://www.midominio.com/nuevo.html
</pre>
De esta forma cuando se intente acceder a dicha p&aacute;gina antigua se redireccionar&aacute; autom&aacute;ticamente a la nueva p&aacute;gina, y sin afectar al ranking que tuviera para los buscadores.]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=81</wfw:commentRss>
			<slash:comments>4</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/redireccionar-dominios-con-htaccess.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Migrar dominios entre servidores mediante Plesk</title>
			<link>http://www.imaginanet.com/blog/migrar-dominios-entre-servidores-mediante-plesk.html</link>
			<guid>http://www.imaginanet.com/blog/migrar-dominios-entre-servidores-mediante-plesk.html</guid>
			<comments>http://www.imaginanet.com/blog/migrar-dominios-entre-servidores-mediante-plesk.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Fri, 17 Jun 2011 09:42:11 +0100</pubDate>
					<category><![CDATA[Servidores y Seguridad]]></category>
					<description><![CDATA[En ocasiones es necesario realizar un cambio de servidor para   nuestras webs. El gran problema es que el traspaso no s&oacute;lo implica mover   los archivos de la web, si no es mucho m&aacute;s: cuentas de correo con sus   emails, bases de datos, configuraci&oacute;n DNS, configuraci&oacute;n de la quota  del  dominio,...]]></description>
			<content:encoded><![CDATA[><p>En ocasiones es necesario realizar un cambio de servidor para   nuestras webs. El gran problema es que el traspaso no s&oacute;lo implica mover   los archivos de la web, si no es mucho m&aacute;s: cuentas de correo con sus   emails, bases de datos, configuraci&oacute;n DNS, configuraci&oacute;n de la quota  del  dominio, etc.</p>
<p>Mover los archivos mediante FTP y realizar una  importaci&oacute;n de la  base de datos es posible, pero cuando se tratan de  unos cuantos miles  de dominios, bases de datos y tener que crear de  nuevo las cuentas de  correo (y perder los correos guardados en el  servidor), resulta  realmente pesado e ineficiente.</p>
<h3>Administrador de migraciones de Plesk</h3>
<p>Si nuestro servidor tiene instalado el panel de control Plesk, el  proceso se simplifica de gran manera, ya que &eacute;l har&aacute; por nosotros toda  la transferencia de archivos y configuraci&oacute;n por nosotros de los  dominios entre los hosts que deseemos.</p>
<p>En primer lugar, pulsaremos sobre el bot&oacute;n "<strong>Administrador de migraciones</strong>" de la pantalla de inicio</p>
<p>&nbsp;</p>
<p><img title="Administrador de Migraciones" src="http://www.imaginanet.com/ftp/articulos_web/migraciones_plesk/1.png" alt="Administraci&oacute;n de migraciones de Plesk para transferir hosts entre servidores" width="144" height="40" /></p>
<p>&nbsp;</p>
<p>Entonces entraremos en la pantalla principal de las migraciones de Plesk, con las migraciones ya hechas, en proceso y su estado.</p>
<p>&nbsp;</p>
<p><img title="Pantalla principal de las migraciones de Plesk de nuestro servidor" src="http://www.imaginanet.com/ftp/articulos_web/migraciones_plesk/2.png" alt="Pantalla principal de migraciones de Plesk" width="593" height="302" /></p>
<p>&nbsp;</p>
<p>Pulsamos sobre "<strong>Iniciar Migraci&oacute;n nueva</strong>" para iniciar una nueva migraci&oacute;n que nos llevar&aacute; a la introducci&oacute;n de <strong>credenciales en el servidor origen</strong>: direcci&oacute;n IP y cuenta de administrador (root en servidores Linux y Administrador en servidores Windows).</p>
<p>&nbsp;</p>
<p><img title="Introducci&oacute;n de credenciales en el host origen" src="http://www.imaginanet.com/ftp/articulos_web/migraciones_plesk/31.png" alt="Credenciales en el servidor origen" width="482" height="141" /></p>
<p>&nbsp;</p>
<p>En esta pantalla es importante estar atentos&nbsp; a la parte inferior la  opci&oacute;n de transferir todos los dominios o s&oacute;lo los dominios  seleccionados.</p>
<p>&nbsp;</p>
<p><img title="Elegimos si queremos transferir todos o algunos dominios" src="http://www.imaginanet.com/ftp/articulos_web/migraciones_plesk/32.png" alt="Deberemos seleccionar si queremos transferir todos o s&oacute;lo los dominios seleccionados" width="653" height="116" /></p>
<p>&nbsp;</p>
<p>En este punto, Plesk conectar&aacute; con el servidor origen y en la opci&oacute;n  inferior podremos decidir sin transferir s&oacute;lo correo, archivos o todo.  En nuestro caso hemos seleccionado s&oacute;lo migrar algunos dominios.</p>
<p>&nbsp;</p>
<p><img title="Selecci&oacute;n de dominios" src="http://www.imaginanet.com/ftp/articulos_web/migraciones_plesk/4.png" alt="Seleccionamos los dominios a transferir" width="316" height="110" /></p>
<p>&nbsp;</p>
<p>En la &uacute;ltima pantalla de migraci&oacute;n, Plesk nos pregunta sobre qu&eacute;  hacer en caso de conflictos en la migraci&oacute;n. Por ejemplo puede ser que  si la configuraci&oacute;n del servidor s&oacute;lo permite una base de datos por  dominio y migramos un dominio que contiene dos, crear&aacute; un conflicto. La  mejor opci&oacute;n en este punto es <strong>mantener las opciones por defecto</strong>.</p>
<p>Finalmente la migraci&oacute;n se inicia y volvemos a la pantalla inicial  del asistente de migraciones, donde podemos ver una barra de progreso en  la migraci&oacute;n que acabamos de realizar. En funci&oacute;n de la velocidad y  peso de los archivos a transferir durar&aacute; m&aacute;s o menos.</p>
<p>Tras terminar, es posible que la migraci&oacute;n se haya completado con advertencias, aunque por lo general <em>no suelen ser importantes</em>.  Podemos ver el informe final de la migraci&oacute;n y liberar el espacio  ocupado por ella en el disco duro del servidor destino clickando sobre  ella.</p>
<p>&nbsp;</p>
<p><img title="Informe final de la migraci&oacute;n" src="http://www.imaginanet.com/ftp/articulos_web/migraciones_plesk/5.png" alt="Informe final de la migraci&oacute;n de Plesk" width="546" height="166" /></p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=80</wfw:commentRss>
			<slash:comments>3</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/migrar-dominios-entre-servidores-mediante-plesk.html</feedburner:origLink>
		</item>
				
		<item>
			<title>El patrón singleton con PHP</title>
			<link>http://www.imaginanet.com/blog/el-patron-singleton-con-php.html</link>
			<guid>http://www.imaginanet.com/blog/el-patron-singleton-con-php.html</guid>
			<comments>http://www.imaginanet.com/blog/el-patron-singleton-con-php.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue, 31 May 2011 21:08:30 +0100</pubDate>
					<category><![CDATA[PHP]]></category>
					<description><![CDATA[Algunas veces nos interesa tener controlada la creaci&oacute;n de objetos por  motivos como por ejemplo el ahorro de memoria. Una forma de hacer esto  es utilizando el patr&oacute;n de dise&ntilde;o "Singleton". Vamos a estudiar un  ejemplo en PHP para ver su utilidad, funcionamiento e implementaci&oacute;n.
Un claro ejemplo de la...]]></description>
			<content:encoded><![CDATA[><p>Algunas veces nos interesa tener controlada la creaci&oacute;n de objetos por  motivos como por ejemplo el ahorro de memoria. Una forma de hacer esto  es utilizando el patr&oacute;n de dise&ntilde;o "Singleton". Vamos a estudiar un  ejemplo en PHP para ver su utilidad, funcionamiento e implementaci&oacute;n.</p>
<p>Un claro ejemplo de la utilidad de este patr&oacute;n ser&iacute;a una clase para trabajar con bases de datos. Si cada vez que necesitemos conectarnos tenemos que crear una instancia del objeto, estar&iacute;amos aumentando el consumo de memoria de nuestra aplicaci&oacute;n de una manera innecesaria. Lo que normalmente suele hacer la gente es utilizar una variable global que ser&iacute;a una instancia de ese objecto, pero el uso de variables globales no es recomendado por multitud de razones que dar&iacute;an para otro "Post".</p>
<p>Para conseguir nuestro objetivo lo primero que tenemos que hacer es no permitir crear instancias del objeto, para esto basta con "ocultar" el constructor declar&aacute;ndolo como "private". Lo siguiente que necesitamos es crear un m&eacute;todo est&aacute;tico que nos devuelva una instancia de ese objeto, si existe una ya creada la devolvemos y si no creamos una nueva.</p>
<p>Veamos un ejemplo de implementaci&oacute;n:</p>
<pre class="code php">
	class Database {
		static private $instance = null;
		
		private function __contruct() {}
		
		public static function getInstance() {
			if (self::$instance == null) {
				self::$instance = new Database();
			}
			return self::$instance;
		}
		
		public function connect($dsn) {
			...
		}
		
		public function query($sql) {
			...
		}
		
		public function executeQuery() {
			...
		}
		
		public function getResult() {
			...
		}
		
		public function disconnect() {
			...
		}
	}
</pre>
<br /><br />
<p>Éste sería un prototipo de una clase para trabajar con una base de datos. Como podemos ver, ya no podremos hacer "$db = new Database();", por lo que nos aseguramos el ahorro de memoria. En su lugar para obtener el objeto que deseamos tendremos que hacer:</p>
<pre class="code php">
	...
	$db = Database::getInstance();
	$db->connect($dsn);
	...
	...
</pre>
<br /><br />
<p>Siempre que llamemos al método estático "getInstance()" se comprobará que no exista ya una instancia de este objeto, si no existe crearemos una, la guardaremos como una propiedad estática de la clase y la devolveremos, muy simple.</p>
<p>Otra forma de ejecutar el código anterior sin tener que inicializar ninguna variable:</p>
<pre class="code php">
	...
	Database::getInstance()->connect($dsn);
	...
</pre>
<br /><br />
<p>Como se puede apreciar, utilizando este patrón adecuadamente, a parte de ahorrar memoria, tendríamos un código más limpio y libre de variables globales, que pueden ser modificadas por accidente en otros procesos</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=79</wfw:commentRss>
			<slash:comments>5</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/el-patron-singleton-con-php.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Crear un pasador con jQuery</title>
			<link>http://www.imaginanet.com/blog/crear-un-pasador-con-jquery.html</link>
			<guid>http://www.imaginanet.com/blog/crear-un-pasador-con-jquery.html</guid>
			<comments>http://www.imaginanet.com/blog/crear-un-pasador-con-jquery.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 23 May 2011 10:46:36 +0100</pubDate>
					<category><![CDATA[XHTML]]></category>
					<category><![CDATA[JavaScript]]></category>
					<category><![CDATA[CSS]]></category>
					<category><![CDATA[jQuery]]></category>
					<description><![CDATA[Vamos a ver como crear un pasador sencillo con jQuery. Para ello lo primero es crear la estructura html, donde tendremos b&aacute;sicamente una capa contenido con un ancho fijo y overflow oculto, y dentro de esta una capa llamada carril que contiene todos los elementos del pasador, y ser&aacute; la que iremos moviendo de...]]></description>
			<content:encoded><![CDATA[>Vamos a ver como crear un pasador sencillo con jQuery. Para ello lo primero es crear la estructura html, donde tendremos b&aacute;sicamente una capa contenido con un ancho fijo y overflow oculto, y dentro de esta una capa llamada carril que contiene todos los elementos del pasador, y ser&aacute; la que iremos moviendo de posici&oacute;n para as&iacute; conseguir el efecto buscado.<br />
<pre class="code">    <div class="marco">
       <div class="contenido">
           <div class="carril">
               <div class="mini">
                   <a class="enlace" href="#"><img src="/imaginanet/imgx/obra1.jpg" alt="" /></a>
               </div>
               <div class="mini">
                   <a class="enlace" href="#"><img src="/imaginanet/imgx/obra2.jpg" alt="" /></a>
               </div>
               <div class="mini">
                   <a class="enlace" href="#"><img src="/imaginanet/imgx/obra3.jpg" alt="" /></a>
               </div>                
           </div>
       </div>
       <a class="prev nomore" href="#"></a>
       <a class="next" href="#"></a>
   </div>
</pre>
Los enlaces para pasar de p&aacute;gina los colocamos en una capa padre a la capa contenido, dado que la capa contenido tiene overflow oculto y de meterlos dentro no se ver&iacute;an. Por tanto tendremos el siguiente c&oacute;digo css:<br />
<pre class="code">div.marco div.contenido {
   width: 172px;
   height: 80px;
   overflow: hidden;
   margin-left: 20px;
}
div.marco div.contenido div.carril {
   position: relative;
   white-space: nowrap;
}
div.marco div.contenido div.carril div.mini {
   display: inline-block;
   _display: inline;
   #display: inline;
   width: 80px;
   height: 80px;
   overflow:hidden;    
}
</pre>
A descatar que los elementos que van dentro del carril, los colocamos con inline-block, y la capa padre (carril) va con white-space: nowrap para que estos elementos del pasador no salten de l&iacute;nea.<br /> <br /> Ahora solo queda crear el c&oacute;digo javascript que mueva el pasador, para ello necesitamos saber cuanto tama&ntilde;o debemos desplazar el carril para hacer el cambio de p&aacute;gina y simular el pasador. Este tama&ntilde;o lo calculamos sabiendo la distancia que separa un elemento del carril (un div.mini) de otro, m&aacute;s su ancho, y multiplicamos el resultado por el n&uacute;mero de items que tenemos por p&aacute;gina.<br />
<pre class="code">       if (nitems &lt;= itemsxpag) {
           $(this).find("a.next").remove();
           $(this).find("a.prev").remove();
       }
       else {
           $(this).parent().find("a.next").click(function (e) {
               e.preventDefault();

               if (pagactual == npages)
                   return;
               $(self).parent().find("a.prev").removeClass("nomore");
               
               ul.animate({left:"-=" + ancho + "px"});
               pagactual++;
               
               if (pagactual == npages)
                   $(this).addClass("nomore");
           });
           $(this).parent().find("a.prev").click(function (e) {
               e.preventDefault();

               if (pagactual == 1)
                   return;
               $(self).parent().find("a.next").removeClass("nomore");
               
               ul.animate({left:"+=" + ancho + "px"});
               pagactual--;
               if (pagactual == 1)
                   $(this).addClass("nomore");
           });
       }
</pre>
En este c&oacute;digo creamos los manejadores para los clicks de los enlaces de siguiente y atras, donde b&aacute;sicamente comprobamos en que p&aacute;gina nos encontramos y si hay m&aacute;s p&aacute;ginas en la direcci&oacute;n en la que nos piden desplazarnos. La animaci&oacute;n se hace con animate de jQuery, y como podemos ver modificamos la posici&oacute;n (con left) de la capa carril, sumandole el ancho en caso de ir a una p&aacute;gina siguiente, o restandole el ancho en caso de ir a una p&aacute;gina anterior.<br /> <br /> Se puede ver el pasador explicado en funcionamiento <a href="http://www.imaginanet.com/ftp/blog/pasador/index.htm" target="_blank">aqu&iacute;</a>.]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=78</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/crear-un-pasador-con-jquery.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Validar email con javascript</title>
			<link>http://www.imaginanet.com/blog/validar-email-con-javascript.html</link>
			<guid>http://www.imaginanet.com/blog/validar-email-con-javascript.html</guid>
			<comments>http://www.imaginanet.com/blog/validar-email-con-javascript.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Fri, 20 May 2011 15:10:09 +0100</pubDate>
					<category><![CDATA[JavaScript]]></category>
					<description><![CDATA[En toda web con formularios de registro se suele incluir un campo para que el usuario introduzca su e-mail, pero antes de almacenarlo debemos asegurarnos de que el usuario nos esta facilitando un e-mail correcto, para ello podemos utilizar una expresi&oacute;n regular que compruebe que se cumplen los requisitos necesarios como...]]></description>
			<content:encoded><![CDATA[>En toda web con formularios de registro se suele incluir un campo para que el usuario introduzca su e-mail, pero antes de almacenarlo debemos asegurarnos de que el usuario nos esta facilitando un e-mail correcto, para ello podemos utilizar una expresi&oacute;n regular que compruebe que se cumplen los requisitos necesarios como tener una arroba, una extensi&oacute;n, etc.<br /> <br /> A continuaci&oacute;n la funci&oacute;n javascript que valida un email:<br />
<pre class="code">    function validarEmail(valor) {                    
       if (/(?:[a-z0-9!#$%&amp;'*+/=?^_`{|}~-]+(?:.[a-z0-9!#$%&amp;'*+/=?^_`{|}~-]+)*|"(?:[x01-x08x0bx0cx0e-x1fx21x23-x5bx5d-x7f]|[x01-x09x0bx0cx0e-x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[x01-x08x0bx0cx0e-x1fx21-x5ax53-x7f]|[x01-x09x0bx0cx0e-x7f])+)])/.test(valor)){
           return (true)
       } else {
           return (false);
       }
   }
</pre>
Para utilizarla solo hay que pasarle el email a verificar y nos devolver&aacute; un booleano verdadero si es valido o falso en caso contrario.]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=77</wfw:commentRss>
			<slash:comments>1</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/validar-email-con-javascript.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Validar nif/dni con javascript</title>
			<link>http://www.imaginanet.com/blog/validar-nifdni-con-javascript.html</link>
			<guid>http://www.imaginanet.com/blog/validar-nifdni-con-javascript.html</guid>
			<comments>http://www.imaginanet.com/blog/validar-nifdni-con-javascript.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Fri, 20 May 2011 14:52:43 +0100</pubDate>
					<category><![CDATA[Comercio electrónico]]></category>
					<category><![CDATA[JavaScript]]></category>
					<description><![CDATA[Lo primero es saber en que consiste el algoritmo de validaci&oacute;n de un nif/dni. Y es tan simple como coger los 8 n&uacute;meros del documento y hacer el modulo 23 de dicho n&uacute;mero. Este 23 es porque existen 23 letras para el nif/dni:  TRWAGMYFPDXBNJZSQVHLCKE  Vamos a calcular la letra de un nif/dni ficticio: 12345678...]]></description>
			<content:encoded><![CDATA[>Lo primero es saber en que consiste el algoritmo de validaci&oacute;n de un nif/dni. Y es tan simple como coger los 8 n&uacute;meros del documento y hacer el modulo 23 de dicho n&uacute;mero. Este 23 es porque existen 23 letras para el nif/dni:<br /> <br /> <em>TRWAGMYFPDXBNJZSQVHLCKE</em><br /> <br /> Vamos a calcular la letra de un nif/dni ficticio:<br /> <em>12345678</em><br /> <br /> Calculamos el modulo 23 del n&uacute;mero anterior y obtenemos: 14, por tanto este nif/dni tiene letra Z, dado que empezamos a contar las letras de izquierda a derecha y comenzando por el valor 0, por tanto es como buscar la letra 15 (si empiezas contando por el 1).<br /> <br /> Este algoritmo en javascript en una funci&oacute;n quedar&iacute;a as&iacute;:<br />
<pre class="code">function letraDni(numeros) {
    var letras = "TRWAGMYFPDXBNJZSQVHLCKE";
    return letras.charAt(numeros % 23);
}
</pre>
Ahora tan solo quedar&iacute;a llamarla con los 8 n&uacute;meros del nif/dni que queremos comprobar, y comparar la letra que nos retorna la funci&oacute;n con la letra indicada por el usuario.]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=76</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/validar-nifdni-con-javascript.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Validar número de cuenta bancaria</title>
			<link>http://www.imaginanet.com/blog/validar-numero-de-cuenta-bancaria.html</link>
			<guid>http://www.imaginanet.com/blog/validar-numero-de-cuenta-bancaria.html</guid>
			<comments>http://www.imaginanet.com/blog/validar-numero-de-cuenta-bancaria.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Fri, 20 May 2011 14:07:55 +0100</pubDate>
					<category><![CDATA[Comercio electrónico]]></category>
					<category><![CDATA[JavaScript]]></category>
					<description><![CDATA[Es muy com&uacute;n querer validar un numero de cuenta bancaria para evitar errores de transcripci&oacute;n. Si nos fijamos un n&uacute;mero de cuenta esta formado por 20 d&iacute;gitos, separados en 4 bloques:  1234-1234-12-1234567890  Los 4 primeros d&iacute;gitos corresponden al banco, los siguientes 4 a la sucursal, los 2...]]></description>
			<content:encoded><![CDATA[>Es muy com&uacute;n querer validar un numero de cuenta bancaria para evitar errores de transcripci&oacute;n. Si nos fijamos un n&uacute;mero de cuenta esta formado por 20 d&iacute;gitos, separados en 4 bloques:<br /> <br /> <em>1234-1234-12-1234567890</em><br /> <br /> Los 4 primeros d&iacute;gitos corresponden al banco, los siguientes 4 a la sucursal, los 2 siguientes son los d&iacute;gitos de control, y los &uacute;ltimos 10 son el n&uacute;mero de cuenta dentro de la sucursal.<br /> <br /> Para validar la cuenta se utilizan los dos d&iacute;gitos de control, siendo el primero necesario para validar los 8 primeros (banco y sucursal), y el segundo para validar los &uacute;ltimos 10 (del n&uacute;mero de cuenta).<br /> <br /> A continuaci&oacute;n vamos a calcular los d&iacute;gitos de control para la cuenta ficticia que hemos puesto antes, de esta forma comprobaremos si los d&iacute;gitos de control de arriba son erroneos:<br /> <em>banco:</em> 1234<br /> <em>sucursal:</em> 1234<br /> <em>cuenta:</em> 1234567890<br /> <br /> Antes de comenzar necesitamos saber la siguiente lista de pesos:<br /> <em>1, 2, 4, 8, 5, 10, 9, 7, 3, 6</em><br /> <br /> <em>Empezamos con el primer d&iacute;gito de control:</em><br /> Cogemos los 4 d&iacute;gitos del banco y sucursal, 12341234 y como tenemos 10 pesos (listados antes), a&ntilde;adimos dos ceros delante 0012341234, y multiplicamos cada d&iacute;gito por su peso correspondiente, el orden vienen dado por la posici&oacute;n que ocupan, es decir, el primer n&uacute;mero por el primero peso, el segundo n&uacute;mero por el segundo peso... cada resultado lo sumamos para obtener un solo n&uacute;mero.<br /> (0 * 1) + (0 * 2) + (1 * 4) + (2 * 8) + (3 * 5) + (4 * 10) + (1 * 9) + (2 * 7) + (3 * 3) + (4 * 6) = 4 + 16 + 15 + 40 + 9 + 14 + 9 + 24 = 131<br /> <br /> Ahora hacemos la siguiente operaci&oacute;n para obtener el primer n&uacute;mero del d&iacute;gito de control:<br /> 11 - (131 mod 11) = 11 - 10 = 1<br /> <br /> Y para <em>obtener el segundo d&iacute;gito de control</em> operamos de la misma forma multiplicando los 10 d&iacute;gitos de la cuenta por su peso correspondiente, sumando estos resultados, y haciendo la resta con el modulo de 11:<br /> (1 * 1) + (2 * 2) + (3 * 4) + (4 * 8) + (5* 5) + (6 * 10) + (7 * 9) + (8 * 7) + (9 * 3) + (0 * 6) = 1 + 4 + 12 + 32 + 25 + 60 + 63 + 56 + 27 + 0 = 280<br /> <br /> 11 - (280 mod 11) = 11 - 5 = 6<br /> <br /> Por tanto los d&iacute;gitos de control son el valor 16, y no 12 como hab&iacute;amos puesto al principio. Suele ser t&iacute;pico que necesitemos validar esto en javascript en un formulario, por ello a continuaci&oacute;n un ejemplo de funci&oacute;n que lo har&iacute;a:<br />
<pre class="code">function calculaDigito(valores) {
     pesos = new Array(1, 2, 4, 8, 5, 10, 9, 7, 3, 6);
     d = 0;
     for (i=0; i&lt;=9; i++) {
       d += parseInt(valores.charAt(i)) * pesos[i];
     }
     d = 11 - (d % 11);
     if (d==11) d=0;
     if (d==10) d=1;
     return d;
}
</pre>
A esta funci&oacute;n habr&iacute;a que llamarla dos veces, primero con los 8 primeros numeros (banco y sucursal) mas dos ceros delante, y luego con los 10 n&uacute;meros de la cuenta, y ya tendr&iacute;amos los d&iacute;gitos de control.]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=75</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/validar-numero-de-cuenta-bancaria.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Comandos útiles para un servidor Ubuntu / Debian</title>
			<link>http://www.imaginanet.com/blog/comandos-utiles-para-un-servidor-ubuntu-debian.html</link>
			<guid>http://www.imaginanet.com/blog/comandos-utiles-para-un-servidor-ubuntu-debian.html</guid>
			<comments>http://www.imaginanet.com/blog/comandos-utiles-para-un-servidor-ubuntu-debian.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue, 17 May 2011 14:29:22 +0100</pubDate>
					<category><![CDATA[Servidores y Seguridad]]></category>
					<category><![CDATA[Linux]]></category>
					<description><![CDATA[Completamos el listado de comandos &uacute;tiles para servidores web Linux con algunos comandos propios para distribuciones Ubuntu / Debian:
Firewall:
Poner en marcha el firewall
ufw enable
Parar firewall
ufw disable
Estado
ufw status
Bloquear puerto:
ufw deny port
Bloquear tr&aacute;fico procedente de cierta IP:
ufw deny from...]]></description>
			<content:encoded><![CDATA[><p>Completamos el listado de <a title="Comandos &uacute;tiles para servidores web LAMP" href="http://www.imaginanet.com/blog/comandos-utiles-para-un-servidor-linux.html">comandos &uacute;tiles para servidores web Linux</a> con algunos comandos propios para distribuciones Ubuntu / Debian:</p>
<h3>Firewall:</h3>
<p>Poner en marcha el firewall</p>
<pre class="code">ufw enable</pre>
<p>Parar firewall</p>
<pre class="code">ufw disable</pre>
<p>Estado</p>
<pre class="code">ufw status</pre>
<p>Bloquear puerto:</p>
<pre class="code">ufw deny port</pre>
<p>Bloquear tr&aacute;fico procedente de cierta IP:</p>
<pre class="code">ufw deny from ip</pre>
<p>Permitir puerto:</p>
<pre class="code">ufw allow port</pre>
<p>&nbsp;</p>
<h3>Manejo de paquetes:</h3>
<p>Actualizar lista de paquetes disponibles</p>
<pre class="code">apt-get update</pre>
<p>Actualizar todos los paquetes (hacer con cuidado en un servidor en producci&oacute;n):</p>
<pre class="code">apt-get upgrade</pre>
<p>Actualizar a la siguiente versi&oacute;n de la distribuci&oacute;n (hacer con cuidado en un servidor en producci&oacute;n):</p>
<pre class="code">apt-get dist-upgrade</pre>
<p>Buscar un paquete disponible:</p>
<pre class="code">apt-cache search paquete</pre>
<p>Instalar un paquete:</p>
<pre class="code">apt-get install paquete</pre>
<p>Eliminar un paquete:</p>
<pre class="code">apt-get remove paquete</pre>
<p>Intentar solucionar conflictos y dependencias rotas:</p>
<pre class="code">dpkg &ndash;configure -a</pre>
<h3>Art&iacute;culos relacionados</h3>
<ul>
<li><a href="http://www.imaginanet.com/blog/comandos-utiles-para-un-servidor-linux.html">Comandos &uacute;tiles para servidores web Linux&nbsp;</a></li>
<li><a title="Comandos &uacute;tiles para un servidor web RedHat / CentOS" href="http://www.imaginanet.com/blog/comandos-utiles-para-un-servidor-redhat-centos.html">Comandos &uacute;tiles para servidores web RedHat / CentOS</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=74</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/comandos-utiles-para-un-servidor-ubuntu-debian.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Comandos útiles para un servidor RedHat / CentOS</title>
			<link>http://www.imaginanet.com/blog/comandos-utiles-para-un-servidor-redhat-centos.html</link>
			<guid>http://www.imaginanet.com/blog/comandos-utiles-para-un-servidor-redhat-centos.html</guid>
			<comments>http://www.imaginanet.com/blog/comandos-utiles-para-un-servidor-redhat-centos.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue, 17 May 2011 13:40:43 +0100</pubDate>
					<category><![CDATA[Servidores y Seguridad]]></category>
					<category><![CDATA[Linux]]></category>
					<description><![CDATA[Completamos el listado de comandos &uacute;tiles para servidores web Linux con algunos comandos propios para distribuciones RedHat / CentOS:
Manejo de paquetes:
Buscar paquetes
yum list paquete
Instalar paquete
yum install paquete
Actualizar paquete
yum update paquete
Borrar paquete
yum remove paquete
Servicios
Asociar un servicio...]]></description>
			<content:encoded><![CDATA[><p>Completamos el listado de <a title="Comandos &uacute;tiles para servidores web Linux" href="http://www.imaginanet.com/blog/comandos-utiles-para-un-servidor-linux.html">comandos &uacute;tiles para servidores web Linux</a> con algunos comandos propios para distribuciones RedHat / CentOS:</p>
<h3>Manejo de paquetes:</h3>
<p>Buscar paquetes</p>
<pre class="code">yum list paquete</pre>
<p>Instalar paquete</p>
<pre class="code">yum install paquete</pre>
<p>Actualizar paquete</p>
<pre class="code">yum update paquete</pre>
<p>Borrar paquete</p>
<pre class="code">yum remove paquete</pre>
<h3>Servicios</h3>
<p>Asociar un servicio al inicio</p>
<pre class="code">chkconfig vsftpd on</pre>
<h3>Art&iacute;culos relacionados</h3>
<ul>
<li><a title="Comandos &uacute;tiles para un servidor web LAMP" href="http://www.imaginanet.com/blog/comandos-utiles-para-un-servidor-linux.html">Comandos &uacute;tiles para servidores web Linux</a></li>
<li><a title="Comandos &uacute;tiles para un servidor web Ubuntu / Debian" href="http://www.imaginanet.com/blog/comandos-utiles-para-un-servidor-ubuntu-debian.html">Comandos &uacute;tiles para servidores web Ubuntu / Debian</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=73</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/comandos-utiles-para-un-servidor-redhat-centos.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Comandos útiles para un servidor Linux</title>
			<link>http://www.imaginanet.com/blog/comandos-utiles-para-un-servidor-linux.html</link>
			<guid>http://www.imaginanet.com/blog/comandos-utiles-para-un-servidor-linux.html</guid>
			<comments>http://www.imaginanet.com/blog/comandos-utiles-para-un-servidor-linux.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue, 17 May 2011 12:18:26 +0100</pubDate>
					<category><![CDATA[Servidores y Seguridad]]></category>
					<category><![CDATA[Linux]]></category>
					<description><![CDATA[Para la programaci&oacute;n de p&aacute;ginas web, si contratamos un servidor web dedicado o VPS LAMP (Linux Apache MySQL PHP) y necesitamos realizar algunos ajustes en el sistema via SSH, necesitaremos tener nociones del sistema que vamos a tratar.
A continuaci&oacute;n listamos una serie de comandos &uacute;tiles para...]]></description>
			<content:encoded><![CDATA[><div>
<p>Para la <a title="Programaci&oacute;n de p&aacute;ginas web" href="http://www.imaginanet.com/programacion-web.html">programaci&oacute;n de p&aacute;ginas web</a>, si contratamos un <strong>servidor web</strong> dedicado o VPS LAMP (<em>Linux Apache MySQL PHP</em>) y necesitamos realizar algunos ajustes en el sistema via SSH, necesitaremos tener nociones del sistema que vamos a tratar.</p>
<p>A continuaci&oacute;n listamos una serie de comandos &uacute;tiles para servidores Linux y al final dejamos indicados los comandos propios para distribuciones Ubuntu / Debian y RedHat / CentOS.</p>
</div>
<p><span style="font-size: 12px; font-weight: bold;"><br />Comandos generales:</span></p>
<p>Conectar a trav&eacute;s de SSH</p>
<pre class="code">ssh root@direccionip</pre>
<p>Ejecutar un comando con privilegios de root (si no lo somos)</p>
<pre class="code">sudo comando</pre>
<p>Obtener versi&oacute;n del kernel</p>
<pre class="code">uname -a</pre>
<p>Espacio en disco ocupado por un archivo o carpeta</p>
<pre class="code">du -hlsc carpeta_o_archivo</pre>
<p>Espacio libre en los sistemas de ficheros</p>
<pre class="code"> df &nbsp; </pre>
<p>Empaquetar</p>
<pre class="code">tar cvf paquete.tar directorio_a_empaquetar</pre>
<p>Desempaquetar</p>
<pre class="code">tar xvf paquete.tar</pre>
<p>&nbsp;</p>
<h3>Servicios:</h3>
<p>Iniciar un servicio</p>
<pre class="code">/etc/init.d/service start</pre>
<p>Parar un servicio</p>
<pre class="code">/etc/init.d/service stop</pre>
<p>Estado de un servicio</p>
<pre class="code">/etc/init.d/service status</pre>
<p>Reiniciar servicio</p>
<pre class="code">/etc/init.d/service restart</pre>
<p>&nbsp;</p>
<h3>Interfaces de red:</h3>
<p>Informaci&oacute;n de las interfaces</p>
<pre class="code">ifconfig</pre>
<p>Parar una interfaz</p>
<pre class="code">ifdown interfaz</pre>
<p>Levantar una interfaz</p>
<pre class="code">ifup interfaz</pre>
<p>Editar archivo de configuraci&oacute;n de las interfaces</p>
<pre class="code">nano /etc/network/interfaces</pre>
<p>Editar archivo de servidores de nombres</p>
<pre class="code">nano /etc/resolv.conf</pre>
<p>Editar archivo hosts</p>
<pre class="code">nano /etc/hosts</pre>
<p>&nbsp;</p>
<h3>MySQL</h3>
<p>Exportar base de datos</p>
<pre class="code">mysqldump --user USUARIO --password=CONTRASE&Ntilde;A nombre_base_datos &gt; archivo.sql</pre>
<p>Exportar base de datos</p>
<pre class="code">mysqldump -u USUARIO -p nombre_base_datos &gt; archivo.sql</pre>
<p>Importar base de datos&nbsp;(debe existir antes esa base de datos)</p>
<pre class="code">mysql -u USUARIO -p nombre_base_datos &lt; archivo.sql</pre>
<p>&nbsp;</p>
<h3>Art&iacute;culos relacionados</h3>
<ul>
<li><a title="Comandos para un servidor LAMP (Linux Apache MySQL PHP) en Ubuntu / Debian" href="http://www.imaginanet.com/blog/comandos-utiles-para-un-servidor-ubuntu-debian.html">Comandos &uacute;tiles para un servidor web Ubuntu / Debian</a></li>
<li><a title="Comandos &uacute;tiles para un servidor web CentOS / RedHat" href="http://www.imaginanet.com/blog/comandos-utiles-para-un-servidor-redhat-centos.html">Comandos &uacute;tiles para un servidor web CentOS / RedHat</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=72</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/comandos-utiles-para-un-servidor-linux.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Obtener datos del muro de Facebook con PHP</title>
			<link>http://www.imaginanet.com/blog/obtener-datos-del-muro-de-facebook-con-php.html</link>
			<guid>http://www.imaginanet.com/blog/obtener-datos-del-muro-de-facebook-con-php.html</guid>
			<comments>http://www.imaginanet.com/blog/obtener-datos-del-muro-de-facebook-con-php.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Fri, 13 May 2011 12:28:52 +0100</pubDate>
					<category><![CDATA[Redes Sociales]]></category>
					<category><![CDATA[XHTML]]></category>
					<category><![CDATA[PHP]]></category>
					<description><![CDATA[Podemos obtener f&aacute;cilmente datos del muro de facebook con PHP gracias al "graph api". Lo &uacute;nico que tenemos que hacer es hacer una llamada al API y procesar los datos que nos devuelve en formato JSON. PHP nos ofrece herramientas para hacer esto de la forma m&aacute;s sencilla posible
Vamos a ver un ejemplo de como...]]></description>
			<content:encoded><![CDATA[><p>Podemos obtener f&aacute;cilmente datos del muro de facebook con PHP gracias al "graph api". Lo &uacute;nico que tenemos que hacer es hacer una llamada al API y procesar los datos que nos devuelve en formato JSON. PHP nos ofrece herramientas para hacer esto de la forma m&aacute;s sencilla posible</p>
<p>Vamos a ver un ejemplo de como obtener los datos del muro de <a href="http://www.imaginanet.com">Imaginanet</a>. Para ello debemos saber el identificador de la p&aacute;gina (o del usuario en caso de que el muro que nos interese sea el de una persona y no una p&aacute;gina). Ese identificador lo obtenemos, por ejemplo de la url de la p&aacute;gina. Si accedemos a la p&aacute;gina de facebook de <a href="http://www.imaginanet.com">Imaginanet</a>, la url que tenemos es la siguiente: <a href="http://www.facebook.com/pages/Imaginanet/293803966478">http://www.facebook.com/pages/Imaginanet/293803966478</a>. El n&uacute;mero que aparece al final es el identificador que queremos.</p>
<br />
<pre class="code php">	$id_usuario = "293803966478";
	$respuesta = file_get_contents("https://graph.facebook.com/" . $id_usuario . "/feed");

</pre>
<br />
<p>En la variable "$respuesta" tenemos los datos que queremos en formato JSON, para transformarlos en un array asociativo que nos permita manejarlo de forma sencilla solo tenemos que hacer lo siguiente:</p>
<br />
<pre class="code php">	$datos = json_decode($respuesta,true);

</pre>
<br />
<p>Ahora en la variable "$datos" tenemos un array asociativo con los datos del muro.</p>
<p>Si por ejemplo quisieramos sacar las &uacute;ltimas 4 fotos que haya en las publicaciones del muro, har&iacute;amos lo siguiente:</p>
<br />
<pre class="code php">	$facebook = array();
	$i = 0;
	foreach ($datos["data"] as $value) {
		if (trim($value["picture"]) != "") {
			$facebook[$i]["src"] = trim($value["picture"]);
			$facebook[$i]["titulo"] = trim($value["name"]);
			$facebook[$i]["texto"] = trim($value["description"]);
			$i++;
		}
		if ($i&gt;4) break;
	}
	$html = "";
	foreach ($facebook as $key =&gt; $value) {
		$html .= '
			<div>
				<h1>'.$value["titulo"].'</h1>
				&lt;img src="' . $value["src"] . '" alt="' . $value["titulo"] . '" /&gt;
				<div>'.$value["texto"].'</div>
			</div>
		';
	}

	echo $html;

</pre>
<br />
<p>Hay que tener en cuenta que esto s&oacute;lo funcionar&iacute;a para muros p&uacute;blicos, de otra forma tendr&iacute;amos que utilizar alg&uacute;n m&eacute;todo de autenticaci&oacute;n. Podemos utilizar alguna de las clases PHP que nos provee facebook, para trabajar con esta API.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=71</wfw:commentRss>
			<slash:comments>11</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/obtener-datos-del-muro-de-facebook-con-php.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Comprimir archivos dinámicamente en ZIP con PHP</title>
			<link>http://www.imaginanet.com/blog/comprimir-archivos-dinamicamente-en-zip-con-php.html</link>
			<guid>http://www.imaginanet.com/blog/comprimir-archivos-dinamicamente-en-zip-con-php.html</guid>
			<comments>http://www.imaginanet.com/blog/comprimir-archivos-dinamicamente-en-zip-con-php.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Fri, 29 Apr 2011 10:08:07 +0100</pubDate>
					<category><![CDATA[PHP]]></category>
					<description><![CDATA[En ocasiones es necesario comprimir din&aacute;micamente uno o varios archivos para generar un &uacute;nico archivo que un usuario se pueda descargar en funci&oacute;n de los par&aacute;metros de entrada. Algunos ejemplos en los que se puede usar:                  

Informes de algunos meses del a&ntilde;o.
M&uacute;ltiples...]]></description>
			<content:encoded><![CDATA[>En ocasiones es necesario comprimir din&aacute;micamente uno o varios archivos para generar un &uacute;nico archivo que un usuario se pueda descargar en funci&oacute;n de los par&aacute;metros de entrada. Algunos ejemplos en los que se puede usar:                  
<ul>
<li>Informes de algunos meses del a&ntilde;o.</li>
<li>M&uacute;ltiples im&aacute;genes o v&iacute;deos.</li>
<li>PDFs asociados a una p&aacute;gina.</li>
<li>Etc.</li>
</ul>
<p><strong>Con PHP podemos comprimir en formato ZIP</strong> de varias maneras, pero vamos a destacar dos:</p>
<ul>
<li>Nativamente con PHP, mediante su librer&iacute;a ZipArchive</li>
<li>Con librer&iacute;as externas, como PclZip</li>
</ul>
<h2>Comprimiendo archivos en ZIP con PHP mediante ZipArchive</h2>
<p>Si tu servidor tiene una versi&oacute;n superior a 5.2.0 y la extensi&oacute;n zip podemos hacer uso de ella.</p>
<p>Para saber si tenemos los requisitos, debemos usar la funci&oacute;n phpinfo() en un archivo PHP y nos mostrar&aacute; toda la informaci&oacute;n relativa al servidor.</p>
<p>Por ejemplo:</p>
<pre class="code php">&lt;?php

phpinfo();

?&gt;</pre>
<br />y debemos obtener una salida parecida a la siguiente: <br /><br /><span style="text-decoration: underline;">Versi&oacute;n de PHP</span><br /><br /><br /><img title="Versi&oacute;n de PHP para comprimir archivos en formato ZIP mediante PHP" src="http://www.imaginanet.com/ftp/articulos_web/comprimir_archivos_php/phpinfo_php5210.png" alt="Captura de pantalla de la versi&oacute;n de PHP para comprimir archivos en formato ZIP mediante PHP" width="602" height="76" /><br /><br /><span style="text-decoration: underline;">ZIP activado</span><br /><img title="Extensi&oacute;n PHP ZIP ARCHIVE" src="http://www.imaginanet.com/ftp/articulos_web/comprimir_archivos_php/ziparchive_comprimir_archivos_dinamicamente_zip.png" alt="Comprimiendo archivos en PHP mediante ZIP" width="618" height="125" /><br /><br />
<p style="margin-bottom: 0cm;">A continuaci&oacute;n podemos usar la librer&iacute;a de la siguiente manera para comprimir los archivos a.txt y b.txt en el mismo archivo ZIP:</p>
<br />
<pre class="code php">&lt;?php

$zip = new ZipArchive();

$filename = 'test.zip';

if($zip-&gt;open($filename,ZIPARCHIVE::CREATE)===true) {
        $zip-&gt;addFile('a.txt');
        $zip-&gt;addFile('b.txt');
        $zip-&gt;close();
        echo 'Creado '.$filename;
}
else {
        echo 'Error creando '.$filename;
}

?&gt;
</pre>
teniendo especial cuidado en la ejecuci&oacute;n para que tenga los permisos necesarios de escritura el archivo que comprime.
<h2>Comprimiendo archivos en ZIP con PHP mediante PclZip</h2>
<p>En ocasiones no tenemos acceso a la instalaci&oacute;n y modificaci&oacute;n de paquetes y configuraci&oacute;n de nuestro servidor, por lo que una buena opci&oacute;n es el uso de la librer&iacute;a PclZip.</p>
<p>Debemos descargar la librer&iacute;a y tras ello la guardaremos en una carpeta, por ejemplo lib.</p>
<pre class="code php">&lt;?php

require('lib/pclzip.lib.php');
$zip = new PclZip('test.zip');
$zip-&gt;create('a.txt,b.txt');

?&gt;
</pre>
<br /> Al igual que en el caso anterior, para crearlo deberemos tener permisos de ejecuci&oacute;n.<br /><br />
<h3 style="margin-bottom: 0.5cm;">Enlaces relacionados</h3>
<ul>
<li><a title="Clase ZipArchive de PHP" href="http://php.net/manual/es/class.ziparchive.php" target="_blank">PHP.net: ZipArchive</a></li>
<li><a title="Clase PclZip de PHP" href="http://www.phpconcept.net/pclzip/" target="_blank">PclZip</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=70</wfw:commentRss>
			<slash:comments>4</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/comprimir-archivos-dinamicamente-en-zip-con-php.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Cómo utilizar cualquier fuente/tipografía en nuestra página web</title>
			<link>http://www.imaginanet.com/blog/como-utilizar-cualquier-fuente-tipografia-en-nuestra-pagina-web.html</link>
			<guid>http://www.imaginanet.com/blog/como-utilizar-cualquier-fuente-tipografia-en-nuestra-pagina-web.html</guid>
			<comments>http://www.imaginanet.com/blog/como-utilizar-cualquier-fuente-tipografia-en-nuestra-pagina-web.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed, 27 Apr 2011 18:27:47 +0100</pubDate>
					<category><![CDATA[XHTML]]></category>
					<category><![CDATA[JavaScript]]></category>
					<category><![CDATA[CSS]]></category>
					<description><![CDATA[A la hora de crear p&aacute;ginas webs a veces nos encontramos limitados por las tipograf&iacute;as o fuentes tipogr&aacute;ficas que podemos utilizar en ellas, dado que no todos los navegadores y sistemas operativos incluyen el mismo n&uacute;mero de fuentes, y las tipograf&iacute;as de los sistemas operativos no ser&aacute;n las...]]></description>
			<content:encoded><![CDATA[>A la hora de crear p&aacute;ginas webs a veces nos encontramos limitados por las tipograf&iacute;as o fuentes tipogr&aacute;ficas que podemos utilizar en ellas, dado que no todos los navegadores y sistemas operativos incluyen el mismo n&uacute;mero de fuentes, y las tipograf&iacute;as de los sistemas operativos no ser&aacute;n las mismas. Por ello si queremos aplicar cualquier fuente a nuestra p&aacute;gina podemos hacer lo siguiente:<br /> <br /> Lo primero es descargar la fuente en formato True Type, cuya extensi&oacute;n es ttf. Una vez tengamos la fuente en ttf, debemos convertirla tambi&eacute;n a formato Open Type Embebido, es decir eot, o formato Web Open Font (woff) para tener compatibilidad con Internet explorer. Para llevar a cabo dicha conversi&oacute;n existen multitud de programas y p&aacute;ginas gratuitas, tan solo debemos buscar por las palabras &ldquo;ttf to eot&rdquo; o &ldquo;ttf to woff&rdquo; en cualquier buscador para encontrar una.<br /> <br /> Una vez tengamos la fuente en ambos formatos debemos utilizar en CSS la directiva @font-face para declarar nuestra nueva fuente, por ejemplo si hemos descargado la fuente &ldquo;futurastd-light-webfont.ttf&rdquo;, debemos colocar el siguiente c&oacute;digo en nuestra hoja de estilos:<br />
<pre class="code">	@font-face {
		font-family: "Futura";
		font-style: normal;
		font-weight: normal;
		src: local("?"), url("/fonts/futurastd-light-webfont.woff") format("woff"), url("/fonts/futurastd-light-webfont.ttf") format("truetype");
	}
</pre>
<br /> Siendo font-family el nombre que utilizaremos en el resto de la hoja de estilos para referenciar a nuestra nueva fuente.<br /> <br /> A continuaci&oacute;n un ejemplo de como utilizar nuestra nueva fuente que hemos declarado arriba:<br />
<pre class="code">	p {
		font-family: Futura;
	}
</pre>
<br /> De esta forma todas las etiquetas &ldquo;p&rdquo; tendr&aacute;n como estilo nuestra nueva fuente declarada como Futura.<br /> <br /> Existen dos alternativas m&aacute;s para utilizar cualquier fuente, una se conoce como sIFR y consiste en realizar el remplazo de las fuentes mediante flash. Y la otra alternativa es Cuf&oacute;n, la cu&aacute;l utiliza javascript y la etiqueta canvas para remplazar cualquier texto por la fuente nueva, y es la que m&aacute;s se utiliza a d&iacute;a de hoy por no requerir plugins, tener una gran compatiblidad con todos los navegadores, ser f&aacute;cil de usar y tener una gran velocidad incluso con grandes textos.<br /> <br /> Para utilizar cuf&oacute;n tenemos que convertir nuestra fuente True Type a SVG, para a su vez convertirla en VML (lenguaje de marcas vectorizado), y obtener finalmente un json con cierta funcionalidad. Esto lo podemos hacer desde la <a href="http://cufon.shoqolate.com/generate/">Web de Cuf&oacute;n</a> de manera sencilla y r&aacute;pida.<br /> <br /> Las ventajas de Cuf&oacute;n son claras, permite cargar cualquier fuente con tan solo incluir un script en nuestra p&aacute;gina web. Y para el renderizado se utiliza VML para Internet Explorer y la etiqueta canvas de HTML 5 para el resto de navegadores.<br /> <br /> A continuaci&oacute;n un ejemplo de c&oacute;digo para utilizar Cuf&oacute;n:<br /> Lo primero es declarar el script de cufon qu&eacute; podemos descargar de su web.<br />
<pre class="code">	<script src="/imaginanet/cufon-yui.js" type="text/javascript"><!--mce:0--></script>
</pre>
<br /> Despu&eacute;s colocamos el json de la fuente generada, el cu&aacute;l se genera utilizando el generador de la web de Cuf&oacute;n.<br />
<pre class="code">	<script src="/imaginanet/YourFont.font.js" type="text/javascript"><!--mce:1--></script>
</pre>
<br /> Y ya simplemente remplazamos las etiquetas o textos deseados, colocando en una etiqueta script el c&oacute;digo, en el ejemplo se hace un replace para la etiqueta h1 y para el id sub1.<br />
<pre class="code">	Cufon.replace('h1');
	Cufon.replace('#sub1');
</pre>
<br />
<pre class="code">	<h1>Texto a remplazar con la nueva fuente</h1>
</pre>
<br /> Cuf&oacute;n adem&aacute;s soporta selectores de jQuery o cualquier otro framework de javascript, pero para poder utilizarlos deberemos incluir jQuery o el utilizado en nuestra web.<br /> <br /> Finalmente comentar que la directiva @font-family de CSS requiere navegadores con soporte de CSS3, y tiene la ventaja de permitirnos copiar el texto al portapapeles, cosa que con Cuf&oacute;n no podemos hacer. Ahora bien si quieres utilizar cualquier fuente en navegadores antiguos debes utilizar Cuf&oacute;n, pues estos no soportan la directiva font-family.]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=68</wfw:commentRss>
			<slash:comments>8</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/como-utilizar-cualquier-fuente-tipografia-en-nuestra-pagina-web.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Expresiones regulares con PHP y Javascript</title>
			<link>http://www.imaginanet.com/blog/expresiones-regulares-con-php-y-javascript.html</link>
			<guid>http://www.imaginanet.com/blog/expresiones-regulares-con-php-y-javascript.html</guid>
			<comments>http://www.imaginanet.com/blog/expresiones-regulares-con-php-y-javascript.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Thu, 31 Mar 2011 15:53:21 +0100</pubDate>
					<category><![CDATA[PHP]]></category>
					<category><![CDATA[JavaScript]]></category>
					<description><![CDATA[Las expresiones regulares son un mecanismo que nos permite realizar b&uacute;squedas y reemplazos de textos complejos.&nbsp;
Por ejemplo podr&iacute;amos sustituir todas las ocurrencias del texto  "www.yahoo.com" por "www.google.com" utilizando la siguiente expresi&oacute;n  regular en...]]></description>
			<content:encoded><![CDATA[><p>Las expresiones regulares son un mecanismo que nos permite realizar b&uacute;squedas y reemplazos de textos complejos.&nbsp;</p>
<p>Por ejemplo podr&iacute;amos sustituir todas las ocurrencias del texto  "www.yahoo.com" por "www.google.com" utilizando la siguiente expresi&oacute;n  regular en javascript:&nbsp;</p>
<p>texto.replace(/www.yahoo.com/gi,"www.google.com")</p>
<p>El lenguage PERL es el que ha hecho crecer a las expresiones regulares hasta llegar a ser lo que conocemos hoy. En PHP y javascript se contruyen los patrones de forma similar, con Javascript podemos aprovecharnos de ellas mediante los m&eacute;todos del objeto string, y en php con funciones como preg_search o preg_replace.</p>
<p>&nbsp;</p>
<table border="0" align="left">
<tbody>
<tr>
<td colspan="2" align="left" valign="top"><strong>Para crear patrones tenemos los siguientes caracteres comod&iacute;n:</strong></td>
</tr>
<tr>
<td align="left" valign="top">&nbsp;</td>
<td align="left" valign="top">Marca de car&aacute;cter especial</td>
</tr>
<tr>
<td align="left" valign="top">^</td>
<td align="left" valign="top">Comienzo de l&iacute;nea / Negaci&oacute;n cuando est&aacute; dentro de ( ) o [ ]</td>
</tr>
<tr>
<td align="left" valign="top">$</td>
<td align="left" valign="top">Final de l&iacute;nea</td>
</tr>
<tr>
<td align="left" valign="top">.</td>
<td align="left" valign="top">Cualquier car&aacute;cter salvo el salto de l&iacute;nea</td>
</tr>
<tr>
<td align="left" valign="top">|</td>
<td align="left" valign="top">Para indicar opciones</td>
</tr>
<tr>
<td align="left" valign="top">( )</td>
<td align="left" valign="top">Para agrupar caracteres</td>
</tr>
<tr>
<td align="left" valign="top">[ ]</td>
<td align="left" valign="top">Conjunto de caracteres opcionales</td>
</tr>
<tr>
<td colspan="2" align="left" valign="top">&nbsp;</td>
</tr>
<tr>
<td colspan="2" align="left" valign="top"><strong>Modificadores. Cada modificador act&uacute;a sobre        el car&aacute;cter o el par&eacute;ntesis inmediatamente anterior.</strong></td>
</tr>
<tr>
<td align="left" valign="top">*</td>
<td align="left" valign="top">Aparece 0 o m&aacute;s veces</td>
</tr>
<tr>
<td align="left" valign="top">+</td>
<td align="left" valign="top">1 o m&aacute;s veces</td>
</tr>
<tr>
<td align="left" valign="top">?</td>
<td align="left" valign="top">1 &oacute; 0 veces</td>
</tr>
<tr>
<td align="left" valign="top">{n}</td>
<td align="left" valign="top">Exactamente n veces</td>
</tr>
<tr>
<td align="left" valign="top">{n,}</td>
<td align="left" valign="top">n veces o m&aacute;s</td>
</tr>
<tr>
<td align="left" valign="top">{n,m}</td>
<td align="left" valign="top">Entre m y n</td>
</tr>
<tr>
<td colspan="2" align="left" valign="top">&nbsp;</td>
</tr>
<tr>
<td colspan="2" align="left" valign="top"><strong>Caracteres especiales</strong></td>
</tr>
<tr>
<td align="left" valign="top">&#92;b</td>
<td align="left" valign="top">Principio o fin de palabra</td>
</tr>
<tr>
<td align="left" valign="top">&#92;B</td>
<td align="left" valign="top">Marca la frontera en una palabra</td>
</tr>
<tr>
<td align="left" valign="top">&#92;d</td>
<td align="left" valign="top">D&iacute;gito</td>
</tr>
<tr>
<td align="left" valign="top">&#92;D</td>
<td align="left" valign="top">Car&aacute;cter alfab&eacute;tico</td>
</tr>
<tr>
<td align="left" valign="top">&#92;O</td>
<td align="left" valign="top">Car&aacute;cter nulo</td>
</tr>
<tr>
<td align="left" valign="top">&#92;t</td>
<td align="left" valign="top">Tabulador</td>
</tr>
<tr>
<td align="left" valign="top">&#92;f</td>
<td align="left" valign="top">Salto de p&aacute;gina</td>
</tr>
<tr>
<td align="left" valign="top">&#92;n</td>
<td align="left" valign="top">Salto de l&iacute;nea</td>
</tr>
<tr>
<td align="left" valign="top">&#92;w</td>
<td align="left" valign="top">Car&aacute;cter alfanum&eacute;rico [a-zA-Z0-9_ ]</td>
</tr>
<tr>
<td align="left" valign="top">&#92;W</td>
<td align="left" valign="top">Lo contrario a w ([^a-zA-Z0-9_ ])</td>
</tr>
<tr>
<td align="left" valign="top">&#92;s</td>
<td align="left" valign="top">Espacio</td>
</tr>
<tr>
<td align="left" valign="top">&#92;S</td>
<td align="left" valign="top">Lo contrario a espacio</td>
</tr>
<tr>
<td align="left" valign="top">&#92;cX</td>
<td align="left" valign="top">car&aacute;cter de control X</td>
</tr>
<tr>
<td align="left" valign="top">&#92;oNN</td>
<td align="left" valign="top">car&aacute;cter octal NN</td>
</tr>
<tr>
<td align="left" valign="top">&#92;xHH</td>
<td align="left" valign="top">hexadecimal HH</td>
</tr>
<tr>
<td colspan="2" align="left" valign="top">&nbsp;</td>
</tr>
<tr>
<td colspan="2" align="left" valign="top"><strong>Al final del patr&oacute;n tambi&eacute;n podemos utilizar modificadores</strong></td>
</tr>
<tr>
<td align="left" valign="top">i</td>
<td align="left" valign="top">El patr&oacute;n es indiferente a may&uacute;sculas o min&uacute;sculas</td>
</tr>
<tr>
<td align="left" valign="top">g</td>
<td align="left" valign="top">Busca todas las ocurrencias del patr&oacute;n</td>
</tr>
</tbody>
</table>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p><br /></p>

<p><strong>Algunas expresiones regulares &uacute;tiles:</strong></p>
<table border="0">
	<tbody>
	<tr>
		<td valign="top" style="padding: 0 0 10px 0;">/(http)[s?]://)/gi</td>
		<td valign="top">Busca todas las palabras que contengan http:// o https://, insensible a may&uacute;sculas</td>
	</tr>
	<tr>
		<td valign="top" style="padding: 0 0 10px 0;">/[&#92;w-&#92;.]{3,}@([&#92;w-]{2,}&#92;.)*([&#92;w-]{2,}&#92;.)[&#92;w-]{2,4}/</td>
		<td valign="top">Para validar emails</td>
	</tr>
	<tr>
		<td valign="top" style="padding: 0 0 10px 0;">^(ht|f)tp(s?)&#92;:&#92;/&#92;/[0-9a-zA-Z]([-.&#92;w]*[0-9a-zA-Z])*(:(0-9)*)*(&#92;/?)( [a-zA-Z0-9&#92;-&#92;.&#92;?&#92;,&#92;'&#92;/&#92;&#92;&#92;+&%&#92;$#_]*)?$</td>
		<td valign="top">Para validar urls</td>
	</tr>
	<tr>
		<td valign="top" style="padding: 0 0 10px 0;">/^[#]$([a-f0-9]{3})|([a-f0-9]{6})$/i</td>
		<td valign="top">Para validar un color en formato html</td>
	</tr>
	</tbody>
</table>

<p><br /></p>
<p><br /></p>
</table>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=67</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/expresiones-regulares-con-php-y-javascript.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Leer correo con PHP</title>
			<link>http://www.imaginanet.com/blog/leer-correo-con-php.html</link>
			<guid>http://www.imaginanet.com/blog/leer-correo-con-php.html</guid>
			<comments>http://www.imaginanet.com/blog/leer-correo-con-php.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Thu, 31 Mar 2011 09:34:25 +0100</pubDate>
					<category><![CDATA[PHP]]></category>
					<description><![CDATA[Suele ser muy com&uacute;n en una web el env&iacute;o de correos electr&oacute;nicos mediante la funci&oacute;n mail de PHP, ahora bien puede ser que a veces necesitemos leer correos desde PHP, ya sea para crear una aplicaci&oacute;n de webmail, o para mostrar al usuario sus correos recibidos, o cualquier otra funcionalidad que se...]]></description>
			<content:encoded><![CDATA[><p>Suele ser muy com&uacute;n en una web el env&iacute;o de correos electr&oacute;nicos mediante la funci&oacute;n mail de PHP, ahora bien puede ser que a veces necesitemos leer correos desde PHP, ya sea para crear una aplicaci&oacute;n de webmail, o para mostrar al usuario sus correos recibidos, o cualquier otra funcionalidad que se nos ocurra.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" src="http://www.imaginanet.com/ftp/articulos_web/phpmail.png" alt="Leer correo con PHP" width="250" height="132" /><br /><br />Para lograr esto, tenemos dos formas de hacerlo:<br /> <em>1) <strong>Implementar el protocolo directamente a trav&eacute;s de sockets</strong>.</em><br /> Puede que sea la forma m&aacute;s laboriosa pero en algunos casos, puede ser &uacute;til. Como hemos dicho se trata de abrir un socket al servidor de correo y comunicarnos con &eacute;l utilizando el protocolo requerido, donde los m&aacute;s comunes son POP3 e IMAP.<br /> <br /> Por ejemplo, para crear el socket har&iacute;amos:</p>
<pre class="code">$server = "ip del servidor";
$user = "usuario de correo";
$pass = "contrase&ntilde;a del correo";
$connection = fsockopen($server, 110, $errno, $errstr, 30);</pre>
A destacar que aqu&iacute; abrimos la conexi&oacute;n al puerto 110 (correspondiente a POP3).<br /> <br /> Para logearnos en el servidor de correo, bastar&iacute;a con hacer lo siguiente:<br />
<pre class="code">fputs($connection, "user $usern");
echo fgets($connection)."<br />";
fputs($connection, "pass $passn");
echo fgets($connection)."<br />";</pre>
Como podemos ver se trata de env&iacute;ar un mensaje y esperar una respuesta.<br /> <br /> Los mensajes que env&iacute;amos y el orden en que se env&iacute;an los marca el protocolo a utilizar en este caso POP3, as&iacute; que por ejemplo si queremos recibir el correo n&uacute;mero 2 debemos enviar lo siguiente:<br />
<pre class="code">fputs($connection, "RETR 2n");
$total = 0;
$bloque = 1000;
while ($total &lt; $tamano) {
    echo fread($connection, $bloque);
    $total = $total + $bloque;
}</pre>
Se env&iacute;a el mensaje RETR 2, con lo cual el servidor de correo nos manda el mensaje n&uacute;mero 2, y procedemos a leerlo. El tama&ntilde;o del mensaje a leer, lo obtenemos mandadole previamente el mensaje LIST 2.<br /> <br /> <em>2) La forma m&aacute;s sencilla y recomendada, consiste en utilizar <strong>las funciones IMAP</strong> que nos proporciona PHP. Estas permiten conectar con POP3, IMAP y NNTP</em>.<br /> En este caso si queremos abrir una conexi&oacute;n POP3 como antes, tendremos que utilizar la funci&oacute;n imap_open:<br />
<pre class="code">$mbox = imap_open ("{localhost:110/pop3}INBOX", "user_id", "password");</pre>
<br />Para obtener el numero de mensajes se utiliza imap_check, y para leer la cabecera de un mensaje por si queremos ver qui&eacute;n lo ha enviado, se utiliza la funci&oacute;n:<br />
<pre class="code">$cabecera = imap_headerinfo($mbox, numero_mensaje)
$from = $cabecera-&gt;from;
$subject = $cabecera-&gt;subject;</pre>
Para leer ya el mensaje en s&iacute;, utilizamos la funci&oacute;n imap_fetchstructure, pasandole como parametros la conexi&oacute;n abierta ($mbox), y el n&uacute;mero del mensaje.<br /> De esta forma obtenemos todas las partes que contiene el mensaje de correo electr&oacute;nico, pudiendo ser estas texto plano, html...<br /> <br /> Otras funciones &uacute;tiles son imap_delete, que nos permite eliminar un mensaje, e imap_expunge que hace efectivos los cambios, por ejemplo borra finalmente los mensajes marcados con delete.<br /> <br /> A destacar que las funciones IMAP al conectar a una cuenta de POP3 no disponen de toda su funcionalidad, es decir no podemos marcar mensajes como le&iacute;dos, ni manejar carpetas, ...]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=66</wfw:commentRss>
			<slash:comments>5</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/leer-correo-con-php.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Creando documentos PDFs dinámicos con PHP</title>
			<link>http://www.imaginanet.com/blog/creando-documentos-pdfs-dinamicos-con-php.html</link>
			<guid>http://www.imaginanet.com/blog/creando-documentos-pdfs-dinamicos-con-php.html</guid>
			<comments>http://www.imaginanet.com/blog/creando-documentos-pdfs-dinamicos-con-php.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed, 30 Mar 2011 16:15:47 +0100</pubDate>
					<category><![CDATA[PHP]]></category>
					<category><![CDATA[XHTML]]></category>
					<description><![CDATA[Cuando tenemos una aplicaci&oacute;n web, es muy com&uacute;n que tengamos que generar un archivo PDF con datos extra&iacute;dos de una base de datos para crear por ejemplo: informes, cat&aacute;logos, facturas, documentos, etc.El uso de algunas de estas librer&iacute;as para PHP puede llegar a ser demasiado complicado, as&iacute;...]]></description>
			<content:encoded><![CDATA[><p>Cuando tenemos una aplicaci&oacute;n web, es muy com&uacute;n que tengamos que generar un archivo PDF con datos extra&iacute;dos de una base de datos para crear por ejemplo: informes, cat&aacute;logos, facturas, documentos, etc.<br /><br />El uso de algunas de estas librer&iacute;as para PHP puede llegar a ser demasiado complicado, as&iacute; que vamos a hacer uso de la librer&iacute;a <strong>mPDF</strong> que nos permite <span style="text-decoration: underline;">generar PDFs en base a un c&oacute;digo HTML y CSS</span>.<br /><br />Los resultados que vamos a obtener van a ser muy buenos en funci&oacute;n del c&oacute;digo HTML usado, aunque tambi&eacute;n podemos usar otras librer&iacute;as m&aacute;s complejas pero con resultados m&aacute;s profesionales como es el caso de ezPDF, aunque para un sencillo ejemplo mPDF nos ser&aacute; suficiente.<br /><br /></p>
<h2>Generando PDFs din&aacute;micos con mPDF en base a un c&oacute;digo HTML y CSS</h2>
<br />Con mPDF podemos seleccionar m&uacute;ltiples opciones, como la resoluci&oacute;n del documento generado, a&ntilde;adir fuentes propias o incluso hacer uso de CSS3. A continuaci&oacute;n vamos a mostrar un peque&ntilde;o ejemplo que especificamos la cabecera, cuerpo y pie del documento.<br /><br />
<pre class="code php">&lt;?php

$cabecera = "&lt;span&gt;&lt;b&gt;Mi primer documento PDF din&aacute;mico con mPDF&lt;/b&gt;&lt;/span&gt;";

$cuerpo = "&lt;html&gt;
&lt;body&gt;
&lt;br/&gt;
&lt;h1&gt;&iexcl;Hola mundo!&lt;/h1&gt;
&lt;br/&gt;
&lt;div&gt;
&lt;p&gt;A continuaci&oacute;n mostramos algunos &lt;u&gt;datos&lt;/u&gt;&lt;/p&gt;
&lt;table style='width:200px;text-align:center;'&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;A&lt;/th&gt;
&lt;th&gt;B&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;						
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;						
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;Aqu&iacute; podemos introducir datos din&aacute;micos desde PHP&lt;/p&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;";

$pie = "&lt;span&gt;
&lt;a href=\&quot;http://www.imaginanet.com\&quot;&gt;Dise&ntilde;o y Programaci&oacute;n Web: Imaginanet&lt;/a&gt;
 - &lt;i&gt;Creado &quot;.date(&quot;d/m/Y&quot;).&quot;&lt;/i&gt;
&lt;/span&gt;";

include("mpdf/mpdf.php");
$mpdf=new mPDF();
$mpdf-&gt;SetHTMLHeader($cabecera);
$mpdf-&gt;SetHTMLFooter($pie);
$mpdf-&gt;WriteHTML($cuerpo);
$mpdf-&gt;Output();

?&gt;</pre>
<p>&nbsp;</p>
<p>Como podemos ver, es m&aacute;s complicado la maquetaci&oacute;n que el uso de PHP. En la maquetaci&oacute;n podemos hacer uso de todos los tags HTML, aunque no tienen un comportamiento 100% al de un navegador, as&iacute; que deberemos adaptarnos a la salida que mPDF produce.</p>
<p>Pod&eacute;is ver el resultado final del documento PDF <a title="PDF din&aacute;mico generado mediante PHP" href="http://www.imaginanet.com/ftp/articulos_web/documento_dinamico_php_pdf.pdf">generado din&aacute;micamente mediante PHP en este enlace</a>.</p>
<h2>Automatizando nuestro script</h2>
Es muy com&uacute;n que cuando generamos un  cat&aacute;logo este sea muy pesado. Mediante mPDF, si se trata de un cat&aacute;logo  de unas cincuenta p&aacute;ginas puede tardar f&aacute;cilmente unos 30 o 40 segundos  en generarlo si este tiene un buen n&uacute;mero de im&aacute;genes. Si nuestra web  tiene una gran cantidad de tr&aacute;fico y sumado a indexaci&oacute;n que realizan  los buscadores, puede afectar al rendimiento de nuestro servidor.<br /><br />Para  solucionarlo, una buena opci&oacute;n es generar estos documentos  autom&aacute;ticamente cada cierto tiempo, como por ejemplo una vez a la semana  o una vez al d&iacute;a, y que la descarga se produzca sobre un archivo  est&aacute;tico.<br /><br />
<h3><strong>Linux</strong></h3>
<br />Vamos a hacer uso de la herramienta  crontab, un sencillo ejemplo podr&iacute;a ser a&ntilde;adir la siguiente l&iacute;nea a  nuestro archivo /etc/crontab:<br /><br />
<pre class="code">50 8 * * 1 root php /var/www/vhosts/test-domain.yy/httpdocs/cron/generacion_pdf.php
</pre>
<p><br />Esto  ejecutar&iacute;a todos los lunes a las 8:50 de la ma&ntilde;ana el archivo  /var/www/vhosts/test-domain.yy/httpdocs/cron/generacion_pdf.php como el  usuario root.<br /><strong>&nbsp;</strong></p>
<h3><strong>Plesk</strong></h3>
<p>Dentro del dominio donde corra nuestro script, tenemos un apartado de tareas programadas que guarda el mismo formato que el crontab de Linux.</p>
<h2>Enlaces relacionados</h2>
<ul>
<li><a title="Librer&iacute;a PHP mPDF" href="http://mpdf.bpm1.com/" target="_blank">mPDF</a></li>
<li><a title="Librer&iacute;a PHP ezPDF" href="http://www.ros.co.nz/pdf/" target="_blank">ezPDF</a></li>
<li><a title="Linux Crontab" href="http://es.wikipedia.org/wiki/Cron_%28Unix%29" target="_blank">Cron</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=65</wfw:commentRss>
			<slash:comments>2</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/creando-documentos-pdfs-dinamicos-con-php.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Cómo maquetar con CSS y capas una web</title>
			<link>http://www.imaginanet.com/blog/como-maquetar-con-css-y-capas-una-web.html</link>
			<guid>http://www.imaginanet.com/blog/como-maquetar-con-css-y-capas-una-web.html</guid>
			<comments>http://www.imaginanet.com/blog/como-maquetar-con-css-y-capas-una-web.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue,  1 Mar 2011 09:28:11 +0100</pubDate>
					<category><![CDATA[CSS]]></category>
					<category><![CDATA[XHTML]]></category>
					<description><![CDATA[En esta entrada vamos a ver como olvidarnos de las tablas para maquetar, ya que mostraremos como crear un t&iacute;pica web con cabecera, contenido y menu lateral, y pie utilizando solo capas y CSS.Primeramente recordemos como se hac&iacute;a esto con tablas, para as&iacute; poder apreciar la mayor sencillez de utilizar CSS con...]]></description>
			<content:encoded><![CDATA[>En esta entrada vamos a ver como olvidarnos de las tablas para maquetar, ya que mostraremos como crear un t&iacute;pica web con cabecera, contenido y menu lateral, y pie utilizando solo capas y CSS.<br /><br />Primeramente recordemos como se hac&iacute;a esto con tablas, para as&iacute; poder apreciar la mayor sencillez de utilizar CSS con capas:<br />
<pre class="code">&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;
&nbsp;&nbsp; &nbsp;&lt;table&gt;&lt;tr&gt;&lt;td&gt;Cabecera&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&lt;/td&gt;
&nbsp;&nbsp; &nbsp;&lt;/tr&gt;
&nbsp;&nbsp; &nbsp;&lt;tr&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&lt;td&gt;
&nbsp;&nbsp; &nbsp;&lt;table&gt;&lt;tr&gt;
&lt;td&gt;Menu Lateral Izquierdo&lt;/td&gt;
&lt;td&gt;Contenido&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&lt;/td&gt;
&nbsp;&nbsp; &nbsp;&lt;/tr&gt;
&nbsp;&nbsp; &nbsp;&lt;tr&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&lt;td&gt;
&nbsp;&nbsp; &nbsp;&lt;table&gt;&lt;tr&gt;&lt;td&gt;Pie&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&lt;/td&gt;
&nbsp;&nbsp; &nbsp;&lt;/tr&gt;
&lt;/table&gt;</pre>
<br />Faltar&iacute;a definir anchuras de las tablas anteriores, pero no vamos a entrar en detalle con las tablas. Ahora aplicando capas tendr&iacute;amos el siguiente c&oacute;digo:<br />
<pre class="code">&lt;div id="cabecera"&gt;
&nbsp;&nbsp; &nbsp;Cabecera
&lt;/div&gt;
&lt;div id="menulateral"&gt;
&nbsp;&nbsp; &nbsp;Menu Lateral Izquierdo
&lt;/div&gt;
&lt;div id="contenido"&gt;
&nbsp;&nbsp; &nbsp;Contenido
&lt;/div&gt;
&lt;div id="pie"&gt;
&nbsp;&nbsp; &nbsp;Pie
&lt;/div&gt;</pre>
<br />Se puede apreciar ya una mayor sencillez. Los campos id de las capas (etiquetas div) son utlizados para dar estilos con CSS tal y como vemos a continuaci&oacute;n:<br />Primero le damos una anchura y altura fija a la cabecera, adem&aacute;s de un color al fondo para apreciar claramente la posici&oacute;n de la capa.<br />
<pre class="code">#cabecera {
&nbsp;&nbsp; &nbsp;width: 600px;
&nbsp;&nbsp; &nbsp;height: 100px;
&nbsp;&nbsp; &nbsp;background: green;
}</pre>
<br />Ahora al menu lateral y al contenido les hacemos lo mismo, anchura, altura y color de background, pero adem&aacute;s a&ntilde;adimos la propiedad float con valor left. Esto le dice a ambos elementos que se coloquen como flotantes a la izquierda. En otras palabras nos permite por en una misma "l&iacute;nea" dos elementos de tipo bloque como son las capas (div).<br />
<pre class="code">#menulateral {
&nbsp;&nbsp; &nbsp;float: left;
&nbsp;&nbsp; &nbsp;width: 250px;
&nbsp;&nbsp; &nbsp;height: 100px;
&nbsp;&nbsp; &nbsp;background: yellow;
}
#contenido {
&nbsp;&nbsp; &nbsp;float: left;
&nbsp;&nbsp; &nbsp;width: 350px;
&nbsp;&nbsp; &nbsp;height: 200px;
&nbsp;&nbsp; &nbsp;background: blue;
}</pre>
<br />Finalmente al pie le damos tambi&eacute;n anchura,altura y color de background, y le a&ntilde;adimos la propiedad clear con el valor left, cuyo significado es no permitir elementos flotantes por la izquierda de este elemento. Por tanto el pie aparecera en una l&iacute;nea nueva, debajo del menu lateral y el contenido.<br />
<pre class="code">#pie {
&nbsp;&nbsp; &nbsp;width: 600px;
&nbsp;&nbsp; &nbsp;height: 50px;
&nbsp;&nbsp; &nbsp;background: cyan;
&nbsp;&nbsp; &nbsp;clear: left;
}</pre>
<br />Para apreciar mejor dicho comportamiento podemos cambiar la propiedad float de la capa contenido y poner la propiedad float con el valor "right", de esta manera la capa aparece desplaza a la esquina derecha del navegador, y se ve como "flota" sobre el elemento pie, es decir, como sobrepasa la l&iacute;nea que ocupa el pie. Para solucionar esto tendremos que cambiar la propiedad clear del pie y ponerle el valor "both", para as&iacute; no permitir elementos flotantes ni a izquierda, ni a derecha.<br /><br />Para poder centrar la p&aacute;gina web, se suele englobar todas las capas en una capa contenedora que ser&aacute; la que centremos, es decir, ponemos:<br />
<pre class="code">&lt;div id="contenedor"&gt;
&nbsp;&nbsp; &nbsp;...c&oacute;digo de capas anterior...
&lt;/div&gt;</pre>
<br />Ahora para poder centrar la capa contenedora debemos definirle una anchura, pues por defecto tiene toda la anchura disponible, y es por ello que los elementos con float right aparecen pegados a la derecha, por ello le aplicamos el siguiente c&oacute;digo CSS:<br />
<pre class="code">#contenedor {
&nbsp;&nbsp; &nbsp;width: 600px;
&nbsp;&nbsp; &nbsp;margin: 0 auto;
}</pre>
<br />Aqu&iacute; adem&aacute;s de la anchura le definimos la propiedad margin (margen), con valor 0 para el top y bottom, y auto para izquierda y derecha. Este auto provocar&aacute; que la capa contenedora se centre.<br /><br />Una buena pr&aacute;ctica para maquetar es realizar previamente un reseteo de los estilos, puesto que no todos los navegadores utilizan los mismo valores por defecto para cada etiqueta, por ello nos podemos encontrar con qu&eacute; se vea diferente nuestra p&aacute;gina en distintos navegadores. Con un reseteo se evitan gran parte de estas posibles diferencias.<br /><br />Aqu&iacute; un ejemplo de reseteo:<br />
<pre class="code">html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
&nbsp;&nbsp; &nbsp;margin: 0;
&nbsp;&nbsp; &nbsp;padding: 0;
&nbsp;&nbsp; &nbsp;border: 0;
&nbsp;&nbsp; &nbsp;outline: 0;
&nbsp;&nbsp; &nbsp;font-size: 100%;
&nbsp;&nbsp; &nbsp;vertical-align: baseline;
&nbsp;&nbsp; &nbsp;background: transparent;
}</pre>
<br />Si probamos este c&oacute;digo tal c&uacute;al en Internet Explorer podremos ver que no se centra a no ser que definamos el doctype del documento, por ello siempre es recomendable ponerlo:<br />
<pre class="code">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;/head&gt;
&lt;body&gt;
&nbsp;&nbsp; &nbsp;...c&oacute;digo anterior de capas...
&lt;/body&gt;
&lt;/html&gt;</pre>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=64</wfw:commentRss>
			<slash:comments>2</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/como-maquetar-con-css-y-capas-una-web.html</feedburner:origLink>
		</item>
				
		<item>
			<title>API de datos de Youtube</title>
			<link>http://www.imaginanet.com/blog/api-de-datos-de-youtube.html</link>
			<guid>http://www.imaginanet.com/blog/api-de-datos-de-youtube.html</guid>
			<comments>http://www.imaginanet.com/blog/api-de-datos-de-youtube.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Sun, 27 Feb 2011 22:06:55 +0100</pubDate>
					<category><![CDATA[Redes Sociales]]></category>
					<category><![CDATA[Web 2.0]]></category>
					<category><![CDATA[PHP]]></category>
					<description><![CDATA[Para crear aplicaciones relacionadas con youtube tenemos 2 APIs, API de datos y API del reproductor:
- El API de datos est&aacute; orientado a desarrolladores acostumbrados a programar en el lado del servidor. Yotube nos proporciona clases implementadas en varios lenguajes de programaci&oacute;n que nos podemos descargar.
- El API...]]></description>
			<content:encoded><![CDATA[><p>Para crear aplicaciones relacionadas con youtube tenemos <a href="http://code.google.com/intl/es-ES/apis/youtube/overview.html" target="_blank">2 APIs</a>, API de datos y API del reproductor:</p>
<p>- El API de datos est&aacute; orientado a desarrolladores acostumbrados a programar en el lado del servidor. Yotube nos proporciona clases implementadas en varios lenguajes de programaci&oacute;n que nos podemos descargar.</p>
<p>- El API del reproductor nos permite configurar las opciones del reproductor de youtube en nuestra web, creando incluso nuestros propios controles.</p>
<p>En este art&iacute;culo nos vamos a centrar en una descripci&oacute;n general del API de datos.</p>
<p>Esta API se basa en el protocolo <a href="http://www.imaginanet.com/blog/servidor-rest-con-php-y-peticiones-mediante-jquery-y-ajax.html">REST</a>, con peticiones HTTP y respuesta en formato XML, aunque tambi&eacute;n podemos obtener la respuesta en formato JSON a&ntilde;adiento a la petici&oacute;n el par&aacute;metro alt=jsonc.</p>
<p>Para autenticarnos disponemos de 3 esquemas: AuthSub, OAuth o ClientLogin.</p>
<p>- AuthSub: Para crear una aplicaci&oacute;n web que permita a los usuarios vincular v&iacute;deos, comentarios, puntuaciones, contactos u otra informaci&oacute;n con sus propias cuentas de YouTube.</p>
<p>- OAuth: Este m&eacute;todo se utiliza con la misma finalidad que el anterior pero utilizando un sistema est&aacute;ndar basado en el protocolo abierto <a href="http://oauth.net">OAuth</a></p>
<p>- ClientLogin: Para asociar todas las acciones de tu aplicaci&oacute;n a una cuenta de Youtube.</p>
<p>Si tu aplicaci&oacute;n requiere que sus usuarios introduzcan su usuario y contrase&ntilde;a de youtube, no deber&iacute;as usar el m&eacute;todo ClientLogin.</p>
<p>Para crear tu aplicaci&oacute;n tambi&eacute;n necesitar&aacute;s de una clave de desarrollador y un ID de cliente que puedes obtener <a href="http://code.google.com/apis/youtube/dashboard/" target="_blank">aqu&iacute;</a></p>
<p>En la <a href="http://code.google.com/intl/es-ES/apis/youtube/reference.html" target="_blank">gu&iacute;a de referencia</a> del API tienes informaci&oacute;n detallada sobre todas las acciones que puedes realizar y sobre los c&oacute;digos de respuesta HTTP para solicitudes del API de datos de YouTube.</p>
<p>Ahora vamos a ver unos ejemplos con PHP y curl de lo que podemos hacer utilizando este API:</p>
<p><strong>A&ntilde;adir un v&iacute;deo favorito a tu canal:</strong></p>
<p>En este ejemplo suponemos que estamos utilizando el m&eacute;todo de autenticaci&oacute;n ClientLogin. En las cabeceras de la petici&oacute;n POST debemos pasarle el m&eacute;todo de autenticaci&oacute;n y el "authtoken" que obtenemos al autenticarnos (AUTH_TOKEN), la clave de desarrollador (DEVELOPER_KEY). Tambi&eacute;n le estamos indicando que queremos los datos en formato JSON. En la variable $data tenemos que poner el id del video de youtube que queremos a&ntilde;adir como favorito a nuestro canal. como estamos utilizando un protocolo REST tenemos que enviarlo en el formato correspondiente, por eso las claves del array deben ser ["data"]["video"]["id"], este formato ser&aacute; el mismo que recibamos cuando hagamos una petici&oacute;n GET para obtener los videos favoritos de nuesto canal.</p>
<pre class="code php">	$data["data"]["video"]["id"] = 'ID_VIDEO';

	$ch = curl_init();

	curl_setopt($ch,CURLOPT_URL,'http://gdata.youtube.com/feeds/api/users/TU_CANAL/favorites?alt=jsonc');

	curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
	curl_setopt($ch, CURLOPT_POST, 1);
	curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
	curl_setopt($ch, CURLOPT_HTTPHEADER, array(
			"Host: gdata.youtube.com",
			"Content-Type: application/json",
			"Authorization: GoogleLogin auth=AUTH_TOKEN",
			"GData-Version: 2,
			"X-GData-Key: key=DEVELOPER_KEY"
	));
	$response = curl_exec($ch);
	$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
	curl_close($ch);
</pre>
<br />
<p><strong>Borrar un v&iacute;deo favorito de tu canal:</strong></p>
<p>Para borrar un video favorito de nuestro canal es muy simple, solo tenemos que enviar una petici&oacute;n DELETE a la url del video correspondiente. Para referenciar al video en la url utilizamos su ID.</p>
<pre class="code php">	$ch = curl_init('http://gdata.youtube.com/feeds/api/users/TU_CANAL/favorites/ID_VIDEO');
	curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($ch, CURLOPT_HTTPHEADER, array(
			"Host: gdata.youtube.com",
			"Content-Type: application/atom+xml",
			"Authorization: GoogleLogin auth=AUTH_TOKEN",
			"X-GData-Key: key=DEVELOPER_KEY"
	));
	$response = curl_exec($ch);
	$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
	curl_close($ch);
</pre>
<br />
<p><strong>Obtener los v&iacute;deos favoritos de tu canal:</strong></p>
<p>Obtener un listado con los v&iacute;deos favoritos de tu canal es mucho m&aacute;s simple. No necesitamos estar autenticados, pues esta acci&oacute;n es p&uacute;blica. As&iacute; que podemos utilizar la funci&oacute;n de php "file_get_contents". Si pasamos por GET el par&aacute;metro alt=jsonc, recibiremos la respuesta en JSON, por lo que parsearla ser&aacute; mucho m&aacute;s sencillo, solo hay que aplicarle la funci&oacute;n "json_decode" a la respuesta.</p>
<pre class="code php">	$response = file_get_contents("http://gdata.youtube.com/feeds/api/users/TU_CANAL/favorites?v=2&amp;alt=jsonc");
	$response = json_decode($response,true);
</pre>
<br />
<p>En la <a href="http://code.google.com/intl/es-ES/apis/youtube/reference.html" target="_blank">gu&iacute;a de referencia</a> del API tenemos los c&oacute;digos de respuesta de estas acciones, adem&aacute;s de una explicaci&oacute;n m&aacute;s detallada de lo que podemos hacer con esta API. En estos ejemplos hemos utilizado php y curl para hacer las peticiones, pero desde la web del API podemos descargarnos clases para distintos lenguajes de programaci&oacute;n que nos facilitar&aacute;n esta tarea.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=63</wfw:commentRss>
			<slash:comments>1</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/api-de-datos-de-youtube.html</feedburner:origLink>
		</item>
				
		<item>
			<title>El tiempo en tu web mediante el API Google Weather</title>
			<link>http://www.imaginanet.com/blog/el-tiempo-en-tu-web-mediante-el-api-google-weather.html</link>
			<guid>http://www.imaginanet.com/blog/el-tiempo-en-tu-web-mediante-el-api-google-weather.html</guid>
			<comments>http://www.imaginanet.com/blog/el-tiempo-en-tu-web-mediante-el-api-google-weather.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed, 16 Feb 2011 13:03:12 +0100</pubDate>
					<category><![CDATA[PHP]]></category>
					<description><![CDATA[Mediante Google Weather podemos  mostrar un informe meteorol&oacute;gico para diferentes ciudades de manera personalizada del tiempo actual y una predicci&oacute;n de los d&iacute;as pr&oacute;ximos.
La llamada a Google Weather es una simple llamada a una URL pasando el par&aacute;metro de  ciudad, por ejemplo...]]></description>
			<content:encoded><![CDATA[>Mediante Google Weather podemos  mostrar un <strong>informe meteorol&oacute;gico</strong> para diferentes ciudades de manera personalizada del tiempo actual y una predicci&oacute;n de los d&iacute;as pr&oacute;ximos.
<p>La llamada a Google Weather es una simple llamada a una URL pasando el par&aacute;metro de  ciudad, por ejemplo <a href="http://www.google.com/ig/api?weather=Madrid">http://www.google.com/ig/api?weather=Madrid</a> devolvi&eacute;ndonos un XML (podemos probar a poner esta direcci&oacute;n en un navegador web para hacernos una idea).</p>
<p>El siguiente paso ser&iacute;a procesar el XML devuelto y mostrar los datos que nos interesen. Por ejemplo vamos a mostrar un c&oacute;digo en PHP para el <strong>API de Google Weather</strong> usando la librer&iacute;a <span style="text-decoration: underline;">SimpleXML</span>:</p>
<pre class="code php">&lt;?php
	// Proceso
	$ciudad = "Barcelona";

	$xml = simplexml_load_file("http://www.google.com/ig/api?weather=".$ciudad);

	if($xml===false) { // Fallo al contactar con Google
			return null;
	}

	$current = $xml-&gt;xpath("/xml_api_reply/weather/current_conditions"); 
	if(count($current)==0) { // Ciudad err&oacute;nea
			return null;
	}

	$temperatura_centigrados = $current[0]-&gt;temp_c["data"];
	$humedad = $current[0]-&gt;humidity["data"];
	$condiciones = $current[0]-&gt;condition["data"];
	$icono = $current[0]-&gt;icon["data"];
	
	// Vista
	echo 'Temperatura: '.$temperatura_centigrados.'&amp;deg;&lt;br/&gt;';
	echo $humedad.'&lt;br/&gt;';
	echo 'Condiciones: '.$condiciones.'&lt;br/&gt;';
	echo '&lt;img src="http://www.google.com/'.$icono.'" alt="'.$condiciones.'" title="'.$condiciones.'"/&gt;"';
	
?&gt;

</pre>
<p>Por &uacute;ltimo, para hacer nuestra aplicaci&oacute;n resistente a fallos, recomendamos ejecutar este script desde una llamada AJAX, ya que si Google fallara o tardara en responder, nuestra p&aacute;gina tardar&iacute;a o fallar&iacute;a al servirse.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=62</wfw:commentRss>
			<slash:comments>10</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/el-tiempo-en-tu-web-mediante-el-api-google-weather.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Mostrar videos en capas superpuestas</title>
			<link>http://www.imaginanet.com/blog/mostrar-videos-en-capas-superpuestas.html</link>
			<guid>http://www.imaginanet.com/blog/mostrar-videos-en-capas-superpuestas.html</guid>
			<comments>http://www.imaginanet.com/blog/mostrar-videos-en-capas-superpuestas.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Thu, 28 Apr 2011 09:32:41 +0100</pubDate>
					<category><![CDATA[XHTML]]></category>
					<category><![CDATA[JavaScript]]></category>
					<category><![CDATA[CSS]]></category>
					<category><![CDATA[Internet Explorer]]></category>
					<description><![CDATA[Es posible que en alguna situaci&oacute;n tengamos dos videos superpuestos, ya sea porque tengamos un dise&ntilde;o con pesta&ntilde;as, o que incluso tengamos alguna ventana que haga de popup y deba mostrarse por encima de un video.  Para poder lograr que los videos se coloquen correctamente debemos pasarle el parametro...]]></description>
			<content:encoded><![CDATA[>Es posible que en alguna situaci&oacute;n tengamos dos videos superpuestos, ya sea porque tengamos un dise&ntilde;o con pesta&ntilde;as, o que incluso tengamos alguna ventana que haga de popup y deba mostrarse por encima de un video.<br /> <br /> Para poder lograr que los videos se coloquen correctamente debemos pasarle el parametro &ldquo;wmode&rdquo; con el valor &ldquo;transparent&rdquo; de esta forma no dar&aacute;n ning&uacute;n problema en Internet Explorer. Ahora bien para crear dos pesta&ntilde;as y que podamos tener ambos videos abiertos y cambiar entre ellos, podemos optar por la siguiente soluci&oacute;n:<br /> <br /> Colocar las capas con posici&oacute;n absoluta y jugar con la propiedad z-index para ir cambiando cu&aacute;l se muestra por encima de la otra, de esta forma podremos estar viendo los videos sin que al cambiar de pesta&ntilde;a vuelva a empezar la reproducci&oacute;n del video.<br />
<pre class="code"><div style="background: #CCC; width: 680px; position: relative;">
       <div>
           <a onclick="document.getElementById('parte2').style .zIndex='1';document.getElementById('parte1').style .zIndex='2';return false;" href="#">Video 1</a>
           <a onclick="document.getElementById('parte1').style .zIndex='1';document.getElementById('parte2').style .zIndex='2';return false;" href="#">Video 2</a>
       </div>
       <div id="parte1" style="z-index: 2; position: absolute; background: #090; width: 680px; text-align: center;">
           <iframe src="http://www.youtube.com/embed/mkUdQtINflw?wmode=transparent" width="640" height="390"></iframe>
       </div>
       <div id="parte2" style="z-index: 1; position: absolute; background: #009; width: 680px; text-align: center;">
           <iframe src="http://www.youtube.com/embed/Ezk0e1VL80o?wmode=transparent" width="640" height="390"></iframe>
       </div>
</div>
</pre>
<br /> Podemos ver el ejemplo en funcionamiento <a href="http://www.imaginanet.com/ftp/blog/videos.htm" target="_blank">aqu&iacute;</a>.]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=69</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/mostrar-videos-en-capas-superpuestas.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Servidor REST con PHP y peticiones mediante jquery y ajax.</title>
			<link>http://www.imaginanet.com/blog/servidor-rest-con-php-y-peticiones-mediante-jquery-y-ajax.html</link>
			<guid>http://www.imaginanet.com/blog/servidor-rest-con-php-y-peticiones-mediante-jquery-y-ajax.html</guid>
			<comments>http://www.imaginanet.com/blog/servidor-rest-con-php-y-peticiones-mediante-jquery-y-ajax.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 14 Feb 2011 20:45:36 +0100</pubDate>
					<category><![CDATA[PHP]]></category>
					<category><![CDATA[jQuery]]></category>
					<category><![CDATA[Ajax]]></category>
					<description><![CDATA[Un servidor REST (Representational State Transfer) puede ser muy &uacute;til para la creaci&oacute;n de aplicaciones HTML5. Utilizar&iacute;amos el servidor para el m&oacute;delo de datos y el cliente (navegador) para la l&oacute;gica de la aplicaci&oacute;n, realizando llamadas ajax al servidor que devolver&iacute;a los datos en...]]></description>
			<content:encoded><![CDATA[><p>Un servidor <strong>REST</strong> (Representational State Transfer) puede ser muy &uacute;til para la creaci&oacute;n de aplicaciones HTML5. Utilizar&iacute;amos el servidor para el m&oacute;delo de datos y el cliente (navegador) para la l&oacute;gica de la aplicaci&oacute;n, realizando llamadas ajax al servidor que devolver&iacute;a los datos en formato JSON, por ejemplo. En un sistema REST, cada recurso es direccionable &uacute;nicamente a trav&eacute;s de su URI, y disponemos de un conjunto de aplicaciones (<strong>POST</strong>, <strong>GET</strong>, <strong>PUT</strong> y <strong>DELETE</strong>), propias del protocolo HTTP, para trabajar con esos recursos.</p>
<p>Por ejemplo, si disponemos de una base de datos de clientes y queremos objetener una lista con ellos, tendr&iacute;amos que acceder a la URL del recurso "clientes", http://servidor.com/clientes. Una petici&oacute;n GET a este recurso nos devolver&iacute;a un array con todos los clientes que tenemos en nuestra BB.DD. Si lo que queremos es obtener la informaci&oacute;n de un cliente en particular, por ejemplo el cliente con identificador igual a 00001, har&iacute;amos una petici&oacute;n GET a la url http://servidor.com/clientes/00001. Para crear un cliente nuevo tendr&iacute;amos que enviar por POST una petici&oacute;n a http://servidor.com/clientes con los datos del nuevo cliente. Para modificar alg&uacute;n dato del cliente 00001 usar&iacute;amos una petici&oacute;n PUT con los nuevos datos a http://servidor.com/clientes/00001. Si la petici&oacute;n es DELETE a esa misma url, borrar&iacute;amos ese registro de la BB.DD. Normalmente los datos que devuelve el servidor estar&aacute;n en formato JSON o XML. Para nuestro ejemplo utilizaremos JSON, ideal para trabajar con aplicaciones javascript.</p>
<p>Para tratar mediante PHP las peticiones en nuestro servidor utilizaremos un c&oacute;digo parecido a este:</p>
<pre class="code php">$method = $_SERVER['REQUEST_METHOD'];

// tendremos que tratar esta variable para obtener el recurso adecuado de nuestro modelo.
$resource = $_SERVER['REQUEST_URI'];

// Dependiendo del m&eacute;todo de la petici&oacute;n ejecutaremos la acci&oacute;n correspondiente.
switch ($method) {
	case 'GET':
		// c&oacute;digo para m&eacute;todo GET
		break;
	case 'POST':
		$arguments = $_POST;
		// c&oacute;digo para m&eacute;todo POST
		break;
	case 'PUT':
		parse_str(file_get_contents('php://input'), $arguments);
		// c&oacute;digo para m&eacute;todo PUT
		break;
	case 'DELETE':
		// c&oacute;digo para m&eacute;todo DELETE
		break;
}
echo json_encode($response,true); // $response será un array con los datos de nuestra respuesta.
</pre>
<br />
<p>Utilizando jquery es muy sencillo realizar peticiones a nuestro servidor con la funci&oacute;n $.ajax:</p>
<pre class="code js">$.ajax({
	url: 'http://servidor.com/recurso', // url del recurso
	type: "get", // podr&iacute;a ser get, post, put o delete.
	data: {}, // datos a pasar al servidor, en caso de necesitarlo
	success: function (r) {
		// aqu&iacute; tratar&iacute;amos la respuesta del servidor
	}
});
</pre>
<br />
<p>Con estas simples indicaciones ya tenemos las bases para la construcci&oacute;n de una aplicaci&oacute;n. Si dise&ntilde;amos bien nuestro modelo de datos tendremos la oportunidad de crear gran variedad de aplicaciones para distintos tipos de clientes (navegadores web, m&oacute;viles, aplicaciones de escritorio ...), sin tener que modificar nuestro servidor, utilizando un m&eacute;todo estandar, sencillo e intuitivo.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=61</wfw:commentRss>
			<slash:comments>14</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/servidor-rest-con-php-y-peticiones-mediante-jquery-y-ajax.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Como compartir contenidos con RSS en PHP</title>
			<link>http://www.imaginanet.com/blog/como-compartir-contenidos-con-rss-en-php.html</link>
			<guid>http://www.imaginanet.com/blog/como-compartir-contenidos-con-rss-en-php.html</guid>
			<comments>http://www.imaginanet.com/blog/como-compartir-contenidos-con-rss-en-php.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed,  2 Feb 2011 08:36:13 +0100</pubDate>
					<category><![CDATA[PHP]]></category>
					<category><![CDATA[RSS]]></category>
					<description><![CDATA[RSS (Really Simple Sindication) es un est&aacute;ndar con formato XML que permite compartir contenidos de una p&aacute;gina web. Facilitando incluso leer dichos contenidos sin disponer de un navegador web.
Para poder compartir el contenido se debe seguir el siguiente formato indicado por RSS (solo mostramos las etiquetas...]]></description>
			<content:encoded><![CDATA[><p>RSS (Really Simple Sindication) es un est&aacute;ndar con formato XML que permite compartir contenidos de una p&aacute;gina web. Facilitando incluso leer dichos contenidos sin disponer de un navegador web.</p>
<p><img style="display: block; margin-left: auto; margin-right: auto;" title="RSS" src="http://www.imaginanet.com/ftp/articulos_web/128px-Feed-icon.svg.png" alt="RSS" width="128" height="128" /><br />Para poder compartir el contenido se debe seguir el siguiente formato indicado por RSS (solo mostramos las etiquetas m&aacute;s comunes):</p>
<pre class="code">&lt;?xml version="1.0" encoding="Codificaci&oacute;n de nuestro texto del contenido o web"?&gt;
&lt;rss version="2.0"&gt;
&nbsp;&nbsp; &nbsp;&lt;channel&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&lt;title&gt;T&iacute;tulo de nuestro contenido o web&lt;/title&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&lt;link&gt;Enlace a nuestro contenido o web &lt;/link&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&lt;description&gt;Descripci&oacute;n del contenido o web&lt;/description&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&lt;language&gt;Idioma del contenido o web&lt;/language&gt;

&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&lt;item&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&lt;title&gt;Titulo del item&lt;/title&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&lt;link&gt;Enlace del item &lt;/link&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&lt;pubDate&gt;Fecha de publicaci&oacute;n del item&lt;/pubDate&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&lt;description&gt;Descripci&oacute;n del item&lt;/description&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&lt;/item&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&lt;item&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;...
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&lt;/item&gt;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;...
&nbsp;&nbsp; &nbsp;&lt;/channel&gt;
&lt;/rss&gt;
</pre>
Como podemos apreciar, si por ejemplo queremos compartir las noticias de un blog, se debe crear un item por cada una de ellas.<br /><br />No vamos a entrar en detalle de como generar los datos necesarios, pero lo normal es obtenerlos de una base de datos a trav&eacute;s de una serie de consultas SQL. Ahora bien una vez tengamos nuestros datos generados, hay que tener en cuenta lo siguiente:<br /><br />- La codificaci&oacute;n a indicar en la cabecera de xml, debe ser la misma que la codificaci&oacute;n usada para almacenar nuestros datos, siendo las m&aacute;s comunes ISO-8859-1 y UTF-8.<br />- Para los datos como t&iacute;tulo y descripci&oacute;n, o cualquier otro campo cuyo contenido suela llevar etiquetas HTML, es necesario o bien eliminarlas utilizando funciones PHP como "htmlentities" o "strip_tags", o bien utilizar la etiqueta &lt;![CDATA[ ]]&gt; que hace que el contenido que tenga se ignore y no se procese como XML, permitiendo mostrar el contenido HTML.<br />- Si nuestro contenido tiene acentos no ser&aacute; suficiente con utilizar las funciones de PHP mencionadas, suponiendo que no se quisiera conservar las etiquetas HTML, sino que ser&aacute; necesario utilizar adem&aacute;s la etiqueta CDATA para escapar dichos car&aacute;cteres.<br /><br />En resumen si queremos conservar las etiquetas HTML o tenemos acentos utilizamos la etiqueta CDATA. Y si por el contrario no queremos etiquetas HTML, entonces utilizamos las funciones PHP citadas.<br />
<pre class="code">&nbsp;&nbsp; &nbsp;echo "&lt;title&gt;&lt;![CDATA[". $titulo ."]]&gt;&lt;/title&gt;";
&nbsp;&nbsp; &nbsp;echo "&lt;description&gt;&lt;![CDATA[". $texto ."]]&gt;&lt;/description&gt;";
</pre>
Siguiendo estos consejos &uacute;ltimos evitaremos errores de lectura XML, es decir, de XML mal formado.<br />]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=60</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/como-compartir-contenidos-con-rss-en-php.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Controlar los pagos por PayPal mediante Notificación de Pago Instantánea</title>
			<link>http://www.imaginanet.com/blog/controlar-los-pagos-por-paypal-mediante-notificacion-de-pago-instantanea.html</link>
			<guid>http://www.imaginanet.com/blog/controlar-los-pagos-por-paypal-mediante-notificacion-de-pago-instantanea.html</guid>
			<comments>http://www.imaginanet.com/blog/controlar-los-pagos-por-paypal-mediante-notificacion-de-pago-instantanea.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Fri, 14 Jan 2011 08:47:06 +0100</pubDate>
					<category><![CDATA[Comercio electrónico]]></category>
					<category><![CDATA[PHP]]></category>
					<description><![CDATA[Tras ver como realizar pagos por PayPal en una tienda virtual en tu web, el siguiente paso ser&iacute;a saber si finalmente el usuario realiz&oacute; el pago o no, ya que podr&iacute;a haber cerrado la ventana, no tener la tarjeta de cr&eacute;dito a mano o simplemente haberse arrepentido.
Verificando el pago de las compras en un...]]></description>
			<content:encoded><![CDATA[><p>Tras ver como <a title="Pagar mediante PayPal en tu p&aacute;gina web" href="http://www.imaginanet.com/blog/como-utilizar-paypal-para-realizar-compras-en-tu-web.html">realizar pagos por PayPal en una tienda virtual</a> en tu web, el siguiente paso ser&iacute;a saber si finalmente el usuario realiz&oacute; el pago o no, ya que podr&iacute;a haber cerrado la ventana, no tener la tarjeta de cr&eacute;dito a mano o simplemente haberse arrepentido.</p>
<h3>Verificando el pago de las compras en un comercio electr&oacute;nico mediante PayPal</h3>
<p>Como no sabemos si el cliente va a realmente a pagar tras ir a la pantalla de pago de PayPal, lo ideal es tratar cada compra como no pagada hasta que recibamos la confirmaci&oacute;n por parte de PayPal de que as&iacute; ha sido.</p>
<p>Para recibir la notificaci&oacute;n por parte de PayPal, deberemos activar la opci&oacute;n del <strong>Instant Payment Notification</strong> o <strong>Notificaci&oacute;n de Pago Instant&aacute;nea</strong> en el panel de control de tu cuenta y especificar la ruta de donde tiene que avisar con unos datos relativos a la compra que se ha realizado satisfactoriamente.</p>
<p>Este archivo al que PayPal avisa lo alojaremos en nuestro servidor y deber&aacute; ser programado a medida para realizar la acci&oacute;n que corresponda. En nuestro caso programaremos en PHP y la ruta de aviso por ejemplo podr&iacute;a ser http://www.mi-host-de-pruebas.com/paypal_ipn.php</p>
<p>La programaci&oacute;n del archivo paypal_ipn.php har&aacute; actualizar el estado en base de datos de ese pedido de no pagado a pagado.</p>
<h3>Configurando Instant Payment Notification en nuestra cuenta de PayPal</h3>
<p>Lo primero deberemos crear una cuenta <em>Premier</em> o <em>Business</em> de PayPal y acceder a ella. En la pantalla principal, deberemos estar en la pesta&ntilde;a "Mi cuenta", ir al submen&uacute; "Perfil" y elegir "M&aacute;s opciones".</p>
<p>En la nueva pantalla elegir la opci&oacute;n "Preferencias de Notificaci&oacute;n de pago instant&aacute;nea". Ahora rellenaremos el campo "URL de notificaci&oacute;n" con la direcci&oacute;n que nos interese (por ejemplo http://www.mi-host-de-pruebas.com/paypal_ipn.php), marcaremos la opci&oacute;n de "Recibir mensajes de IPN (activado)" y guardaremos los cambios.</p>
<h3>Programando la actualizado de la compra electr&oacute;nica con PHP</h3>
<p>Cuando se realiza un pago satisfactoriamente, PayPal nos env&iacute;a una serie de variables mediante POST con la que podemos identificar qu&eacute; pago se ha pagado satisfactoriamente, pero s&oacute;lo nos har&aacute;n falta dos:</p>
<ul>
<li><strong><em>payment_status</em></strong>: puede tener varios valores, pero los que nos interesan son s&oacute;lo dos, <em>Completed</em>, que significa que la transacci&oacute;n de dinero se ha completado, y <em>Processed</em>, indica que el pago ha sido aceptado pero no se ha completado a&uacute;n la transacci&oacute;n de dinero por que el banco del cliente a&uacute;n no ha hecho la transferencia de dinero (este caso tambi&eacute;n lo contemplamos como pago v&aacute;lido).</li>
<li><strong><em>item_number</em></strong>: esta variable es una de las que nuestra p&aacute;gina web env&iacute;o al redirigirnos a PayPal (lo podemos ver en la primera parte de como utilizar PayPal en nuestra p&aacute;gina web) y contiene un valor que identifique la compra que se ha pagado.</li>
</ul>
<p>Lo primero es comprobar que payment_status nos indica que se ha realizado un pago, a partir de ah&iacute; deberemos jugar con la variable item_number que puede tener m&uacute;ltiples usos. Si por ejemplo al llamar a PayPal indicamos que item_number es "VENTA-512", en la notificaci&oacute;n sabremos que la venta de identificador 512 se ha pagado satisfactoriamente.</p>
<p>Tambi&eacute;n podr&iacute;amos realizar distintos tipos de pago en nuestra web que no s&oacute;lo sea de venta, si no transacci&oacute;n, alquiler, etc. y siempre podr&iacute;amos identificarla mediante la variable item_number.</p>
<p><strong>Ejemplo de como procesar una Notificaci&oacute;n de Pago Instant&aacute;nea mediante PHP</strong></p>
<pre class="code php">&lt;?php

// Poner aqu&iacute; c&oacute;digo de inicializaci&oacute;n en base de datos //

if($_POST['payment_status']=='Completed' || $_POST['payment_status']=='Processed') {
	// Suponemos que el item_number que nosotros enviamos es del formato: XXXXX-YYYY
	// Donde XXXXX es el tipo de pago e YYYY es el identificador &uacute;nico del pago
	$tipo_venta_aux = explode('-',$_POST['item_number']);
	$tipo_venta = $tipo_venta_aux[0];
	$item_pagado = $tipo_venta_aux[1];

	$pago_valido = false;

        // Verificamos en base de datos
	switch($tipo_venta) {
		case 'VENTA':
			// Verificamos que es una venta existente y pendiente de pago
			$pago_valido = true;
			break;
		case 'ALQUILER':
			// Verificamos que es un alquiler existente y pendiente de pago
			$pago_valido = true;
			break;
		case 'PAGO_MENSUAL':
			// Verificamos que es un pago mensual existente y pendiente de pago
			$pago_valido = true;
			break;
	}

	if($pago_valido == true) {
		// Actualizamos el estado a pagado y hacemos lo que nos interese.
		// Como por ejemplo notificar al cliente de que el pago ha sido registrado.
	}
}

// Poner aqu&iacute; c&oacute;digo de finalizaci&oacute;n en base de datos //

?&gt;
</pre>
<h3><strong>P&aacute;ginas y art&iacute;culos relacionados</strong></h3>
<ul>
<li><a title="Pagar mediante PayPal en tu p&aacute;gina web" href="http://www.imaginanet.com/blog/como-utilizar-paypal-para-realizar-compras-en-tu-web.html">Como realizar compras en tu web mediante PayPal</a>.</li>
<li><a title="M&aacute;s informaci&oacute;n sobre PayPal IPN" href="https://www.paypal.com/ipn">Documentaci&oacute;n de PayPal sobre IPN</a>.</li>
<li><a title="Pagos masivos a PayPal" href="http://www.imaginanet.com/blog/pagos-en-serie-de-paypal.html">Pagos en serie a PayPal</a>.</li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=59</wfw:commentRss>
			<slash:comments>13</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/controlar-los-pagos-por-paypal-mediante-notificacion-de-pago-instantanea.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Programando para Android: una sencilla aplicación</title>
			<link>http://www.imaginanet.com/blog/programando-para-android-una-sencilla-aplicacion.html</link>
			<guid>http://www.imaginanet.com/blog/programando-para-android-una-sencilla-aplicacion.html</guid>
			<comments>http://www.imaginanet.com/blog/programando-para-android-una-sencilla-aplicacion.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 13 Dec 2010 10:40:12 +0100</pubDate>
					<category><![CDATA[Apps]]></category>
					<category><![CDATA[Android]]></category>
					<category><![CDATA[Java]]></category>
					<description><![CDATA[Vamos a hablar sobre como programar una aplicaci&oacute;n para un dispositivo con Android que se va a tratar de una sencilla calculadora.
Como todos sabemos, Android se programa mediante el lenguaje de programaci&oacute;n Java. Este ejemplo de la calculadora puede parecer demasiado b&aacute;sico, pero con una idea inicial de como...]]></description>
			<content:encoded><![CDATA[><p>Vamos a hablar sobre como programar una aplicaci&oacute;n para un dispositivo con <strong>Android</strong> que se va a tratar de una sencilla calculadora.</p>
<p>Como todos sabemos, Android se programa mediante el lenguaje de programaci&oacute;n <strong>Java</strong>. Este ejemplo de la calculadora puede parecer demasiado b&aacute;sico, pero con una idea inicial de como hacer una peque&ntilde;a aplicaci&oacute;n para Android y nociones sobre Java, veremos que desarrollar un programa m&aacute;s complejo es muy f&aacute;cil.</p>
<p><span style="text-decoration: underline;">En primer lugar</span>, necesitaremos el <strong>Android SDK</strong> que lo podemos descargar de <a href="http://developer.android.com/sdk/index.html">http://developer.android.com/sdk/index.html</a></p>
<p>Tras instalarlo deberemos ejecutar el archivo android dentro de la carpeta tools y hacer lo siguiente:</p>
<ul>
<li>Instalar la plataforma de la versi&oacute;n Android a emular, lo haremos desde la pesta&ntilde;a <em>Available packages</em> y elegiremos la versi&oacute;n que queramos (2.1, 2.2, 2.3, etc)</li>
<li>Crear un dispositivo virtual, pesta&ntilde;a <em>Virtual devices</em>, que ser&aacute; nuestro dispositivo a emular.</li>
</ul>
<p><span style="text-decoration: underline;">Como segundo paso</span>, haremos uso de la plataforma <strong>Eclipse</strong> y su plugin ADT para el desarrollo de Android bajo Eclipse. Podemos hacerlo desde la direcci&oacute;n <a href="http://developer.android.com/sdk/eclipse-adt.html">http://developer.android.com/sdk/eclipse-adt.html</a></p>
<p>Ahora nos quedar&iacute;a configurar Eclipse para que supiera la ruta hasta el SDK de Android y tendr&iacute;amos todo preparado para trabajar. Lo podemos hacer desde el men&uacute; Window -&gt; Preferences y dentro de la ventana en la pesta&ntilde;a Android tenemos la opci&oacute;n SDK Location.</p>
<p>Ahora tenemos todo preparado y configurado para empezar a crear aplicaciones. La web del SDK de Android contiene varios ejemplo de como empezar a programar y el ejemplo m&aacute;s sencillo es el del "<em>Hola Mundo</em>" donde viene todo el proceso indicado arriba de forma m&aacute;s detallada (lo pod&eacute;is encontrar aqu&iacute; <a href="http://developer.android.com/resources/tutorials/hello-world.html">http://developer.android.com/resources/tutorials/hello-world.html</a>).</p>
<p>Nosotros nos vamos a basar en uno un poco m&aacute;s avanzado y lo vamos a ampliar hasta crear una aplicaci&oacute;n con cierta utilidad. Este ejemplo es el de como posicionar elementos con tama&ntilde;os y posiciones relativas <a href="http://developer.android.com/resources/tutorials/views/hello-relativelayout.html" target="_blank">http://developer.android.com/resources/tutorials/views/hello-relativelayout.html</a> y vamos a a&ntilde;adir algunos elementos y funcionalidades para crear nuestra sencilla calculadora.</p>
<h3>Creando nuestra primera aplicaci&oacute;n para Android</h3>
<p>Para ver cual queremos que sea la interfaz final e intuir el funcionamiento, vamos a mostrar una captura de pantalla del resultado final en el emulador:</p>
<p><img title="Primer programa para Android: una calculadora" src="http://www.imaginanet.com/ftp/articulos_web/android/Programa sencillo Android SDK.png" alt="Programaci&oacute;n para Android"/></p>
<p>donde podemos ver tres elementos: <em>TextView</em> (objeto para mostrar texto), <em>EditText</em> (caja de entrada de texto) y <em>Button</em> (bot&oacute;n).</p>
<p>Empezaremos creando en Eclipse un proyecto para Android, modificaremos el archivo <strong>res/layout/main.xml</strong> en su vista de c&oacute;digo de fuente y pegaremos el siguiente c&oacute;digo XML:</p>
<pre class="code">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"&gt;
    &lt;TextView
        android:id="@+id/label_a"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Operando A:"/&gt;
    &lt;EditText
        android:id="@+id/op_a"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@android:drawable/editbox_background"
        android:layout_below="@id/label_a"/&gt;
     &lt;TextView
        android:id="@+id/label_b"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/op_a"     
        android:text="Operando B:"/&gt;
    &lt;EditText
        android:id="@+id/op_b"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@android:drawable/editbox_background"
        android:layout_below="@id/label_b"/&gt;       
    &lt;Button
        android:id="@+id/sumar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/op_b"
        android:layout_alignParentLeft="true"
        android:layout_marginLeft="1dip"
		android:onClick="cSumar"        
        android:text="+" /&gt;
    &lt;Button
        android:id="@+id/restar"    
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/sumar"
        android:layout_alignTop="@id/sumar"
		android:onClick="cRestar"             
        android:text="-" /&gt;
    &lt;Button
        android:id="@+id/multiplicar"   
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/restar"
        android:layout_alignTop="@id/restar"
		android:onClick="cMultiplicar"            
        android:text="*" /&gt;
    &lt;Button
        android:id="@+id/dividir"    
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/multiplicar"
        android:layout_alignTop="@id/sumar"
 		android:onClick="cDividir" 
        android:text="/" /&gt;   
    &lt;TextView
        android:id="@+id/texto_resultado"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/dividir"                    
        android:text="Resultado:"/&gt;              
    &lt;TextView
        android:id="@+id/resultado"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/texto_resultado"          
        android:text="Realice operaci&oacute;n para obtener resultado"/&gt;                  
&lt;/RelativeLayout&gt;
</pre>
<p><span style="text-decoration: underline;">Los atributos relevantes para este ejemplo de cada elemento son</span>:</p>
<ul>
<li><em>android:id</em> identificador de cada objeto</li>
<li><em>android:layout_width</em> y <em>android:layout_height</em>, anchura y altura respectivamente</li>
<li><em>android:layout_below</em>: indica si el objeto est&aacute; debajo de otro</li>
<li><em>android:layout_toRightOf</em> y <em>android:layout_alignTop</em>: indican si est&aacute;n varios elementos en la misma fila sobre qu&eacute; objeto se coloca a su derecha y su posicionamiento en altura</li>
<li><em>android:text</em> es el texto por defecto en cada elemento</li>
<li><em>android:onClick</em> es el nombre del m&eacute;todo p&uacute;blico a ejecutar al pulsar ese bot&oacute;n. Este m&eacute;todo debe ser obligatoriamente p&uacute;blico y tener como par&aacute;metro de entrada la vista, ejemplo public void function cSumar(View view) { ... }.</li>
</ul>
<p>ahora vamos a programar el funcionamiento de los objetos descritos en el archivo de extensi&oacute;n java creado para el proyecto:</p>
<pre class="code php">package com.android.calculadora;

import android.app.Activity;
import android.os.Bundle;
import android.widget.*;
import android.view.*;

public class Calculadora extends Activity {
	
	// Instancias de objetos a usar
	private double valor_a, valor_b;
	private EditText op_a, op_b;
	private TextView resultado;
	
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        // Asignamos los objetos
        this.op_a = (EditText) findViewById(R.id.op_a);
        this.op_b = (EditText) findViewById(R.id.op_b);
        this.resultado = (TextView) findViewById(R.id.resultado);              
    }

    public void cSumar(View view) {
    	if(this.op_a.getText().toString().length() &gt; 0 &amp;&amp; this.op_b.getText().toString().length() &gt; 0) {
        	this.valor_a = Double.parseDouble(this.op_a.getText().toString());
        	this.valor_b = Double.parseDouble(this.op_b.getText().toString());    
        	this.resultado.setText(Double.toString((this.valor_a + this.valor_b)));    		
    	}
    }

    public void cRestar(View view) {
    	if(this.op_a.getText().toString().length() &gt; 0 &amp;&amp; this.op_b.getText().toString().length() &gt; 0) {
        	this.valor_a = Double.parseDouble(this.op_a.getText().toString());
        	this.valor_b = Double.parseDouble(this.op_b.getText().toString());    
        	this.resultado.setText(Double.toString((this.valor_a - this.valor_b)));    		
    	}
    }
    
    public void cMultiplicar(View view) {
    	if(this.op_a.getText().toString().length() &gt; 0 &amp;&amp; this.op_b.getText().toString().length() &gt; 0) {
        	this.valor_a = Double.parseDouble(this.op_a.getText().toString());
        	this.valor_b = Double.parseDouble(this.op_b.getText().toString());    
        	this.resultado.setText(Double.toString((this.valor_a * this.valor_b)));    		
    	}
    }
    
    public void cDividir(View view) {
    	if(this.op_a.getText().toString().length() &gt; 0 &amp;&amp; this.op_b.getText().toString().length() &gt; 0) {
        	this.valor_a = Double.parseDouble(this.op_a.getText().toString());
        	this.valor_b = Double.parseDouble(this.op_b.getText().toString());    
        	if(this.valor_b != 0) {
            	this.resultado.setText(Double.toString((this.valor_a / this.valor_b)));         		
        	}
        	else {
            	this.resultado.setText("Infinito");         		
        	}
    	}
    }       
}
</pre>
<p>El m&eacute;todo onCreate se ejecuta al crear la aplicaci&oacute;n y es donde asignamos los objetos declarados en el XML a objetos Java. Tras ello declaramos las funciones definidas en los atributos onClick de cada bot&oacute;n.</p>
<p>Por &uacute;ltimo nos quedar&iacute;a ejecutarlo y probar el funcionamiento.</p>
<h3>Conclusiones</h3>
<p>Como hemos dicho, este ejemplo de una calculadora es un ejemplo muy sencillo pero podemos ver que con un poco de c&oacute;digo y unas peque&ntilde;as nociones sobre Android SDK podemos sacar much&iacute;simo provecho de nuestros conocimientos sobre Java.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=58</wfw:commentRss>
			<slash:comments>59</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/programando-para-android-una-sencilla-aplicacion.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Como usar HTML 5</title>
			<link>http://www.imaginanet.com/blog/como-usar-html-5.html</link>
			<guid>http://www.imaginanet.com/blog/como-usar-html-5.html</guid>
			<comments>http://www.imaginanet.com/blog/como-usar-html-5.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon,  6 Sep 2010 13:34:43 +0100</pubDate>
					<category><![CDATA[HTML5]]></category>
					<description><![CDATA[Antes de empezar habr&iacute;a que aclarar que HTML5 sigue en estado de borrador y lo seguir&aacute; estando durante algunos a&ntilde;os m&aacute;s.
Vamos a comentar las novedades m&aacute;s importantes.&nbsp;
Algo b&aacute;sico es que HTML5 est&aacute; definido en base al DOM (la representaci&oacute;n  interna de una web con la...]]></description>
			<content:encoded><![CDATA[><p>Antes de empezar habr&iacute;a que aclarar que HTML5 sigue en estado de borrador y lo seguir&aacute; estando durante algunos a&ntilde;os m&aacute;s.</p>
<p>Vamos a comentar las novedades m&aacute;s importantes.&nbsp;</p>
<p>Algo b&aacute;sico es que HTML5 est&aacute; definido en base al DOM (la representaci&oacute;n  interna de una web con la que trabaja un navegador), dejando de lado la  representaci&oacute;n &ldquo;real&rdquo;, definiendo a la vez un est&aacute;ndar HTML y XHTML.</p>
<p><span style="font-size: 15px; font-weight: bold;">Mejor estructura</span></p>
<p>Hoy en d&iacute;a se abusa bastante del elemento div, que nos permite  estructurar una web en bloques. En HTML5 hay varios elementos que sirven  para estructurar mejor una p&aacute;gina web, estableciendo qu&eacute; es cada  secci&oacute;n, y reemplazando en muchas ocasiones a div. Con este extra de  sem&aacute;ntica, ser&aacute; mucho m&aacute;s coherente y f&aacute;cil de entender por otras  personas. Y lo que es m&aacute;s importante, ser&aacute; trivial de entender para una  m&aacute;quina, d&aacute;ndole m&aacute;s importancia a unas secciones y pudiendo jugar con  esos datos autom&aacute;ticamente. Estos son los elementos:</p>
<ul>
<li><strong>section</strong> representa una secci&oacute;n &ldquo;general&rdquo; dentro de  un documento o aplicaci&oacute;n, como un cap&iacute;tulo de un libro. Puede contener  subsecciones y si lo acompa&ntilde;amos de h1-h6 podemos estructurar mejor toda  la p&aacute;gina.</li>
<li><strong>article</strong> representa un contenido independiente en un  documento, el caso m&aacute;s claro son las entradas de un blog o las noticias  de un peri&oacute;dico online. As&iacute;, dentro de la portada podremos tener varios  art&iacute;culos demarcados sem&aacute;nticamente, por lo que una herramienta puede  extraerlos f&aacute;cilmente.</li>
<li><strong>aside</strong> representa un contenido que est&aacute; muy poco  relacionado con el resto de la p&aacute;gina, como una barra lateral. Esencial  para delimitar el contenido &ldquo;importante&rdquo; del contenido &ldquo;de apoyo&rdquo;,  haciendo m&aacute;s caso al primero que al segundo.</li>
<li><strong>header</strong> representa la cabecera de una secci&oacute;n, y es  de suponer que se le d&eacute; m&aacute;s importancia que al resto, sobre todo si la  secci&oacute;n es un art&iacute;culo.</li>
<li><strong>footer</strong> representa el pi&eacute; de una secci&oacute;n, con  informaci&oacute;n acerca de la p&aacute;gina/secci&oacute;n que poco tiene que ver con el  contenido de la p&aacute;gina, como el autor, el copyright o el a&ntilde;o.</li>
<li><strong>nav</strong> representa una secci&oacute;n dedicada a la navegaci&oacute;n entre el sitio, como la t&iacute;pica barra superior de los peri&oacute;dicos.</li>
</ul>
<p>&nbsp;</p>
<p><span style="font-size: 15px; font-weight: bold;"><img src="http://www.imaginanet.com/ftp/articulos_web/html-html5.gif" alt="de Html a Html5" width="540" height="540" /><br /></span></p>
<p><span style="font-size: 15px; font-weight: bold;"><br />Mejores formularios</span></p>
<p>El elemento <strong>input</strong> ha sido ampliado y ahora permite todos estos tipos de datos:</p>
<ul>
<li><strong>datetime, datetime-local, date, month, week, time</strong>, para que indicar una fecha/hora. </li>
<li><strong>number</strong> para que el usuario indique un n&uacute;mero. </li>
<li><strong>range</strong> para indicar un rango entre dos n&uacute;meros. </li>
<li><strong>email</strong> para indicar un correo electr&oacute;nico. </li>
<li><strong>url</strong> para indicar una direcci&oacute;n web. </li>
<li><strong>search</strong> para indicar una b&uacute;squeda. </li>
<li><strong>color</strong> para indicar un color.</li>
</ul>
<p>Lo m&aacute;s interesante de esto es que los navegadores podr&aacute;n implementar  interfaces espec&iacute;ficas para cada tipo de dato, por ejemplo una fecha o  un color se podr&aacute;n indicar de manera directa e intuitiva. Otro ejemplo  ser&iacute;a el teclado del iPhone, que muestra unos s&iacute;mbolos u otros  dependiendo de si es un texto normal, un email (a&ntilde;ade @ y el punto) o  una url (a&ntilde;ade la barra y el punto com), y que por tanto gana mucho con  este est&aacute;ndar.</p>
<h2>Otros elementos importantes</h2>
<ul>
<li><strong>audio</strong> y <strong>video</strong> sirven para  incrustar un contenido multimedia de sonido o de v&iacute;deo, respectivamente.  Sin duda uno de los a&ntilde;adidos m&aacute;s interesantes, ya que permite  reproducir/controlar v&iacute;deos y audios sin necesidad de plugins como el de  Flash. Se tratan de manera totalmente nativa como cualquier otro  elemento, por ejemplo se pueden incluir enlaces o im&aacute;genes dentro de un  v&iacute;deo. Aunque las implementaciones actuales son un tanto ineficientes,  se espera que en un futuro pr&oacute;ximo se optimicen. Portales de v&iacute;deo como <a href="http://www.youtube.com/html5">Youtube</a> o <a href="http://openvideo.dailymotion.com/es">Dailymotion</a> ya est&aacute;n empezando a mostrar que un futuro sin Flash es posible (&iexcl;y necesario!).</li>
<li><strong>embed</strong> sirve para contenido incrustado pero no  nativo, sino ejecutado por plugins como el de Flash. Aunque embed est&aacute;  soportado por casi todos los navegadores desde hace tiempo, es ahora  cuando entra parte del est&aacute;ndar y evita el infierno/pelea entre object y  embed.</li>
<li><strong>canvas</strong> es un elemento complejo que permite generar  gr&aacute;ficos, dibujando elementos dentro de &eacute;l. Aunque nunca hayas o&iacute;do  hablar de &eacute;l, seguro que lo has usado alguna vez, por ejemplo de Google  Maps. Es un elemento muy potente que dar&aacute; bastante que hablar en el  futuro, y que ser&aacute; el culpable de aplicaciones web espectaculares.</li>
</ul>
<h2>M&aacute;s elementos</h2>
<ul>
<li><strong>dialog</strong> se plantea para escribir conversaciones, por ejemplo para transcripciones de chat.</li>
<li><strong>figure</strong> se plantea para asociar un contenido multimedia (una foto, un v&iacute;deo, etc) a un t&iacute;tulo o leyenda.</li>
<li><strong>mark</strong> representa un texto resaltado, por ejemplo para resaltar una b&uacute;squeda.</li>
<li><strong>meter</strong> representa una medida, como el n&uacute;mero de KB. Tiene m&aacute;s sentido si lo unimos con&hellip;</li>
<li><strong>progress</strong> representa el estado de una tarea, y se  puede usar por ejemplo al subir un documento o al realizar varias tareas  pesadas. Esto permitir&aacute; barras de tareas personalizadas y potentes.</li>
<li><strong>time</strong> representa una fecha o una hora.</li>
<li><strong>command</strong> representa un comando que el usuario puede ejecutar en su navegador.</li>
<li><strong>output</strong> representa una salida de un programa, probablemente ejecutado directamente en el navegador, como una calculadora.</li>
<li><strong>datagrid</strong> representa datos de manera interactiva y  permite trabajar din&aacute;micamente con informaci&oacute;n y cambiar la p&aacute;gina  respecto a esa informaci&oacute;n. Ser&aacute; &uacute;til sobre todo si se quiere trabajar  con aplicaciones que necesiten de bastantes datos a la vez en el lado  del cliente.</li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=57</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/como-usar-html-5.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Google Chrome cumple 2 años y trae nuevas funcionalidades</title>
			<link>http://www.imaginanet.com/blog/google-chrome-cumple-2-anos-y-trae-nuevas-funcionalidades.html</link>
			<guid>http://www.imaginanet.com/blog/google-chrome-cumple-2-anos-y-trae-nuevas-funcionalidades.html</guid>
			<comments>http://www.imaginanet.com/blog/google-chrome-cumple-2-anos-y-trae-nuevas-funcionalidades.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon,  6 Sep 2010 10:07:23 +0100</pubDate>
					<category><![CDATA[Google]]></category>
					<category><![CDATA[Navegadores]]></category>
					<description><![CDATA[Gogle Chrome est&aacute; en su mejor momento, habiendo alcanzado una cuota de mercado record del 7,5% durante el mes de agosto.
Por otra parte Google ya trabaja en nuevas funcionalidades para 'tablets' y 'netbooks'.
Entre las &uacute;ltimas revisiones de Chrome, hay&nbsp;dos nuevas actualizaciones: control de orientaci&oacute;n y...]]></description>
			<content:encoded><![CDATA[><p>Gogle Chrome est&aacute; en su mejor momento, <strong>habiendo alcanzado una cuota de mercado record del 7,5% durante el mes de agosto.</strong></p>
<p>Por otra parte Google ya trabaja en nuevas funcionalidades para 'tablets' y 'netbooks'.</p>
<p>Entre las &uacute;ltimas revisiones de Chrome, <em>hay</em>&nbsp;dos nuevas actualizaciones: control de orientaci&oacute;n y comandos de voz.</p>
<span>
<p>La primera de estas novedades en Chrome se antoja necesaria si tenemos en cuenta la proliferaci&oacute;n de 'tablets' y  'netbooks' en los &uacute;ltimos tiempos y, tambi&eacute;n, ante el lanzamiento (en  diciembre) de la versi&oacute;n de Chrome que Google desarrolla para estos dispositivos.</p>
<p>Ambas caracter&iacute;sticas ya estaban incluidas en el c&oacute;digo de Chromium,  pero el hecho de que est&eacute;n activadas por defecto hace pensar que pronto  estar&aacute;n disponibles en el navegador de Google.</p>
<p>Ante la importante actualizaci&oacute;n de sus grandes competidores: Firefox (con la llegada de la versi&oacute;n 4) e Internet Explorer (con su versi&oacute;n 9), Google sigue afinando y completando su sistema  operativo y no s&oacute;lo pensando en los equipos de sobremesa. De hecho, el  control de orientaci&oacute;n es algo obligado desde la proliferaci&oacute;n de  dispositivos m&oacute;viles como 'tablets' y 'netbooks'.</p>
<p><strong>Chrome&nbsp;contar&aacute; en su versi&oacute;n '7' con una aceleraci&oacute;n por hardware superior a Explorer 9 y Firefox 4</strong>, pero consumiendo m&aacute;s recursos que estos.</p>
</span>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=55</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/google-chrome-cumple-2-anos-y-trae-nuevas-funcionalidades.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Debate sobre plataformas móviles</title>
			<link>http://www.imaginanet.com/blog/debate-sobre-plataformas-moviles.html</link>
			<guid>http://www.imaginanet.com/blog/debate-sobre-plataformas-moviles.html</guid>
			<comments>http://www.imaginanet.com/blog/debate-sobre-plataformas-moviles.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon,  6 Sep 2010 12:30:29 +0100</pubDate>
					<category><![CDATA[Accesibilidad]]></category>
					<description><![CDATA[Representantes de los distintos sistemas operativos m&oacute;viles se  dieron cita en el evento Tendencias en Plataformas y Desarrollo M&oacute;vil,  organizado por Aecomo, para evaluar las posibilidades de cada uno en el  mercado y las tendencias futuras. El debate lo centraron iPhone y  Android.
Aecomo reuni&oacute; a...]]></description>
			<content:encoded><![CDATA[><p><strong>Representantes de los distintos sistemas operativos m&oacute;viles se  dieron cita en el evento Tendencias en Plataformas y Desarrollo M&oacute;vil,  organizado por Aecomo, para evaluar las posibilidades de cada uno en el  mercado y las tendencias futuras. El debate lo centraron iPhone y  Android.</strong></p>
<p><strong>Aecomo </strong>reuni&oacute; a desarrolladores y representantes de las empresas en el evento <strong>Tendencias en Plataformas y Desarrollo M&oacute;vil</strong>, para que&nbsp; expresaran sus puntos de vista sobre las posibilidades que ofrece el mercado.</p>
<p>El crecimiento experimentado por la programaci&oacute;n de aplicaciones  m&oacute;viles en los &uacute;ltimos tiempos ha sido vertiginoso y ha hecho que muchas  compa&ntilde;&iacute;as se sumen al negocio de construir su propia tienda o mercado.  Las conferencias dieron voz a los distintos actores presentes en el  mercado.</p>
<p><strong>Apple y sus buenas condiciones de trabajo</strong></p>
<p>El valedor de <strong>Apple </strong>fue <strong>Juan Antonio Mu&ntilde;oz-Gallego, socio fundador de Unkasoft</strong>, que justifica su trabajo sobre <strong>iPhone </strong>en la remuneraci&oacute;n econ&oacute;mica. Seg&uacute;n afirma el desarrollador, <strong>la compa&ntilde;&iacute;a paga un 70% de los beneficios que genere la aplicaci&oacute;n a su creador y lo hace en menos de treinta d&iacute;as</strong>.</p>
<div id="attachment_6905" class="wp-caption alignright">
<p class="wp-caption-text">Los smartphone pasan por ser el futuro de la telefon&iacute;a m&oacute;vil</p>
</div>
<p>La <strong>App Store</strong> <strong>ya ha obtenido 1.500 millones de descargas</strong>,  seg&uacute;n los datos de Mu&ntilde;oz-Gallego. Con esto pone de relevancia la  calidad del escaparate que Apple es capaz de ofrecer a los  programadores. Sin embargo, las apps m&oacute;viles m&aacute;s utilizadas son siempre  las mismas: <strong>Google Maps</strong>,<strong> Facebook</strong> y la herramienta musical <strong>Pandora</strong>.</p>
<p>En estos momentos, con el <strong>iPad </strong>ya  en la calle y arropado por un gran &eacute;xito en ventas, los desarrolladores  tienen la oportunidad o la obligaci&oacute;n, seg&uacute;n como se mire, de crear  aplicaciones duales, adaptadas a ambos dispositivos.</p>
<p>Mu&ntilde;oz-Gallego presenta la App Store de Apple como un buen escenario  para potenciar el comercio a trav&eacute;s del m&oacute;vil. Algunas compa&ntilde;&iacute;as ya han  aprovechado en este sentido las capacidades de las distintas versiones  del sistema operativo de iPhone, como <strong>Ikea, que lanz&oacute; un cat&aacute;logo virtual</strong>, permitiendo al usuario comprobar c&oacute;mo quedar&iacute;an sus productos en el lugar que vean con la c&aacute;mara del dispositivo.</p>
<p><strong>Android: innovaci&oacute;n m&aacute;s que dinero</strong></p>
<p>Tendencias en Plataformas y Desarrollo M&oacute;vil trajo a <strong>Israel Ferrer</strong>, <strong>desarrollador de Android y fundador del blog and.roid.es</strong>,  el m&aacute;s importante acerca de este sistema operativo en Espa&ntilde;a, que  ofreci&oacute; datos sobre el gran crecimiento del SO de Google en los &uacute;ltimos  meses.</p>
<p>Durante la charla, Ferrer profundiz&oacute; en la estrategia de Google, afirmando que <strong>al buscador le interesa principalmente la publicidad y el software para monopolizar este sector</strong>.  Por tanto, nada de terminales de momento. Para compensar, Android tiene  una larga lista de dispositivos que lo utilizan como sistema, por lo  que <strong>los desarrolladores deben ajustarse a distinto hardware, as&iacute; como diferentes tama&ntilde;os de pantalla y resoluciones</strong>.</p>
<p>Sin embargo, Android dispone de herramientas para solventar estas  dificultades, seg&uacute;n Ferrer, que aludi&oacute; a la versi&oacute;n 1.6 como una de las  m&aacute;s adecuadas para trabajar.</p>
<p>Respecto a las otra plataformas, Ferrer dijo: <strong>&ldquo;Google piensa que s&oacute;lo tiene dos competidores: iPhone y Blackberry&rdquo;</strong>.  Tambi&eacute;n hizo referencia a la posibilidad de convivencia de varias  tiendas de apps, como el Android Market, que permite la presencia de  otros competidores.</p>
<p>La confrontaci&oacute;n con Apple no se hizo esperar. En este punto, Israel Ferrer afirm&oacute;: &ldquo;<strong>La innovaci&oacute;n est&aacute; en Android&rdquo;</strong>, y se dirigi&oacute; a los desarrolladores diciendo que para ganar dinero &ldquo;iros a iPhone&rdquo;.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=56</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/debate-sobre-plataformas-moviles.html</feedburner:origLink>
		</item>
				
		<item>
			<title>YouTube: Editor onLine de videos</title>
			<link>http://www.imaginanet.com/blog/youtube-editor-online-de-videos.html</link>
			<guid>http://www.imaginanet.com/blog/youtube-editor-online-de-videos.html</guid>
			<comments>http://www.imaginanet.com/blog/youtube-editor-online-de-videos.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Fri, 18 Jun 2010 10:16:24 +0100</pubDate>
					<category><![CDATA[Google Apps]]></category>
					<category><![CDATA[Google]]></category>
					<category><![CDATA[Web 2.0]]></category>
					<description><![CDATA[Cuando Apple acaba de anunciar una aplicaci&oacute;n para la edici&oacute;n onLine de videos, YouTube se ha adelantado y acaba de lanzar su editor de v&iacute;deo desde su web, as&iacute;, los usuarios ya no necesitan tener un programa de edici&oacute;n de v&iacute;deos que adem&aacute;s suele ser complicado de aprender a usar. El...]]></description>
			<content:encoded><![CDATA[>Cuando Apple acaba de anunciar una <a title="Ver post original" href="http://googleblog.blogspot.com/2010/06/edit-video-online-with-youtube-video.html" target="_blank">aplicaci&oacute;n para la edici&oacute;n onLine de videos</a>, YouTube se ha adelantado y acaba de lanzar su editor de v&iacute;deo desde su web, as&iacute;, los usuarios ya no necesitan tener un programa de edici&oacute;n de v&iacute;deos que adem&aacute;s suele ser complicado de aprender a usar. El editor online de YouTube es muy f&aacute;cil y sencillo de utilizar, y permite:<br />Crear un v&iacute;deo a partir de varios<br />Modificar el principio y fin del v&iacute;deo<br />Incluir m&uacute;sica en el v&iacute;deo desde AudioSwap<br />Despreocuparse de formatos cuando se crean v&iacute;deos nuevos.<br /><br />En <a title="Ver v&iacute;deo demo" href="http://www.youtube.com/watch?v=4YsQ6f125GY" target="_blank">este v&iacute;deo</a> se puede ver una demostraci&oacute;n de edici&oacute;n de un v&iacute;deo con esta aplicaci&oacute;n.<br /><br /><br />Google vs. Apple. &iexcl;Esto es competencia!]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=54</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/youtube-editor-online-de-videos.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Diseñando o re-diseñando tu página web a web 2.0</title>
			<link>http://www.imaginanet.com/blog/disenando-o-re-disenando-tu-pagina-web-a-web-20.html</link>
			<guid>http://www.imaginanet.com/blog/disenando-o-re-disenando-tu-pagina-web-a-web-20.html</guid>
			<comments>http://www.imaginanet.com/blog/disenando-o-re-disenando-tu-pagina-web-a-web-20.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Sat, 29 May 2010 10:21:30 +0100</pubDate>
					<category><![CDATA[Redes Sociales]]></category>
					<category><![CDATA[Marketing OnLine]]></category>
					<category><![CDATA[HTML5]]></category>
					<category><![CDATA[Accesibilidad]]></category>
					<category><![CDATA[Web 2.0]]></category>
					<description><![CDATA[&iquest;Has o&iacute;do hablar de web 2.0? Quien no! Est&aacute; de moda en internet hablar de web 2.0, aunque mucha gente no sabe muy bien lo qu&eacute; es.Todo el mundo habla sobre Web 2.0, pero mucha gente puede pensar que es una estrategia de marketing y un t&eacute;rmino cada vez m&aacute;s utilizado y est&aacute; siendo...]]></description>
			<content:encoded><![CDATA[><strong>&iquest;Has o&iacute;do hablar de web 2.0? </strong>Quien no! Est&aacute; de moda en internet hablar de web 2.0, aunque mucha gente no sabe muy bien lo qu&eacute; es.<br />Todo el mundo habla sobre Web 2.0, pero mucha gente puede pensar que es una estrategia de marketing y un t&eacute;rmino cada vez m&aacute;s utilizado y est&aacute; siendo sobre-utilizado.<br /><br />A pesar de todo lo que se est&aacute; hablando, hay otro cap&iacute;tulo sobre web 2.0, que al margen de la publicidad que se le est&aacute; dando y todo el marketing que rodea el t&eacute;rmino, es mucho m&aacute;s potente que todo eso.<br /><br />El concepto <strong>Web 2.0</strong> comenz&oacute; en una sesi&oacute;n de tormenta de ideas (brainstorming) que se llev&oacute; a cabo entre O'Reilly y MediaLive Int. En ella, analizaron las empresas web que hab&iacute;an sobrevivido a la quiebra que hubo de las punto com. En la sesi&oacute;n, analizaron a las empresas que hab&iacute;an sobrevivido a este breakdown. La conclusi&oacute;n que obtuvieron fue bastante interesante, la mayor&iacute;a de estas empresas ten&iacute;an muy pocas cosas en com&uacute;n. &iquest;Hab&iacute;a alguna conexi&oacute;n entre ellas? &iquest;Era esa quiebra un punto de inflexi&oacute;n para la web? O'Reilly y MediaLive cre&iacute;an que s&iacute;. Y entonces se les ocurri&oacute; el t&eacute;rmino Web 2.0<br /><br /><strong>Entonces, &iquest;Qu&eacute; es Web 2.0?</strong><br />En la wikipedia lo definen como una serie de servicios disponibles en internet de segunda generaci&oacute;n que permite la colaboraci&oacute;n entre los usuarios y compartir informaci&oacute;n online. Al contrario que la web de primera generaci&oacute;n, Web 2.0 le da al usuario una experiencia mucho m&aacute;s parecida a la de una aplicaci&oacute;n o programa de escritorio, que a la p&aacute;gina web est&aacute;tica t&iacute;pica de hace a&ntilde;os. Las aplicaciones o webs Web 2.0, suelen utilizar tecnolog&iacute;as o t&eacute;cnicas de programaci&oacute;n que aparecieron a final de los 90, web services APIs (1998), Ajax (1998) y web syndication (1997). Permiten con frecuencia el env&iacute;o masivo de mensajes a sectores o perfiles de usuarios (web social applications). El concepto en s&iacute;, puede englobar el concepto de "blogs" y de "wikis".<br /><br />No existe ninguna definici&oacute;n oficial que defina lo qu&eacute; es "Web 2.0", pero s&iacute; que hay una serie de cosas que todos los que utilizan este emblema tienen en com&uacute;n. Puedes visitar Flickr, del.icious, Wikipedia, Amazon (reviews - opiniones), y el sistema de reputaci&oacute;n de eBay, son sitios conocidos que nacieron con la web 2.0<br /><br />Web 2.0 es algo constru&iacute;do sobre un conocimiento colectivo. Proporciona una herramienta social aplicada a la web, dando m&aacute;s herramientas y conocimiento al usuario y d&aacute;ndoles la oportunidad de poder opinar libremente. Adem&aacute;s, hay que fijarse en que cada vez aparecen m&aacute;s aplicaciones web como hojas de c&aacute;lculo, procesadores de texto, listas de tareas, alertas, calendarios, p&aacute;ginas personales, blogs, comunidades, redes sociales, etc.<br /><br />Adem&aacute;s, la web 2.0 no utiliza la maquetaci&oacute;n cuadriculada de las tablas y sus renderizados. Los dise&ntilde;os web 2.0 han cambiado de las t&iacute;picas cajas cuadriculadas a la flexibilidad de las curvas, dise&ntilde;ar para la web de hoy permite dise&ntilde;os curvos y con movimiento, textos bonitos, gradientes, efectos chulis que parecen flash, y colores bonitos y agradables.<br /><br /><em>Esquinas redondeadas</em><br />Antes era bastante necesario el uso de cajas cuadriculadas, la web 2.0 ha aportado las esquinas redondeadas como algo b&aacute;sico y simple de realizar. Con la web anterior, crear una caja con esquinas redondeadas era una odisea de recorte de im&aacute;genes y posicionado de estas y no era tareal trivial.<br /><br /><em>Titulares que funcionan</em><br />La web 2.0 ha estandarizado el uso de titulares para resaltar los textos de importancia.<br /><br /><em>Gradientes</em><br />Oto elemento de dise&ntilde;o bastante usado en web 2.0 son los gradientes. Sobre todo es util en fondos, por ejemplo podemos tener un gradiente en la cabecera que acabe en un color utilizado como fondo de toda la p&aacute;gina web (ejemplo: http://www.photoshoplab.com/web20-design-kit.html)<br /><br />Y otras propiedades de dise&ntilde;o como <em>colores luminosos, pesta&ntilde;as, reflejos, efectos de movimiento, botones, iconos, y cajas de texto claras para el env&iacute;o de formularios</em>. Otro elemento que se utiliza mucho son las <em>nubes de tags</em>, en los &uacute;ltimos 6 meses se est&aacute;n poniendo de moda. Sitios que las usan son del.icio.us, Technorati, Flickr, ... Una nube de tags te da una idea abstracta de los temas que encontrar&aacute;s en un website, donde lo m&aacute;s popular, aparece a tama&ntilde;o mayor. Una nube de tags (tambi&eacute;n conocida como folkloromies), adem&aacute;s de ser algo moderno y de moda, le da al usuario una herramienta de b&uacute;squeda de contenidos muy f&aacute;cil, r&aacute;pida e intuitiva.<br /><br />Aunque hemos enumerado varias cosas de web 2.0, esta no es una tecnolog&iacute;a, tampoco es una nueva t&eacute;cnica de dise&ntilde;o, lo que realmente es una transici&oacute;n de la web, una transici&oacute;n hacia la experiencia de usuario, la web est&aacute; hecha para el usuario, y para ello utiliza t&eacute;cnicas de dise&ntilde;o y programaci&oacute;n soportadas desde finales de los 90.<br /><br />Tu web puede ser algo m&aacute;s que un lugar informativo. Tu presencia en la web es un lugar m&aacute;s, que con las t&eacute;cnicas de programaci&oacute;n adecuadas puedes montar todo un mundo alrededor de tu negocio<br /><br />En Imaginanet ofrecemos servicios de programaci&oacute;n y dise&ntilde;o web 2.0, si te interesa, visita nuestra secci&oacute;n de <a title="Qu&eacute; te ofrecemos de dise&ntilde;o web 2.0" href="/diseno-web.html">dise&ntilde;o web 2.0</a> para conocer qu&eacute; podemos ofrecerte en cuanto a dise&ntilde;o, o la de programaci&oacute;n web 2.0 si te interesa un desarrollo bien hecho.<br /><br /><br />]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=53</wfw:commentRss>
			<slash:comments>1</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/disenando-o-re-disenando-tu-pagina-web-a-web-20.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Google y Twitter hacen pública su política publicitaria</title>
			<link>http://www.imaginanet.com/blog/google-y-twitter-hacen-publica-su-politica-publicitaria.html</link>
			<guid>http://www.imaginanet.com/blog/google-y-twitter-hacen-publica-su-politica-publicitaria.html</guid>
			<comments>http://www.imaginanet.com/blog/google-y-twitter-hacen-publica-su-politica-publicitaria.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Fri, 28 May 2010 23:34:28 +0100</pubDate>
					<category><![CDATA[Redes Sociales]]></category>
					<category><![CDATA[Marketing OnLine]]></category>
					<category><![CDATA[Google]]></category>
					<description><![CDATA[En la misma semana, estas dos empresas de internet han hecho p&uacute;blica su pol&iacute;tica publicitaria&nbsp;online.Google en su blog hace p&uacute;blico por primera vez, las comisiones que reciben los due&ntilde;os de websites con AdSense. El 68% de los ingresos generados se entregan a los propietarios de websites.Twitter por...]]></description>
			<content:encoded><![CDATA[><p>En la misma semana, estas dos empresas de internet han hecho p&uacute;blica su pol&iacute;tica publicitaria&nbsp;online.<br /><br />Google en su blog hace p&uacute;blico por primera vez, las comisiones que reciben los due&ntilde;os de websites con AdSense. El 68% de los ingresos generados se entregan a los propietarios de websites.<br /><br />Twitter por otra parte ha anunciado que controlar&aacute; m&aacute;s la publicidad e impedir&aacute; que terceros vendan tweets publicitarios gestionados por Twitter, seg&uacute;n anuncian "no permitir&aacute;n inyectar mensajes remunerados en flujos de mensajes de su red social". Toman esta medida por el engorro que puede suponer el aumento descontrolado de publicidad mal gestionada.&nbsp;</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=50</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/google-y-twitter-hacen-publica-su-politica-publicitaria.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Datos de usuarios de Twitter</title>
			<link>http://www.imaginanet.com/blog/datos-de-usuarios-de-twitter.html</link>
			<guid>http://www.imaginanet.com/blog/datos-de-usuarios-de-twitter.html</guid>
			<comments>http://www.imaginanet.com/blog/datos-de-usuarios-de-twitter.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Sat, 29 May 2010 00:06:40 +0100</pubDate>
					<category><![CDATA[Redes Sociales]]></category>
					<category><![CDATA[Marketing OnLine]]></category>
					<description><![CDATA[Las cifras de uso de Twitter a nivel mundial, o en ingl&eacute;s, son impresionantes. No lo son tanto en espa&ntilde;ol.Hoy existen 106 millones de usuarios, que env&iacute;an 55 millones de tweets al dia. Sale a 640 tweets por segundo.Diariamente, se captan 300.000 usuarios nuevos. Y diariamente acceden 180 millones de visitantes...]]></description>
			<content:encoded><![CDATA[>Las cifras de uso de Twitter a nivel mundial, o en ingl&eacute;s, son impresionantes. No lo son tanto en espa&ntilde;ol.<br /><br />Hoy existen 106 millones de usuarios, que env&iacute;an 55 millones de tweets al dia. Sale a 640 tweets por segundo.<br />Diariamente, se captan 300.000 usuarios nuevos. Y diariamente acceden 180 millones de visitantes &uacute;nicos.<br /><br />Hay que tener en cuenta que los mensajes (tweets) se encuentran limitados a 140 caracteres. Los tweets tiene que ser muy cortos y condensados. Cuando hablamos de caracteres hay que contar letras, signos de puntuaci&oacute;n y espacios.<br /><br />El Instituto Max Planck de Alemania, hizo un examen de la actividad en Twitter de una muestra aleatoria de 300.000 usuarios para investigar c&oacute;mo los usuarios usan el servicio, ya que se sabe que el servicio llama mucho la atenci&oacute;n de medios y celebridades, pero no se saben sus efectos &iquest;lo usan los amigos para comunicarse? &iquest;se usa como medio de expresi&oacute;n libre? &iquest;herramienta de marketing online?<br /><br />Los resultados sugieren que el n&uacute;mero de seguidores no tiene relaci&oacute;n con lo que se influye sobre ellos. Es decir, parece no muy rentable el dinero que pagan algunas empresas por conseguir seguidores. El tener muchos seguidores en Twitter significa muy poco. As&iacute; que el presidente de Venezuela que busca el mill&oacute;n de seguidores, tendr&aacute; poca influencia sobre ellos.<br /><br />Existe poca interactividad. Se debe poner m&aacute;s &eacute;nfasis en aumentar la capacidad de respuesta de la audiencia en los Twitter. Hay mucha comunicaci&oacute;n de una &uacute;nica v&iacute;a. Aunque tambi&eacute;n se expone que las empresas que publican noticias han encontrado un gran aliado en Twitter para enlazar a sus noticias comentarios o tweets.<br /><br />Existen pocos twitters activos realmente. &nbsp;Se usa mucho para buscar y leer mensajes de otros, pero poco para generar nuevos. S&oacute;lo el 3% de los twitters tienen m&aacute;s de 100 seguidores. El 24% de los twitters tiene 0 seguidores.<br /><br />Por sexos, un 45% son hombres y el 55% mujeres, aunque los hombres tienen un 15% m&aacute;s seguidores que ellas.<br /><br />El lenguaje m&aacute;s usado es el ingl&eacute;s, el 61% de los usuarios son de habla inglesa, y s&oacute;lo el 4% son en idioma espa&ntilde;ol.<br />Pa&iacute;ses desde donde m&aacute;s se usa: USA el 33%, seguido de India, Alemania, Jap&oacute;n y Reino Unido. De latinoam&eacute;rica es muy popular en Brasil.<br /><br /><br /><br />&nbsp;]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=52</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/datos-de-usuarios-de-twitter.html</feedburner:origLink>
		</item>
				
		<item>
			<title>FaceBook llega a los 10 millones de usuarios en España</title>
			<link>http://www.imaginanet.com/blog/facebook-llega-a-los-10-millones-de-usuarios-en-espana.html</link>
			<guid>http://www.imaginanet.com/blog/facebook-llega-a-los-10-millones-de-usuarios-en-espana.html</guid>
			<comments>http://www.imaginanet.com/blog/facebook-llega-a-los-10-millones-de-usuarios-en-espana.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Fri, 28 May 2010 23:45:19 +0100</pubDate>
					<category><![CDATA[Redes Sociales]]></category>
					<category><![CDATA[Marketing OnLine]]></category>
					<description><![CDATA[FaceBook ha hecho p&uacute;blico que sobrepasa los 10 millones de usuarios en Espa&ntilde;a, usuarios registrados y que acceden a su cuenta con frecuencia.FaceBook naci&oacute; en 2004, y a d&iacute;a de hoy, una cuarta parte de la poblaci&oacute;n espa&ntilde;ola est&aacute; registrada en FaceBook, y el 70% de estos, se conecta...]]></description>
			<content:encoded><![CDATA[>FaceBook ha hecho p&uacute;blico que sobrepasa los 10 millones de usuarios en Espa&ntilde;a, usuarios registrados y que acceden a su cuenta con frecuencia.<br /><br />FaceBook naci&oacute; en 2004, y a d&iacute;a de hoy, una cuarta parte de la poblaci&oacute;n espa&ntilde;ola est&aacute; registrada en FaceBook, y el 70% de estos, se conecta todos los d&iacute;as. As&iacute; Espa&ntilde;a se pone en la d&eacute;cima plaza a nivel muncial en n&uacute;mero de usuarios activos.&nbsp;<br /><br />Si a esto se a&ntilde;ade que FaceBook tiene 62'3 millones de usuarios en espa&ntilde;ol a nivel mundial, lo convierte en una red para la difusi&oacute;n de mensajes muy atractiva en nuestro idioma.&nbsp;]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=51</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/facebook-llega-a-los-10-millones-de-usuarios-en-espana.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Internet TV. Alianza de Google con Sony  e Intel.</title>
			<link>http://www.imaginanet.com/blog/internet-tv-alianza-de-google-con-sony-e-intel.html</link>
			<guid>http://www.imaginanet.com/blog/internet-tv-alianza-de-google-con-sony-e-intel.html</guid>
			<comments>http://www.imaginanet.com/blog/internet-tv-alianza-de-google-con-sony-e-intel.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue, 18 May 2010 13:08:13 +0100</pubDate>
					<category><![CDATA[Internet]]></category>
					<category><![CDATA[Google Apps]]></category>
					<category><![CDATA[Google]]></category>
					<description><![CDATA[Seg&uacute;n una encuesta realizada por Intel a nivel mundial, el electrodom&eacute;stico que m&aacute;s desear&iacute;an tener los ciudadanos es un cable que conecte internet con su televisor. El mi&eacute;rcoles 19 de mayo Google lo presenta en San Francisco. Si algui&eacute;n piensa que la TDT ha tra&iacute;do lo m&aacute;s...]]></description>
			<content:encoded><![CDATA[>Seg&uacute;n una encuesta realizada por Intel a nivel mundial, el electrodom&eacute;stico que m&aacute;s desear&iacute;an tener los ciudadanos es un cable que conecte internet con su televisor. El mi&eacute;rcoles 19 de mayo Google lo presenta en San Francisco. Si algui&eacute;n piensa que la TDT ha tra&iacute;do lo m&aacute;s moderno, la TDT ha sido un adelanto, el futuro est&aacute; en un sistema abierto que ha desarrollado Google que instala internet dentro del televisor y dentro del mismo mando a distancia. Sea cual sea el modelo y marca de estos.<br /><br />Intel ha proporcionado los chips y las televisiones con las que se ha desarrollado son de Sony, aunque se prevee que se pueda instalar en todas las marcas del sector. No se sabe todav&iacute;a si GoogleTV o SmartTV proporcionar&aacute; acceso a todo internet o s&oacute;lo a sus webs como YouTube, Gmail, Picasa, Chrome, Buzz, ...<br /><br />Hace un a&ntilde;o que se venden televisiones con programas que incluyen servicios de Yahoo! como el tiempo o la bolsa. El objetivo de Google es inclu&iacute;r internet en el televisor, y si lo logra "La televisi&oacute;n como concepto va a desaparecer; quedar&aacute; el televisor aunque al fin y al cabo es una pantalla".<br /><br />Siempre se ha dicho que el ordenador nunca ganar&iacute;a al televisor, porque el sof&aacute; es m&aacute;s c&oacute;modo que la silla, pero parece que todo llega. Ahora hay que hacer apuestas por el mando del televisor, y el que tiene todos los boletos es el tel&eacute;fono m&oacute;vil. La aplicaci&oacute;n m&aacute;s descargada en Espa&ntilde;a para iPhone es para ver la televisi&oacute;n de catalu&ntilde;a en directo.<br /><br />La competencia en la TV tiene dos nuevos competidores a nivel mundial: Apple y Google.]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=49</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/internet-tv-alianza-de-google-con-sony-e-intel.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Rediseño web 2.0 para dispositivos móviles táctiles</title>
			<link>http://www.imaginanet.com/blog/rediseno-web-20-para-dispositivos-moviles-tactiles.html</link>
			<guid>http://www.imaginanet.com/blog/rediseno-web-20-para-dispositivos-moviles-tactiles.html</guid>
			<comments>http://www.imaginanet.com/blog/rediseno-web-20-para-dispositivos-moviles-tactiles.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue, 18 May 2010 12:49:05 +0100</pubDate>
					<category><![CDATA[Internet]]></category>
					<category><![CDATA[HTML5]]></category>
					<category><![CDATA[Accesibilidad]]></category>
					<category><![CDATA[Web 2.0]]></category>
					<description><![CDATA[Desde el lanzamiento del iPhone, y reforzado por el nuevo iPad, los fabricantes de dispositivos m&oacute;viles se han inclinado por las pantallas t&aacute;ctiles (multitouch interfaces) y ahora parece llegar a los dispositivos de escritorio como el iPad. Este nuevo entorno de navegaci&oacute;n, hace que el dise&ntilde;o web se...]]></description>
			<content:encoded><![CDATA[>Desde el lanzamiento del iPhone, y reforzado por el nuevo iPad, los fabricantes de dispositivos m&oacute;viles se han inclinado por las pantallas t&aacute;ctiles (multitouch interfaces) y ahora parece llegar a los dispositivos de escritorio como el iPad. Este nuevo entorno de navegaci&oacute;n, hace que el dise&ntilde;o web se piense tambi&eacute;n para estos dispositivos, ya que aunque no lo parezca, la revoluci&oacute;n est&aacute; aqu&iacute;.<br /><br />Steve Jobs dijo que Flash no sirve para los dispositivos t&aacute;ctiles, hay otras facetas de la web que hay que modificar para poder dar un buen soporte a este tipo de aparatos.<br />Raju Vegesna, comenta que estos dispositivos est&aacute;n pidiendo un cambio en la forma de usar los ordenadores, llevamos 20 a&ntilde;os con la misma interface. Los men&uacute;s desplegables son muy f&aacute;ciles de usar en dispositivos tradicionales pero no pasa lo mismo con las pantallas t&aacute;ctiles. Distintos toques en la pantalla t&aacute;ctil no se reconocen com debieran, ya que los servicios web actuales, la mayor&iacute;a de ellos, no est&aacute;n concebidos para la navegaci&oacute;n t&aacute;ctil.<br /><br />As&iacute;, surge una necesidad bastante aconsejable: las aplicaciones web y servicios web se tienen que redise&ntilde;ar para adaptarse tambi&eacute;n a esta forma de navegaci&oacute;n, o deben crearse formas alternativas de navegaci&oacute;n pensadas para estos dispositivos.<br /><br /><a href="http://www.technologyreview.com/computing/25236/?nlid=2950&amp;a=f" target="_blank">Ver noticia original en ingl&eacute;s</a>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=48</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/rediseno-web-20-para-dispositivos-moviles-tactiles.html</feedburner:origLink>
		</item>
				
		<item>
			<title>El número de usuarios de Internet en España sigue aumentando</title>
			<link>http://www.imaginanet.com/blog/el-numero-de-usuarios-de-internet-en-espana-sigue-aumentando.html</link>
			<guid>http://www.imaginanet.com/blog/el-numero-de-usuarios-de-internet-en-espana-sigue-aumentando.html</guid>
			<comments>http://www.imaginanet.com/blog/el-numero-de-usuarios-de-internet-en-espana-sigue-aumentando.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 17 May 2010 18:04:25 +0100</pubDate>
					<category><![CDATA[Internet]]></category>
					<category><![CDATA[Redes Sociales]]></category>
					<category><![CDATA[Marketing OnLine]]></category>
					<description><![CDATA[Seg&uacute;n un estudio de Internet World Stats, Espa&ntilde;a es el sexto usuario de internet en Europa y el d&eacute;cimo cuarto puesto a nivel mundial. Las comunidades donde m&aacute;s usuarios existen son Madrid, Catalu&ntilde;a y Pa&iacute;s Vasco, mientras que Murcia y Extremadura son las que menos usuarios tienen.El...]]></description>
			<content:encoded><![CDATA[><p>Seg&uacute;n un estudio de Internet World Stats, Espa&ntilde;a es el sexto usuario de internet en Europa y el d&eacute;cimo cuarto puesto a nivel mundial. Las comunidades donde m&aacute;s usuarios existen son Madrid, Catalu&ntilde;a y Pa&iacute;s Vasco, mientras que Murcia y Extremadura son las que menos usuarios tienen.<br /><br />El &iacute;ndice de penetraci&oacute;n de internet en la poblaci&oacute;n espa&ntilde;ola es del 72% (en el ranking mundial el puesto ocupado ser&iacute;a el 20) y tiene un crecimiento medio del 440% desde el a&ntilde;o 2000.<br /><br />En el ranking de uso de redes sociales, Espa&ntilde;a ocupa el s&eacute;ptimo puesto a nivel mundial, el 80% de los usuarios est&aacute; en una red social y el 60% consulta estas todos los d&iacute;as.&nbsp;<br /><br />En el informe se recoge que los &iacute;ndices de penetraci&oacute;n a destacar son: Madrid (58%), Catalu&ntilde;a (57%) y Pa&iacute;s Vasco (55%). Mientras que las comunidades con menor &iacute;ndice son Murcia (39%) y Extremadura (36%), estas dos &uacute;ltimas seg&uacute;n el informe, son las que menor crecimiento han tenido en los &uacute;ltimos a&ntilde;os.<br /><br /><strong>Perfil de usuario de internet en Espa&ntilde;a</strong><br />Un 55% son hombres y un 45% mujeres. Una cuarta parte est&aacute; entre los 14 y 24 a&ntilde;os, otra entre 25 y 34 a&ntilde;os, otra entre 35 y 44 a&ntilde;os y el &uacute;ltimo grupo es de m&aacute;s de 45 a&ntilde;os. El perfil de usuario que m&aacute;s ha crecido es el de m&aacute;s de 55 a&ntilde;os.<br />Adem&aacute;s, se informa de que el perfil social del usuario de la web es m&aacute;s alto que el de la poblaci&oacute;n general.<br /><br /><strong>Las redes sociales m&aacute;s populares en Espa&ntilde;a: FaceBook, Tuenti y Twitter.</strong><br />FaceBook con 7.900.000 usuarios es la m&aacute;s importante, seguida de Tuenti con 7 millones y Twitter. En el informe se comenta que las empresas que utilizan redes sociales superan en beneficios e ingresos a la competencia.<br /><br />Si a esto le a&ntilde;adimos que un 30% de los usuarios que utiliza redes sociales recuerda la publicidad de estas, el 52% se convierte en fan de una marca y el 46% habla bien de una marca.&nbsp;</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=47</wfw:commentRss>
			<slash:comments>2</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/el-numero-de-usuarios-de-internet-en-espana-sigue-aumentando.html</feedburner:origLink>
		</item>
				
		<item>
			<title>GobolNet, la red social de los municipios españoles</title>
			<link>http://www.imaginanet.com/blog/gobolnet-la-red-social-de-los-municipios-espanoles.html</link>
			<guid>http://www.imaginanet.com/blog/gobolnet-la-red-social-de-los-municipios-espanoles.html</guid>
			<comments>http://www.imaginanet.com/blog/gobolnet-la-red-social-de-los-municipios-espanoles.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 17 May 2010 17:50:54 +0100</pubDate>
					<category><![CDATA[Internet]]></category>
					<category><![CDATA[Redes Sociales]]></category>
					<category><![CDATA[Marketing OnLine]]></category>
					<description><![CDATA[La FEMP (Federaci&oacute;n Espa&ntilde;ola de Municipios y Provincias) acaba de lanzar GOBOLnet, la red social lanzada con el objetivo de ser un canal de comunicaci&oacute;n cont&iacute;nuo con los cargos pol&iacute;ticos, t&eacute;cnicos y cualquier trabajador de las entidades locales con los ciudadanos. Desde esta red social se...]]></description>
			<content:encoded><![CDATA[>La FEMP (Federaci&oacute;n Espa&ntilde;ola de Municipios y Provincias) acaba de lanzar GOBOLnet, la red social lanzada con el objetivo de ser un canal de comunicaci&oacute;n cont&iacute;nuo con los cargos pol&iacute;ticos, t&eacute;cnicos y cualquier trabajador de las entidades locales con los ciudadanos. Desde esta red social se podr&aacute;n realizar adem&aacute;s video conferencias, intercambiar documentos, enviar mensajes masivos a toda la red GobolNet, etc.<br /><br />Esta experiencia, es un proyecto pionero a nivel mundial ya que aporta nuevos conceptos a las redes sociales.&nbsp;]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=46</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/gobolnet-la-red-social-de-los-municipios-espanoles.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Pagos en serie de PayPal</title>
			<link>http://www.imaginanet.com/blog/pagos-en-serie-de-paypal.html</link>
			<guid>http://www.imaginanet.com/blog/pagos-en-serie-de-paypal.html</guid>
			<comments>http://www.imaginanet.com/blog/pagos-en-serie-de-paypal.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Fri, 14 May 2010 13:25:40 +0100</pubDate>
					<category><![CDATA[Comercio electrónico]]></category>
					<category><![CDATA[PHP]]></category>
					<description><![CDATA[Los pagos en serie de PayPal (batch payments) sirven para realizar m&uacute;ltiples pagos de forma masiva a personas que tengan una cuenta de PayPal para realizar pagos masivos o transferencias peri&oacute;dicas de dinero que es necesario para ciertas empresas o tiendas en Internet.
La gran ventaja es que podemos programar una...]]></description>
			<content:encoded><![CDATA[><p>Los pagos en serie de PayPal (<em>batch payments</em>) sirven para realizar m&uacute;ltiples pagos de forma masiva a personas que tengan una cuenta de PayPal para <span style="text-decoration: underline;">realizar pagos masivos o transferencias peri&oacute;dicas de dinero</span> que es necesario para ciertas <a title="Tiendas, negocios y empresas virtuales" href="http://www.imaginanet.com/diseno-web/tiendas-virtuales.html">empresas o tiendas en Internet</a>.</p>
<p>La gran ventaja es que podemos programar una aplicaci&oacute;n que realice este pago a los usuarios que nosotros deseemos. Para ello deberemos crear un fichero en el que los datos de cada pago estar&aacute;n separados por tabulaciones y cada pago por un salgo de l&iacute;nea. El formato de cada pago es el siguiente:</p>
<ol>
<li><strong>Direcci&oacute;n de correo electr&oacute;nico</strong> del usuario</li>
<li><strong>Importe</strong> en el formato 12.34</li>
<li><strong>C&oacute;digo de la moneda</strong> de pago (<a href="https://www.paypal.com/es/cgi-bin/webscr?cmd=_batch-payment-format-outside">monedas de pago en PayPal</a>). En cada archivo s&oacute;lo puede haber una moneda, por lo que si tenemos que hacer varios pagos de varias monedas deberemos generar diferentes archivos</li>
<li><strong>Identificador</strong> del pago (sin espacios)</li>
<li><strong>Texto explicativo</strong> del pago (opcional)</li>
</ol>
<p>Un ejemplo de archivo de pago en serie ser&iacute;a el siguiente:</p>
<pre class="code">123456@dompruebas.es	2.43	EUR	transferencia_2245	Pago del d&iacute;a  14 de Mayo
abcdfeg@dompruebas.es	122.53	EUR	transferencia_2246	Pago del d&iacute;a  14 de Mayo
</pre>
<p>&nbsp;</p>
<h3>Ejemplo de generaci&oacute;n de pago en serie en PHP</h3>
<p>Con el siguiente sencillo ejemplo, conseguiremos hacer un script que realice pagos en serie. La fuente la suponemos de una base de datos, y tras crear el archivo, deberemos subir el archivo a la web de PayPal para realizar los pagos:</p>
<pre class="code php">&lt;?php
&nbsp;
// Resultados obtenidos de una base de datos, XML, etc.
$moneda = "EUR";
&nbsp;
$bp[0]['email'] = "123456@dompruebas.es";
$bp[0]['importe'] = "2.43";
$bp[0]['identificador'] = "transferencia_2245";
$bp[0]['mensaje'] = "Pago del d&iacute;a  14 de Mayo";
&nbsp;
$bp[1]['email'] = "abcdfeg@dompruebas.es";
$bp[1]['importe'] = "122.53";
$bp[1]['identificador'] = "transferencia_2246";
$bp[1]['mensaje'] = "Pago del d&iacute;a  14 de Mayo";
&nbsp;
// Procesamos
$archivo = "";
$icount = count($bp);
for($i=0;$i&lt;$icount;$i++) {
   $archivo.=$bp[$i]['email']."t";
   $archivo.=$bp[$i]['importe']."t";
   $archivo.=$moneda."t";
   $archivo.=$bp[$i]['identificador']."t";
   $archivo.=$bp[$i]['mensaje']."rn";
}
&nbsp;
$nombre_archivo = date("Ymd").'_'.$moneda.'_bp_'.time().'.txt';
$fd=fopen($nombre_archivo, 'a');
fwrite($fd,$archivo);
fclose($fd);
?&gt;
</pre>
<p>Para m&aacute;s informaci&oacute;n, podemos leer la <a href="https://www.paypal.com/es/cgi-bin/webscr?cmd=_batch-payment-overview-outside">documentaci&oacute;n oficial de los pagos en serie</a>.</p>
<p>&nbsp;</p>
<h3>Art&iacute;culos relacionados:</h3>
<ul>
<li><a title="Utilizar PayPal para vender en tu web" href="http://www.imaginanet.com/blog/como-utilizar-paypal-para-realizar-compras-en-tu-web.html">C&oacute;mo pagar en tu web con PayPal</a></li>
<li><a title="PayPal Instant Payment Notification" href="http://www.imaginanet.com/blog/controlar-los-pagos-por-paypal-mediante-notificacion-de-pago-instantanea.html">Controlar los pagos por PayPal mediante Notificaci&oacute;n de Pago Instant&aacute;nea</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=45</wfw:commentRss>
			<slash:comments>3</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/pagos-en-serie-de-paypal.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Se terminan las IPs</title>
			<link>http://www.imaginanet.com/blog/se-terminan-las-ips.html</link>
			<guid>http://www.imaginanet.com/blog/se-terminan-las-ips.html</guid>
			<comments>http://www.imaginanet.com/blog/se-terminan-las-ips.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Thu, 13 May 2010 12:40:52 +0100</pubDate>
					<category><![CDATA[Internet]]></category>
					<description><![CDATA[Est&aacute; previsto que el a&ntilde;o que viene se agoten las direcciones ip seg&uacute;n el esquema IPv4, el cual se mejor&oacute; con el IPv6 pero muchas empresas y pa&iacute;ses todav&iacute;a no lo han implantado.Este hecho, implica que el d&iacute;a 9 de septiembre de 2012 se agotar&aacute;n las direcciones IP (seg&uacute;n...]]></description>
			<content:encoded><![CDATA[>Est&aacute; previsto que el a&ntilde;o que viene se agoten las direcciones ip seg&uacute;n el esquema IPv4, el cual se mejor&oacute; con el IPv6 pero muchas empresas y pa&iacute;ses todav&iacute;a no lo han implantado.<br /><br />Este hecho, implica que el d&iacute;a 9 de septiembre de 2012 se agotar&aacute;n las direcciones IP (seg&uacute;n los expertos, este d&iacute;a se entregar&aacute; el &uacute;ltimo rango de direcciones IP). El protocolo IPv4 permite 4.000 billones de direcciones IP, una cantidad suficiente cuando naci&oacute; la WWW, pero hoy en d&iacute;a es necesario ampliar el n&uacute;mero.]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=44</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/se-terminan-las-ips.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Cómo crear una campaña de publicidad en móviles. Claves a tener en cuenta.</title>
			<link>http://www.imaginanet.com/blog/como-crear-una-campana-de-publicidad-en-moviles-claves-a-tener-en-cuenta.html</link>
			<guid>http://www.imaginanet.com/blog/como-crear-una-campana-de-publicidad-en-moviles-claves-a-tener-en-cuenta.html</guid>
			<comments>http://www.imaginanet.com/blog/como-crear-una-campana-de-publicidad-en-moviles-claves-a-tener-en-cuenta.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Thu, 13 May 2010 12:34:18 +0100</pubDate>
					<category><![CDATA[Marketing OnLine]]></category>
					<description><![CDATA[Seg&uacute;n un estudio realizado en 2008 por la Uni&oacute;n Internacional de Telecomunicaciones, en el a&ntilde;o 2008 el 61% de la poblaci&oacute;n mudial dispon&iacute;a de tel&eacute;fono m&oacute;vil. Si tenemos en cuenta que ya hace dos a&ntilde;os de este informe y que la cifra es a nivel mundial, podemos decir que todas...]]></description>
			<content:encoded><![CDATA[>Seg&uacute;n un estudio realizado en 2008 por la Uni&oacute;n Internacional de Telecomunicaciones, en el a&ntilde;o 2008 <span style="text-decoration: underline;">el 61% de la poblaci&oacute;n mudial </span>dispon&iacute;a de tel&eacute;fono m&oacute;vil. Si tenemos en cuenta que ya hace dos a&ntilde;os de este informe y que la cifra es a nivel mundial, podemos decir que todas las personas son usuarios de tel&eacute;fono m&oacute;vil. Tenemos un porcentaje de poblaci&oacute;n casi total al que podemos enviarle un mensaje publicitario sin tener que saber donde est&aacute;n.<br /><br />El marketing m&oacute;vil tienen un potencial brutal, ya que la llegada de internet al m&oacute;vil lo ha convertido en una de las mejores opciones para dar a conocer o fomentar un producto, servicio o marca. Adem&aacute;s, es necesario tener en cuenta que al ser un medio personal, permite una segmentaci&oacute;n para la creaci&oacute;n de campa&ntilde;as publicitarias dise&ntilde;adas especialmente para el target al que se dirige.<br /><br /><span style="text-decoration: underline;">Cosas importantes a tener en cuenta cuando pensemos lanzar una campa&ntilde;a publicitaria dirigida a dispositivos m&oacute;viles:</span><br /><br />- <strong>P&aacute;ginas de llegada distintas dependiendo del tipo de m&oacute;vil</strong>: Al tener distintos dispositivos m&oacute;viles con distintas caracter&iacute;sticas, si queremos que nuestros contenidos sean compatibles con todos los modelos de m&oacute;vil, es necesario crear landing pages propias para cada uno.<br />- <strong>Dar contenidos interesantes</strong>. Si ofrecemos contenidos que aportan valor a&ntilde;adido a la campa&ntilde;a, provocamos un feedback positivo de los usuarios. Por ejemplo podemos enviar bonus descuento, promociones con descuentos, informaci&oacute;n interesante para el usuario, v&iacute;deos, etc, incrementaremos el ratio de usuarios atra&iacute;dos por la campa&ntilde;a.<br />- <strong>Utilizar varias opciones</strong>. Cuando se comienza con una estrategia publicitaria, es aconsejable realizar un test con cada modelo planteado para as&iacute; conocer cual funciona mejor con un servicio, marca o producto. El CTR de una campa&ntilde;a sin optimizar no supera el 3%, esta misma campa&ntilde;a optimizada para el target, puede darnos un CTR del 5% o superior.<br />- <strong>Piensa bien el mensaje que quieres transmitir</strong>. Los mensajes publicitarios deben ser cortos, directos y f&aacute;ciles de entender, si adem&aacute;s incluye contenidos virales como galer&iacute;as de fotos, videos, etc, el mensaje funciona por s&iacute; solo.<br /><br />Imaginanet es una <strong><a title="&quot;Imaginanet," href="/">agencia web</a></strong> que puede ayudarte con estrategias de marketing en nuevos medios.]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=43</wfw:commentRss>
			<slash:comments>1</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/como-crear-una-campana-de-publicidad-en-moviles-claves-a-tener-en-cuenta.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Posicionamiento en buscadores, la técnica de marketing online más eficaz</title>
			<link>http://www.imaginanet.com/blog/posicionamiento-en-buscadores-la-tecnica-de-marketing-online-mas-eficaz.html</link>
			<guid>http://www.imaginanet.com/blog/posicionamiento-en-buscadores-la-tecnica-de-marketing-online-mas-eficaz.html</guid>
			<comments>http://www.imaginanet.com/blog/posicionamiento-en-buscadores-la-tecnica-de-marketing-online-mas-eficaz.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed, 12 May 2010 11:57:08 +0100</pubDate>
					<category><![CDATA[SEO]]></category>
					<category><![CDATA[Marketing OnLine]]></category>
					<description><![CDATA[Acaba de hacerse p&uacute;blico un estudio en el que se destaca la t&eacute;cnica de posicionamiento en buscadores como la pr&aacute;ctica de marketing online m&aacute;s importante para todo negocio montado en la red.El posicionamiento en buscadores o SEO (Search Engine Optimization), tiene como objetivo que la web a posicionar...]]></description>
			<content:encoded><![CDATA[>Acaba de hacerse p&uacute;blico un estudio en el que se destaca la t&eacute;cnica de posicionamiento en buscadores como la pr&aacute;ctica de marketing online m&aacute;s importante para todo negocio montado en la red.<br /><br />El posicionamiento en buscadores o SEO (Search Engine Optimization), tiene como objetivo que la web a posicionar aparezca en primeras posiciones de b&uacute;squeda en los distintos buscadores de internet.<br /> <br />Seg&uacute;n los expertos, la optimizaci&oacute;n SEO ser&aacute; la m&aacute;s rentable y la m&aacute;s efectiva t&eacute;cnica de <a title="Imaginanet: Agencia de marketing online" href="/marketing-online.html">marketing online</a>, tanto para empresas que operen en internet u otras que no lo hagan pero tengan presencia. Esto confirma una encuesta que se hizo recientemente en la que el 95% de las pymes online consideran el posicionamiento en buscadores como la t&eacute;cnica de ventas m&aacute;s rentable para su empresa.<br /><br />Aunque se est&aacute; intentando tambi&eacute;n innovar y vender al usuario nuevas tendencias como lo son las redes sociales y otros entornos novedosos, actualmente la t&eacute;cnica m&aacute;s rentable es el SEO, aunque no hay que dejar de fijarse en medios como las redes sociales, ya que juegan un papel importante y jugar&aacute;n un papel m&aacute;s importante en el futuro en lo que respecta al posicionamiento en buscadores.<br /><br />Conclusi&oacute;n: una de las estrategias de <a title="Imaginanet, agencia de marketing online" href="/marketing-online.html">marketing online</a> m&aacute;s importante es el posicionamiento en buscadores.&nbsp;]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=42</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/posicionamiento-en-buscadores-la-tecnica-de-marketing-online-mas-eficaz.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Google lanza un tablet para competir con Apple iPad</title>
			<link>http://www.imaginanet.com/blog/google-lanza-un-tablet-para-competir-con-apple-ipad.html</link>
			<guid>http://www.imaginanet.com/blog/google-lanza-un-tablet-para-competir-con-apple-ipad.html</guid>
			<comments>http://www.imaginanet.com/blog/google-lanza-un-tablet-para-competir-con-apple-ipad.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed, 12 May 2010 11:35:17 +0100</pubDate>
					<category><![CDATA[Google]]></category>
					<description><![CDATA[Verizon en breve va a lanzar un tablet para cuyo lanzamiento cuenta con la ayuda tecnol&oacute;gica de Google.Seg&uacute;n se confirma en la noticia (ver en ingl&eacute;s), est&aacute;n trabajando con Google en el desarrollo del tablet para as&iacute; competir con AT&amp;T.Google s&oacute;lo ha dicho que su software est&aacute;...]]></description>
			<content:encoded><![CDATA[>Verizon en breve va a lanzar un tablet para cuyo lanzamiento cuenta con la ayuda tecnol&oacute;gica de Google.<br /><br />Seg&uacute;n se confirma en la noticia (<a title="Ver noticia original" href="http://online.wsj.com/article/SB10001424052748704250104575238680540806288.html?mod=WSJ_Tech_INTL_LSMODULE" target="_blank">ver en ingl&eacute;s</a>), est&aacute;n trabajando con Google en el desarrollo del tablet para as&iacute; competir con AT&amp;T.<br /><br />Google s&oacute;lo ha dicho que su software est&aacute; preparado para que se use en cualquier dispositivo, as&iacute; que se supone que usar&aacute; Android como sistema operativo.<br /><br />Esta noticia aumenta la guerra entre Google y Apple, que desde hace unos meses han comenzado una batalla que parece plantearse dura y larga.&nbsp;]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=41</wfw:commentRss>
			<slash:comments>1</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/google-lanza-un-tablet-para-competir-con-apple-ipad.html</feedburner:origLink>
		</item>
				
		<item>
			<title>En USA, las editoriales van con Google</title>
			<link>http://www.imaginanet.com/blog/en-usa-las-editoriales-van-con-google.html</link>
			<guid>http://www.imaginanet.com/blog/en-usa-las-editoriales-van-con-google.html</guid>
			<comments>http://www.imaginanet.com/blog/en-usa-las-editoriales-van-con-google.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue, 11 May 2010 11:15:22 +0100</pubDate>
					<category><![CDATA[Comercio electrónico]]></category>
					<category><![CDATA[Google]]></category>
					<description><![CDATA[El buscador americano Google, ha conseguido que las editoriales de Estados Unidos vean bien la entrada del buscador en el negocio de los libros electr&oacute;nicos, uno de los grandes intereses que Google ha declarado abiertamente.Parece ser que la tienda virtual (e-commerce) de libros electr&oacute;nicos (eBooks) de Google...]]></description>
			<content:encoded><![CDATA[>El buscador americano Google, ha conseguido que las editoriales de Estados Unidos vean bien la entrada del buscador en el negocio de los libros electr&oacute;nicos, uno de los grandes intereses que Google ha declarado abiertamente.<br /><br />Parece ser que la <a title="Imaginanet desarrolla tiendas virtuales / e-commerce apps" href="/diseno-web/tiendas-virtuales.html">tienda virtual (e-commerce)</a> de libros electr&oacute;nicos (eBooks) de Google empezar&aacute; a funcionar con m&aacute;s de 25.000 autores y editoriales en junio de este a&ntilde;o. De estos libros, 2 millones ha sido cedidos por las editoriales para poner en marcha la mayor biblioteca virtual del mundo. (<a href="http://www.japantoday.com/category/technology/view/google-backed-by-almost-all-us-publishers-on-digital-bookstore" target="_blank">ver noticia completa en ingl&eacute;s</a>)&nbsp;]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=40</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/en-usa-las-editoriales-van-con-google.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Internet ocupa el móvil de forma espectacular</title>
			<link>http://www.imaginanet.com/blog/internet-ocupa-el-movil-de-forma-espectacular.html</link>
			<guid>http://www.imaginanet.com/blog/internet-ocupa-el-movil-de-forma-espectacular.html</guid>
			<comments>http://www.imaginanet.com/blog/internet-ocupa-el-movil-de-forma-espectacular.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue, 11 May 2010 11:08:18 +0100</pubDate>
					<category><![CDATA[Google Apps]]></category>
					<category><![CDATA[Google]]></category>
					<category><![CDATA[Buscadores]]></category>
					<category><![CDATA[Web 2.0]]></category>
					<description><![CDATA[Sin darnos cuenta, hemos llegado a una situaci&oacute;n en que los proveedores de contenidos y aplicaciones web como son Google, FaceBook, Apple, Skype, Twitter, ..., tienen una cuota de poder alucinante en un sector con ingresos muy atractivos y m&aacute;rgenes de beneficio bastante amplios.Esta situaci&oacute;n est&aacute;...]]></description>
			<content:encoded><![CDATA[>Sin darnos cuenta, hemos llegado a una situaci&oacute;n en que los proveedores de contenidos y aplicaciones web como son Google, FaceBook, Apple, Skype, Twitter, ..., tienen una cuota de poder alucinante en un sector con ingresos muy atractivos y m&aacute;rgenes de beneficio bastante amplios.<br /><br />Esta situaci&oacute;n est&aacute; poniendo nerviosas a las compa&ntilde;&iacute;as de telecomunicaciones, que sin darse cuenta, han perdido en control total del sector que ten&iacute;an, ya que el negocio se basa m&aacute;s en las herramientas que estos proveedores de <a title="Aplicaciones web 2.0" href="/programacion-web/aplicaciones-web.html">aplicaciones web</a> proporcionan que en la mera gesti&oacute;n del tr&aacute;fico de voz y datos.<br /><br />Aunque ya han asumido que la comunicaci&oacute;n con voz no es su principal objetivo (nadie se ha opuesto a Skype, cuya aplicaci&oacute;n de comunicaci&oacute;n por voz la usan m&aacute;s de 500 millones de usuarios en todo el mundo), parece ser que esto no va a pasar con la publicidad, que tras el &eacute;xito conseguido por Google, todos quieren formar parte del negocio.<br /><br />La batalla de verdad s&oacute;lo acaba de empezar, veremos que posiciones toma cada uno de los participantes.&nbsp;]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=39</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/internet-ocupa-el-movil-de-forma-espectacular.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Android vs iPhone. En USA las ventas de Android superan a las de iPhone.</title>
			<link>http://www.imaginanet.com/blog/android-vs-iphone-en-usa-las-ventas-de-android-superan-a-las-de-iphone.html</link>
			<guid>http://www.imaginanet.com/blog/android-vs-iphone-en-usa-las-ventas-de-android-superan-a-las-de-iphone.html</guid>
			<comments>http://www.imaginanet.com/blog/android-vs-iphone-en-usa-las-ventas-de-android-superan-a-las-de-iphone.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue, 11 May 2010 10:55:55 +0100</pubDate>
					<category><![CDATA[Google Apps]]></category>
					<category><![CDATA[Google]]></category>
					<category><![CDATA[Buscadores]]></category>
					<category><![CDATA[Web 2.0]]></category>
					<description><![CDATA[Mientras Nokia sigue manteniendo el primer puesto a nivel mundial en lo que a ventas de tel&eacute;fonos m&oacute;viles se refiere.El sistema operativo Android, de Google, acaba de ocupar la segunda plaza de ventas en Estados Unidos, puesto que ocupaba el iPhone de Apple (ver noticia). As&iacute;, tenemos en primer puesto a...]]></description>
			<content:encoded><![CDATA[>Mientras Nokia sigue manteniendo el primer puesto a nivel mundial en lo que a ventas de tel&eacute;fonos m&oacute;viles se refiere.<br /><br />El sistema operativo Android, de Google, acaba de ocupar la segunda plaza de ventas en Estados Unidos, puesto que ocupaba el iPhone de Apple (<a title="Ver noticia" href="http://www.npd.com/press/releases/press_100510.html" target="_blank">ver noticia</a>). As&iacute;, tenemos en primer puesto a BlackBerry (36%), le sigue Android (28%) y en tercera posici&oacute;n est&aacute; iPhone (21%), seg&uacute;n la noticia, este impulso en ventas se ha debido a las campa&ntilde;as promocionales que han llevado a cabo dos empresas de telefon&iacute;a m&oacute;vil, por otro lado, hay que tener en cuenta que en USA s&oacute;lo una operadora (ATT) vende el iPhone en exclusiva.<br /><br />Seg&uacute;n Apple, desde el lanzamiento del iPhone en 2007 se han vendido 51 millones de tel&eacute;fonos y en el Application Store est&aacute;n disponibles m&aacute;s de 200.000 aplicaciones.&nbsp;<br /><br />Distintos informes de ventas de tel&eacute;fonos de &uacute;ltima generaci&oacute;n dan el liderazgo a Nokia, la segunda plaza es para RIM (BlackBerry), el tercer puesto es para Apple y el cuarto lo ocupa Android.&nbsp;]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=38</wfw:commentRss>
			<slash:comments>1</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/android-vs-iphone-en-usa-las-ventas-de-android-superan-a-las-de-iphone.html</feedburner:origLink>
		</item>
				
		<item>
			<title>La alternativa de Apple a Flash</title>
			<link>http://www.imaginanet.com/blog/la-alternativa-de-apple-a-flash.html</link>
			<guid>http://www.imaginanet.com/blog/la-alternativa-de-apple-a-flash.html</guid>
			<comments>http://www.imaginanet.com/blog/la-alternativa-de-apple-a-flash.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 10 May 2010 15:03:36 +0100</pubDate>
					<category><![CDATA[HTML5]]></category>
					<category><![CDATA[Flash]]></category>
					<category><![CDATA[Web 2.0]]></category>
					<category><![CDATA[JavaScript]]></category>
					<description><![CDATA[Por todos es conocida la disputa entre Apple y Adobe en cuanto a Adobe Flash.Hoy nos hemos enterado (ver noticia en ingl&eacute;s) de que Apple est&aacute; trabajando en el desarrollo de un framework basado en est&aacute;ndares web y que ser&aacute; la alternativa a Adobe Flash y Microsoft Silverlight. Lo m&aacute;s atractivo de...]]></description>
			<content:encoded><![CDATA[>Por todos es conocida la disputa entre Apple y Adobe en cuanto a Adobe Flash.<br /><br />Hoy nos hemos enterado (<a href="http://news.cnet.com/8301-13579_3-20004509-37.html" target="_blank">ver noticia en ingl&eacute;s</a>) de que Apple est&aacute; trabajando en el desarrollo de un framework basado en est&aacute;ndares web y que ser&aacute; la alternativa a Adobe Flash y Microsoft Silverlight. Lo m&aacute;s atractivo de todo es que se ejecutar&aacute; de forma nativa en los navegadores, con lo que no necesitar&aacute; de plugin adicional. El nombre que le han dado es Apple Gianduia.<br /><br />Podemos resumirlo como una adaptaci&oacute;n de Cocoa, CoreData y WebObjects pero en los navegadores y estar&aacute; escrito en JavaScript. Seg&uacute;n parece ser, Apple ha utilizado Gianduia ya en el programa de reservas inclu&iacute;do en iPhone y en varias aplicaciones de tiendas virtuales online.<br /><br />Parece que Apple contra-ataca a Flash con Gianduia.<br /><br />Un nuevo punto a tener en cuenta por <a title="Imaginanet, empresa de dise&ntilde;o web profesional" href="/diseno-web.html">empresas de dise&ntilde;o web</a> y que habr&aacute; que seguir con atenci&oacute;n.]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=34</wfw:commentRss>
			<slash:comments>2</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/la-alternativa-de-apple-a-flash.html</feedburner:origLink>
		</item>
				
		<item>
			<title>La compañía japonesa NEC anuncia una tecnología con la que encontrará vídeos piratas en pocos segundos</title>
			<link>http://www.imaginanet.com/blog/la-compania-japonesa-nec-anuncia-una-tecnologia-con-la-que-encontrara-videos-piratas-en-pocos-segundos.html</link>
			<guid>http://www.imaginanet.com/blog/la-compania-japonesa-nec-anuncia-una-tecnologia-con-la-que-encontrara-videos-piratas-en-pocos-segundos.html</guid>
			<comments>http://www.imaginanet.com/blog/la-compania-japonesa-nec-anuncia-una-tecnologia-con-la-que-encontrara-videos-piratas-en-pocos-segundos.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 10 May 2010 14:53:32 +0100</pubDate>
					<category><![CDATA[HTML5]]></category>
					<category><![CDATA[Flash]]></category>
					<category><![CDATA[Web 2.0]]></category>
					<category><![CDATA[JavaScript]]></category>
					<description><![CDATA[NEC ha anunciado (ver noticia en ingl&eacute;s) que dispone de una tecnolog&iacute;a de identificaci&oacute;n que permitir&aacute; a los propietarios de derechos de autor buscar en pocos segundos v&iacute;deos que cometen infracciones de copyright y est&aacute;n subidos a internet.En la nota de prensa se anuncia como gran invento...]]></description>
			<content:encoded><![CDATA[>NEC ha anunciado (<a href="http://www.tcmagazine.com/tcm/news/misc/27909/nec-claims-find-illegal-video-uploads-seconds" target="_blank">ver noticia en ingl&eacute;s</a>) que dispone de una tecnolog&iacute;a de identificaci&oacute;n que permitir&aacute; a los propietarios de derechos de autor buscar en pocos segundos v&iacute;deos que cometen infracciones de copyright y est&aacute;n subidos a internet.<br /><br />En la nota de prensa se anuncia como gran invento para acabar con la pirater&iacute;a en internet con este sistema capaz de encontrar copias completas id&eacute;nticas o modificadas de una pel&iacute;cula, video clip, ... que est&aacute;n en internet.<br /><br />Seg&uacute;n comentan es un sistema con una precisi&oacute;n superior al 96% y que da una tasa de falsos positivos del 5 por mill&oacute;n durante las pruebas que han realizado. NEC va a presentar esta tecnolog&iacute;a la semana que viene en una conferencia de "embeded systems".<br /><br />Este sistema se podr&aacute; implantar a partir de Septiembre. Su objetivo es la identificaci&oacute;n r&aacute;pida de infracciones de copyright en la red.<br /><br />&iquest;Qu&eacute; os parece?&nbsp;]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=33</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/la-compania-japonesa-nec-anuncia-una-tecnologia-con-la-que-encontrara-videos-piratas-en-pocos-segundos.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Google Apps para educación llega a los 8 millones de usuarios</title>
			<link>http://www.imaginanet.com/blog/google-apps-para-educacion-llega-a-los-8-millones-de-usuarios.html</link>
			<guid>http://www.imaginanet.com/blog/google-apps-para-educacion-llega-a-los-8-millones-de-usuarios.html</guid>
			<comments>http://www.imaginanet.com/blog/google-apps-para-educacion-llega-a-los-8-millones-de-usuarios.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 10 May 2010 15:20:01 +0100</pubDate>
					<category><![CDATA[Google Apps]]></category>
					<description><![CDATA[Google ha comunicado esta noticia en su blog oficial (ver post oficial), y esta noticia nos deja ver c&oacute;mo el master de las b&uacute;squedas invierte en su suite ofim&aacute;tica y soluci&oacute;n de comunicaci&oacute;n para grupos.Si tenemos en cuenta que Google Apps cuenta con un total de 25 millones de usuarios, se ve que...]]></description>
			<content:encoded><![CDATA[>Google ha comunicado esta noticia en su blog oficial (<a href="http://googleblog.blogspot.com/2010/05/schools-are-almost-out-for-summerand-in.html" target="_blank">ver post oficial</a>), y esta noticia nos deja ver c&oacute;mo el master de las b&uacute;squedas invierte en su suite ofim&aacute;tica y soluci&oacute;n de comunicaci&oacute;n para grupos.<br /><br />Si tenemos en cuenta que Google Apps cuenta con un total de 25 millones de usuarios, se ve que casi un tercio son del sistema educativo. Una apuesta estrat&eacute;gica con estas herramientas gratuitas que integran Gmail, Gcalendar, Gtalk, &nbsp;Gdocs, Gpages, ... con la opci&oacute;n de compartirlos y editarlos conjuntamente.<br />]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=35</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/google-apps-para-educacion-llega-a-los-8-millones-de-usuarios.html</feedburner:origLink>
		</item>
				
		<item>
			<title>225 millones de euros para las TIC</title>
			<link>http://www.imaginanet.com/blog/225-millones-de-euros-para-las-tic.html</link>
			<guid>http://www.imaginanet.com/blog/225-millones-de-euros-para-las-tic.html</guid>
			<comments>http://www.imaginanet.com/blog/225-millones-de-euros-para-las-tic.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 10 May 2010 15:40:18 +0100</pubDate>
					<category><![CDATA[Google Apps]]></category>
					<description><![CDATA[La Secretar&iacute;a de Estado de Telecomunicaciones anunci&oacute; el inicio de la convocatoria para la concesi&oacute;n de ayudas en el marco del Plan Avanza. El Gobierno destinar&aacute; en 2010, 225 millones de euros a trav&eacute;s de cuatro l&iacute;neas: Formaci&oacute;n, Competitividad (I+D+i), Ciudadan&iacute;a Digital y...]]></description>
			<content:encoded><![CDATA[>La Secretar&iacute;a de Estado de Telecomunicaciones anunci&oacute; el inicio de la convocatoria para la concesi&oacute;n de ayudas en el marco del Plan Avanza. <br /><br />El Gobierno destinar&aacute; en 2010, 225 millones de euros a trav&eacute;s de cuatro l&iacute;neas: <br />Formaci&oacute;n, Competitividad (I+D+i), Ciudadan&iacute;a Digital y Contenidos de Inter&eacute;s Social.  <br /><br />159 millones de euros se destinar&aacute;n a prestamos y los 66 millones de euros restantes&nbsp;se entregar&aacute;n a trav&eacute;s de subvenciones. <br /><br />El Ministerio de Industria ha publicado una nota de prensa en la que dice que la convocatoria busca contribuir al &ldquo;<em>adecuado desarrollo y utilizaci&oacute;n de las tecnolog&iacute;as, aplicaciones, servicios y contenidos para la sociedad de la informaci&oacute;n</em>&rdquo;.  <br /><br />Desde el Gobierno se insiste en la necesidad de consolidar un modelo de crecimiento econ&oacute;mico sostenible que se base en &ldquo;<em>el incremento de la competitividad y la productividad, la promoci&oacute;n de la igualdad social y regional, la accesibilidad universal y la mejora del bienestar y la calidad de vida de los ciudadanos</em>&rdquo;.  <br /><br />El programa Avanza Competitividad (I+D+i) tiene el presupuesto m&aacute;s alto: 200 millones de euros (150 millones en pr&eacute;stamos y 50 millones en subvenciones). <br /><br />Las solicitudes podr&aacute;n presentarse entre el 7 de mayo y el 7 de junio.  <br /><br />Avanza Contenidos de Inter&eacute;s Social, por su parte, cuenta con un presupuesto de 12 millones de euros (9 millones pr&eacute;stamos y 3 millones en subvenciones) y recibir&aacute; solicitudes entre el 7 de mayo y el 14 de junio.  <br /><br />El presupuesto de Avanza Formaci&oacute;n llega a los 10 millones de euros en subvenciones, con un plazo de presentaci&oacute;n de solicitudes del 7 de mayo al 9 de junio. <br /> <br />Avanza Ciudadan&iacute;a Digital, por &uacute;ltimo, dispone de un presupuesto de 3 millones de euros en subvenciones y aceptar&aacute; solicitudes entre el 7 de mayo y el 1 de junio.]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=37</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/225-millones-de-euros-para-las-tic.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Google cambia el buscador</title>
			<link>http://www.imaginanet.com/blog/google-cambia-el-buscador.html</link>
			<guid>http://www.imaginanet.com/blog/google-cambia-el-buscador.html</guid>
			<comments>http://www.imaginanet.com/blog/google-cambia-el-buscador.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 10 May 2010 15:34:49 +0100</pubDate>
					<category><![CDATA[Google]]></category>
					<category><![CDATA[SEO]]></category>
					<description><![CDATA[Desde hoy se puede ver c&oacute;mo en la parte izquierda del resultado de una b&uacute;squeda nos aparece un men&uacute; nuevo con b&uacute;squeda de im&aacute;genes, libros, noticias, blogs, ... y una vez elegida una opci&oacute;n nos ofrece m&aacute;s opciones sobre el tema/opci&oacute;n elegido (tama&ntilde;os de imagen, color,...]]></description>
			<content:encoded><![CDATA[>Desde hoy se puede ver c&oacute;mo en la parte izquierda del resultado de una b&uacute;squeda nos aparece un men&uacute; nuevo con b&uacute;squeda de im&aacute;genes, libros, noticias, blogs, ... y una vez elegida una opci&oacute;n nos ofrece m&aacute;s opciones sobre el tema/opci&oacute;n elegido (tama&ntilde;os de imagen, color, ...).<br /><br />Se supone que con estos cambios Google pretende ganar en <a title="Dise&ntilde;o web y usabilidad" href="/diseno-web/diseno-web-y-usabilidad.html">usabilidad</a> y ahorrarse p&aacute;ginas vistas de los usuarios. En Google dicen en que el ahorro de tiempo para el usuario ser&aacute; muy grande, ya que podr&aacute; ir a lo que busca de forma directa. El usuario tiene m&aacute;s f&aacute;cilmente en pantalla lo que busca.<br /><br />Adem&aacute;s, han aplicado unas peque&ntilde;as variaciones est&eacute;ticas al buscador como eliminar subrayado de enlaces, degradados, etc.&nbsp;]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=36</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/google-cambia-el-buscador.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Las 6 razones de Apple para no utilizar Flash</title>
			<link>http://www.imaginanet.com/blog/las-6-razones-de-apple-para-no-utilizar-flash.html</link>
			<guid>http://www.imaginanet.com/blog/las-6-razones-de-apple-para-no-utilizar-flash.html</guid>
			<comments>http://www.imaginanet.com/blog/las-6-razones-de-apple-para-no-utilizar-flash.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 10 May 2010 12:12:59 +0100</pubDate>
					<category><![CDATA[HTML5]]></category>
					<category><![CDATA[Accesibilidad]]></category>
					<category><![CDATA[Flash]]></category>
					<category><![CDATA[Web 2.0]]></category>
					<description><![CDATA[Steve Jobs, m&aacute;ximo responsable de Apple ha criticado abiertamente a Adobe en esta carta. En la carta se defienden los est&aacute;ndares abiertos para web, como HTML5&nbsp;.Los seis motivos por los que Flash no funciona en sus dispositivos iPhone, iPod e iPad son:- Flash es de la era de los ratones y no de las pantallas...]]></description>
			<content:encoded><![CDATA[>Steve Jobs, m&aacute;ximo responsable de Apple ha criticado abiertamente a Adobe en <a title="Ver carta. En ingl&eacute;s." href="http://www.apple.com/hotnews/thoughts-on-flash/" target="_blank">esta carta</a>. En la carta se defienden los est&aacute;ndares abiertos para web, como HTML5&nbsp;.<br /><br />Los seis motivos por los que Flash no funciona en sus dispositivos iPhone, iPod e iPad son:<br />- Flash es de la era de los ratones y no de las pantallas t&aacute;ctiles.<br />- Flash no es abierto como lo son HTML, CSS y JavaScript<br />- No es seguro y tampoco es estable.<br />- Gasta m&aacute;s bater&iacute;a en la descodificaci&oacute;n que en el caso de H.264<br />- Flash es multiplataforma y es necesario estar pendientes de cuando Adobe proporciona herramientas para desarrolladores.<br /><br />En definitiva, se aconseja utilizar HTML 5.<br /><br />Imaginanet es una <a title="Agencia web, marketing online y programaci&oacute;n web." href="/">agencia web</a> que desarrolla <a title="Desarrollo y consultor&iacute;a de aplicaciones web" href="/programacion-web/aplicaciones-web.html">aplicaciones web</a> 100% compatibles con todos los dispositivos m&oacute;viles.&nbsp;]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=32</wfw:commentRss>
			<slash:comments>3</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/las-6-razones-de-apple-para-no-utilizar-flash.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Optimización de código PHP</title>
			<link>http://www.imaginanet.com/blog/optimizacion-de-codigo-php.html</link>
			<guid>http://www.imaginanet.com/blog/optimizacion-de-codigo-php.html</guid>
			<comments>http://www.imaginanet.com/blog/optimizacion-de-codigo-php.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Thu, 22 Apr 2010 15:59:48 +0100</pubDate>
					<category><![CDATA[PHP]]></category>
					<description><![CDATA[Cuando tenemos planeado hacer una aplicaci&oacute;n web que va a hacer un trabajo intensivo de operaciones, base de datos, ficheros, etc. (por ejemplo p&aacute;gina corporativa o de comercio electr&oacute;nico) debemos plantearnos la velocidad final que tendr&aacute; con una alta carga de visitas diarias.
Por ello, vamos a...]]></description>
			<content:encoded><![CDATA[><p>Cuando tenemos planeado hacer una aplicaci&oacute;n web que va a hacer un trabajo intensivo de operaciones, base de datos, ficheros, etc. (por ejemplo <a title="Programaci&oacute;n y dise&ntilde;o de p&aacute;ginas web corporativas y de comercio electr&oacute;nico" href="http://www.imaginanet.com/programacion-web.html">p&aacute;gina corporativa o de comercio electr&oacute;nico</a>) debemos plantearnos la velocidad final que tendr&aacute; con una alta carga de visitas diarias.</p>
<p>Por ello, vamos a explicar algunos trucos y consejos con ejemplos para poder escribir nuestro c&oacute;digo PHP optimizado y por tanto nuestras aplicaciones corran m&aacute;s r&aacute;pido.</p>
<h3><span style="text-decoration: underline;">Cadenas de texto</span></h3>
<p><strong>Usar echo en vez de print</strong></p>
<p>Es m&aacute;s r&aacute;pido hacer uso de la funci&oacute;n echo que de la funci&oacute;n print</p>
<pre class="code php">echo &ldquo;Hola&rdquo;; // M&aacute;s r&aacute;pido
print &ldquo;Hola&rdquo;;
</pre>
<p><strong>Evitar concatenar texto innecesariamente y utilizar m&uacute;ltiples echos</strong></p>
<p>Es mejor realizar dos salidas de texto con dos echos diferentes que concatenar texto y despu&eacute;s producir la salida.</p>
<pre class="code php">echo &ldquo;Bienvenido&rdquo;; echo $usuario; // M&aacute;s r&aacute;pido
echo &ldquo;Bienvenido&rdquo;.$usuario;
</pre>
<p><strong>Saber si una cadena de texto est&aacute; vac&iacute;a</strong></p>
<p>Es m&aacute;s r&aacute;pido saber si una variable est&aacute; vac&iacute;a con empty que saber si la longitud en n&uacute;mero de caracteres es cero con strlen.</p>
<pre class="code php">if (empty($cadena)) echo &ldquo;vac&iacute;a&rdquo;; // M&aacute;s r&aacute;pida
if (strlen($s) == 0) echo &ldquo;vac&iacute;a&rdquo;;
</pre>
<p><strong>Substituir texto</strong></p>
<p>La manera m&aacute;s r&aacute;pida para substituir texto es con strtr y no con str_replace o preg_replace.</p>
<pre class="code php">$salida = strtr("abd","d","c"); // M&aacute;s r&aacute;pida
$salida = str_replace("d","c","abd");
$salida = preg_replace("/d/","c","abd");
</pre>
<p><strong>Saber si una cadena est&aacute; contenida en otra</strong></p>
<p>La funci&oacute;n strpos es m&aacute;s r&aacute;pida y ocupa menos memoria que strstr</p>
<pre class="code php">if(strpos("Hola","o")!==false) echo "s&iacute;"; // M&aacute;s r&aacute;pida
$esta_contenida = strstr("Hola","o");
if(!empty($esta_contenida)) echo "s&iacute;";
</pre>
<h3><span style="text-decoration: underline;">Variables y arrays</span></h3>
<p><strong>Uso de variables locales</strong></p>
<p>Es m&aacute;s r&aacute;pido y eficiente en memoria trabajar con variables locales dentro de una funci&oacute;n que con una variable de instancia de un objeto, declarada como global o sin definir:</p>
<pre class="code php">class objeto {
&nbsp;&nbsp;&nbsp;private $c;
&nbsp;&nbsp;&nbsp;public function __Construct() {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;c=0;
&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;public function prueba() {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Inicializaci&oacute;n
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;global $a;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$b = 0;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Incremento
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$a++;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$b++;	// M&aacute;s r&aacute;pida
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;c++;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$d++;
&nbsp;&nbsp;&nbsp;}
}
</pre>
<p><strong>Coste de memoria</strong></p>
<p>Deberemos declarar variables que vayamos a usar. Si vamos a usar una variable con valores temporales podemos llamarla $auxiliar y as&iacute; no declarar muchas variables diferentes que s&oacute;lo usamos una vez.</p>
<p>Las variables que ocupen mucho espacio en memoria, por ejemplo un array muy grande, deberemos borrarlas cuando no se vayan usar con la funci&oacute;n unset.</p>
<p><strong>Calcular la longitud de un array antes de recorrerlo</strong></p>
<p>Es m&aacute;s r&aacute;pido recorrer un array de la siguiente forma</p>
<pre class="code php">$icount = count($lista);
for($i=0;$i&lt;$icount;$i++) {
&nbsp;&nbsp;&nbsp;...
}
</pre>
<p>que de &eacute;sta</p>
<pre class="code php">for($i=0;$i&lt;count($lista);$i++) {
&nbsp;&nbsp;&nbsp;...
}
</pre>
<p>ya que el c&aacute;lculo de count se realiza tantas veces como posiciones tenga el array.</p>
<p><strong>Acceder correctamente a un &iacute;ndice no n&uacute;merico</strong></p>
<p>Debemos acceder a los &iacute;ndices no num&eacute;ricos de un array especific&aacute;ndolo con comillas</p>
<pre class="code php">echo $lista[0]['nombre']; // M&aacute;s r&aacute;pido
echo $lista[0][nombre];
</pre>
<h3><span style="text-decoration: underline;">Funciones y objetos</span></h3>
<p><strong>Hacer uso de las funciones predefinidas en PHP</strong></p>
<p>Las funciones incluidas en PHP siempre ser&aacute;n mucho m&aacute;s r&aacute;pidas que las que podamos hacer nosotros</p>
<p><strong>Uso de include y require</strong></p>
<p>Es m&aacute;s r&aacute;pido hacer uso de include o require que include_once o require_once.</p>
<p><strong>Funciones declaradas en objetos hijos son m&aacute;s r&aacute;pidos que los heredados</strong></p>
<p>Una funci&oacute;n declarada en un objeto hijo es m&aacute;s r&aacute;pida que una funci&oacute;n heredada de un objeto padre.</p>
<h3><span style="text-decoration: underline;">Bases de datos</span></h3>
<p><strong>Ordenar los resultados de m&uacute;ltiples consultas</strong></p>
<p>Cuando tenemos que hacer m&uacute;ltiples consultas SQL que terminen siendo pesadas, es mejor realizar el procesamiento de ordenaci&oacute;n mediante la funci&oacute;n <a href="http://es.php.net/manual/en/function.usort.php">usort</a> o similares que mediante SQL. Un ejemplo acerca de esto pod&eacute;is leer en el <a href="http://highscalability.com/blog/2010/3/23/digg-4000-performance-increase-by-sorting-in-php-rather-than.html">siguiente art&iacute;culo</a> de como Digg consigui&oacute; optimizar su web notablemente mediante estos procedimientos.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=31</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/optimizacion-de-codigo-php.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Palo como solución de Business Intelligence: primeros pasos creando informes</title>
			<link>http://www.imaginanet.com/blog/palo-como-solucion-de-business-intelligence-primeros-pasos-creando-informes.html</link>
			<guid>http://www.imaginanet.com/blog/palo-como-solucion-de-business-intelligence-primeros-pasos-creando-informes.html</guid>
			<comments>http://www.imaginanet.com/blog/palo-como-solucion-de-business-intelligence-primeros-pasos-creando-informes.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed, 14 Apr 2010 11:06:41 +0100</pubDate>
					<category><![CDATA[Business Intelligence]]></category>
					<category><![CDATA[Comercio electrónico]]></category>
					<description><![CDATA[El t&eacute;rmino Business Intelligence (BI) o Inteligencia Empresarial es el uso de datos de esa propia empresa para conocer en mayor profundidad los hechos que se producen en los movimientos de clientes, ventas, gastos, etc. de esa manera podremos conocer fuentes de beneficios y gastos en base a los informes que de manera...]]></description>
			<content:encoded><![CDATA[>El t&eacute;rmino <em>Business Intelligence</em> (BI) o Inteligencia Empresarial es el uso de datos de esa propia empresa para conocer en mayor profundidad los hechos que se producen en los movimientos de clientes, ventas, gastos, etc. de esa manera podremos conocer fuentes de beneficios y gastos en base a los informes que de manera sencilla permite generar.
<h3>Jedox Palo</h3>
<p>Palo es un herramienta OLAP (<em><strong>O</strong>nline <strong>A</strong>nalytical <strong>P</strong>rocessing</em>) de BI, que nos permite crear almacenar datos y generar informes en <span style="text-decoration: underline;">hojas de c&aacute;lculo</span> (via Microsoft Excel / OpenOffice) <span style="text-decoration: underline;">o en el navegador Web</span>. Esta herramienta est&aacute; creada por la empresa Jedox y en las aplicaciones b&aacute;sicas son software libre, por lo que nos permite el uso b&aacute;sico a un costo cero, y adem&aacute;s posee de herramientas m&aacute;s avanzadas de pago.</p>
<h3>Instalando lo necesario</h3>
<p>Lo primero ser&aacute; descargarnos de la <a title="P&aacute;gina oficial de Palo de Jedox" href="http://www.jedox.com" target="_blank">p&aacute;gina oficial de Palo</a> el cliente (Palo for Excel o Palo for Open Office) y el el servidor (Palo Suite) e instalarlo primero el cliente y despu&eacute;s el servidor, si no podr&iacute;a haber alg&uacute;n problema en la instalaci&oacute;n. Adem&aacute;s, debemos bajarnos el manual de uso y configuraci&oacute;n para conocer ciertas funcionalidades y configuraciones.</p>
<p>Para esta instalaci&oacute;n, vamos a suponer que la instalaci&oacute;n que hagamos el cliente y el servidor van a estar en el mismo ordenador. Si queremos que el servidor est&eacute; abierto deberemos abrir el puerto en la configuraci&oacute;n del servidor Palo.</p>
<h4>NOTA: Instalando el complemento de Palo en OpenOffice</h4>
<p>Inicialmente la instalaci&oacute;n del addin de Palo lo hice sobre Excel sin problemas en Office XP. Sin embargo not&eacute; que si quer&iacute;amos hacerlo para OpenOffice bajo Linux mostraba un error Java. Tras buscar un poco por Google encontr&eacute; la siguiente p&aacute;gina <a title="Instalando Palo Addin en OpenOffice " href="http://software.krimnet.com/guide/guide-install-palooca-ubuntu-904-netbook-remix.htm" target="_blank">http://software.krimnet.com/guide/guide-install-palooca-ubuntu-904-netbook-remix.htm</a> en la que que explica los paquetes necesarios para instalarlo bajo Debian/Ubuntu.</p>
<h3>Primeros pasos creando informes con Excel o  OpenOffice</h3>
<p>Ahora arrancaremos nuestra hoja de c&aacute;lculo, si es desde Excel deberemos hacerlo haciendo doble click en el icono Palo Excel-Addin del escritorio, y veremos que tenemos una nueva opci&oacute;n que es la pesta&ntilde;a Palo.</p>
<p>Para crear un informe seleccionaremos la opci&oacute;n Pegar Vista. Las opciones b&aacute;sicas que se muestran son las siguientes:</p>
<ul>
<li><span style="text-decoration: underline;">Servidor / Base de datos:</span> nuestro ordenador se puede conectar a varios servidores que contengan diferentes bases de datos. En principio trabajaremos con la base de datos Demo.</li>
<li><span style="text-decoration: underline;">&Aacute;rea de hoja:</span> son las dimensiones de las que disponemos. Podemos definir una dimensi&oacute;n como un dato medible, como por ejemplo: productos, ventas, a&ntilde;os, clientes, etc.</li>
<li><span style="text-decoration: underline;">T&iacute;tulo de columna:</span> dimensi&oacute;n/es que ir&aacute;n en el eje X, en nuestro caso arrastraremos hasta aqu&iacute; la dimensi&oacute;n Years.</li>
<li><span style="text-decoration: underline;">T&iacute;tulo de rengl&oacute;n:</span> dimensi&oacute;n/es que ir&aacute;n en el eje Y, arrastraremos la dimensi&oacute;n Products.</li>
</ul>
<p>Tras seleccionarlo pulsaremos el bot&oacute;n insertar y el informe quedar&aacute; creado.</p>
<p><img title="Esquema de la vista de Palo" src="http://www.imaginanet.com/blog_files/palo/palo_esquema.png" alt="Esquema de la vista de Palo" /></p>
<p>Podemos ver que la vista consisten en dos zonas: la zona superior contiene las dimensiones no escogidas y la inferior contiene las dimensiones escogidas que queremos ver en detalle.</p>
<p>Si hacemos doble click sobre las celdas azules de la zona inferior podemos ir desplegando las secciones de a&ntilde;os o productos, subdividi&eacute;ndose en otras secciones hasta llegar a un elemento final. Mientras, en las celdas amarillas se muestra el valor calculado.</p>
<p>Podemos seleccionar las dimensiones de la zona superior para modificar el informe. Por ejemplo podemos hacer doble click sobre <em>Europe</em> y elegir <em>Spain</em>, todos los datos de la zona inferior que ahora salen son los pertenecientes a Espa&ntilde;a, pudiendo ver en detalle los valores para los productos seg&uacute;n a&ntilde;os.</p>
<p>Por &uacute;ltimo, tras tener el informe que deseamos, si queremos exportarlo y visualizarlo en un ordenador sin que tenga Palo instalado, podemos pulsar la opci&oacute;n <em>Guardar como Instant&aacute;nea</em>, pero este informe no ser&aacute; din&aacute;mico y s&oacute;lo veremos los datos visualizados al generarlo.</p>
<h3>Fuentes y m&aacute;s informaci&oacute;n</h3>
<ul>
<li><span style="text-decoration: underline;">Wikipedia</span>, Business Intelligence: <a title="Wikipedia Business Intelligence" href="http://es.wikipedia.org/wiki/Business_intelligence" target="_blank">http://es.wikipedia.org/wiki/Business_intelligence</a></li>
<li><span style="text-decoration: underline;">Wikipedia</span>, OLAP: <a title="Wikipedia OLAP" href="http://es.wikipedia.org/wiki/OLAP" target="_blank">http://es.wikipedia.org/wiki/OLAP</a></li>
<li><span style="text-decoration: underline;">Jedox</span>, Palo: <a title="Jedox Palo" href="http://www.jedox.com/" target="_blank">http://www.jedox.com/</a></li>
</ul>
<p>&nbsp;</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=30</wfw:commentRss>
			<slash:comments>1</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/palo-como-solucion-de-business-intelligence-primeros-pasos-creando-informes.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Seguridad en PHP básica: escribiendo aplicaciones web seguras</title>
			<link>http://www.imaginanet.com/blog/seguridad-en-php-basica-escribiendo-aplicaciones-web-seguras.html</link>
			<guid>http://www.imaginanet.com/blog/seguridad-en-php-basica-escribiendo-aplicaciones-web-seguras.html</guid>
			<comments>http://www.imaginanet.com/blog/seguridad-en-php-basica-escribiendo-aplicaciones-web-seguras.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed, 31 Mar 2010 09:29:59 +0100</pubDate>
					<category><![CDATA[PHP]]></category>
					<category><![CDATA[Servidores y Seguridad]]></category>
					<description><![CDATA[A continuaci&oacute;n vamos a explicar algunos conceptos b&aacute;sicos de brechas de seguridad m&aacute;s comunes y como solucionarlos mediante PHP permitiendo escribir aplicaciones web un poco m&aacute;s seguras.
Protecci&oacute;n contra la inyecci&oacute;n de c&oacute;digo SQL
Es muy com&uacute;n trabajar contra una base de...]]></description>
			<content:encoded><![CDATA[><p>A continuaci&oacute;n vamos a explicar algunos conceptos b&aacute;sicos de brechas de seguridad m&aacute;s comunes y como solucionarlos mediante PHP permitiendo escribir <a title="Desarrollo de aplicaciones web a medida" href="/programacion-web/aplicaciones-web.html">aplicaciones web</a> un poco m&aacute;s seguras.</p>
<h3>Protecci&oacute;n contra la inyecci&oacute;n de c&oacute;digo SQL</h3>
<p>Es muy com&uacute;n trabajar contra una base de datos (MySQL, PostgreSQL, Oracle, etc.) y estas consultas dependen de par&aacute;metros llegados desde GET o POST, por lo que permitimos al usuario de cada web que en cierta manera modifique las consultas SQL de nuestra web.</p>
<p>Esto podr&iacute;a provocar que un usuario que construya una consulta SQL malintencionada pudiera obtener resultados indeseados, como poder hacer un login en una zona restringida de nuestra web sin conocer ning&uacute;n usuario / contrase&ntilde;a.</p>
<p>Supongamos la siguiente situaci&oacute;n: tenemos un <strong>nombre de usuario pruebas</strong> y una <strong>contrase&ntilde;a clave_pruebas</strong> guardados en base de datos. Para realizar la identificador obtenemos los par&aacute;metros por POST mediante las variables $_POST['usuario']  y $_POST['clave']. Tras ello realizamos la siguiente consulta SQL:</p>
<pre class="code php">mysql_query('select id from usuariosWeb where usuario = '".$_POST['usuario']."' and password = '".$_POST['clave']."'');</pre>
<p>Si existe un usuario con ese nombre y usuario, es que la identificaci&oacute;n es correcta y por tanto debemos hacer el login. Pero sin embargo, si construy&eacute;semos el siguiente par&aacute;metro</p>
<pre class="code php">$_POST['clave'] ="m' or 1='1"</pre>
<p>podemos observar que nos devuelve un valor v&aacute;lido para identificarse conociendo s&oacute;lo el nombre de usuario.</p>
<p>Para solucionarlo, tenemos diversos m&eacute;todos pero lo m&aacute;s c&oacute;modo es substituir las comillas simples y dobles de todos los par&aacute;metros par&aacute;metros POST mediante el siguiente c&oacute;digo:</p>
<pre class="code php">foreach($_POST as $key =&gt; $value) {
	$_POST[$key] = str_replace("'","",$value);
	$_POST[$key] = str_replace('"','',$value);
}
</pre>
<h3><strong>Guardar contrase&ntilde;as, n&uacute;meros de tarjeta de cr&eacute;dito, direcci&oacute;n de correo, etc. de forma segura con MD5 &oacute; SHA1</strong></h3>
<p>Para guardar las contrase&ntilde;as de los usuarios en las bases de datos debemos guardarlas de manera que no puedan ser visibles a simple vista ya que si alguna persona malintencionada consiguiera acceder a la base de datos, adem&aacute;s de conseguir el control de nuestra web, adem&aacute;s tendr&aacute; acceso a informaci&oacute;n sensible de los usuarios que nos visitan.</p>
<p>Para ello podemos dificultarlo mediante los res&uacute;menes <em>hash</em> MD5 o SHA-1, que aunque se tratan de  algoritmos <em>crackeados</em>, por lo menos no mostraremos como texto plano esta informaci&oacute;n.</p>
<p>Ejemplo:</p>
<pre class="code php">$a = "clave_pruebas";

echo "clave original: ".$a." ";

$b = md5($a);

echo "Hash MD5 de la clave original: ".$b." ";

$c = sha1($a);

echo "Hash SHA-1 de la clave original: ".$c." ";
</pre>
<p>Como podemos ver, con ello conseguimos ocultar m&iacute;nimamente la contrase&ntilde;a de cada usuario. Cuando un usuario se identifique con su contrase&ntilde;a, realizaremos el c&aacute;lculo del <em>hash</em> de su contrase&ntilde;a y compararemos contra la base de datos, no el texto plano de la contrase&ntilde;a, si no del <em>hash</em>.</p>
<h3>Uso de variables de sesi&oacute;n y no de <em>cookies</em></h3>
<p>Normalmente, alguna zona de nuestra web necesite acceso mediante usuario y contrase&ntilde;a. Para que el usuario no tenga que introducirlas repetidamente podemos guardarla mediante <em>cookies</em> pero es una pr&aacute;ctica muy insegura ya que si lo hici&eacute;ramos, esta informaci&oacute;n es transmitida mediante la red en texto plano y podr&iacute;a ser le&iacute;da por cualquier persona que realice un <em>sniffing</em> de red o que lea las <em>cookies</em> guardadas en nuestro ordenador mediante un virus o troyano.</p>
<p>Por ello lo mejor es hacer uso de las variables de sesi&oacute;n. Estas variables se guardan en el servidor por lo que en cualquier caso, la informaci&oacute;n transmitida s&oacute;lo es sensible la primera vez que se env&iacute;a y no las sucesivas veces (por tanto esto ser&iacute;a evitable haciendo uso del protocolo HTTPS en vez de HTTP).</p>
<p>Como ejemplo del usuario de variables de sesi&oacute;n, haremos uso de dos archivos. En el primero creamos una variable de sesi&oacute;n:</p>
<pre class="code php">session_start();
$_SESSION['clave'] = "clave_pruebas";
</pre>
<p>y en el segundo mostramos el valor en pantalla.</p>
<pre class="code php">session_start();
echo $_SESSION['clave'];
</pre>
<h3>Suplantaci&oacute;n de sesiones (<em>Session hijacking</em> o <em>Man in the middle</em>)</h3>
<p>Del uso de variables de sesi&oacute;n se deriva otra posible brecha de seguridad que es una persona malintencionada intente suplantar el cliente de cara al servidor. Cuando iniciamos una sesi&oacute;n, creamos una <em>cookie</em> con un identificador &uacute;nico para esa sesi&oacute;n. Si una persona malintencionada interceptase ese identificador &uacute;nico y mandase esa <em>cookie</em> al servidor, podr&iacute;a suplantar nuestra identidad y tener acceso a nuestras zonas restringidas de la web.</p>
<p>Lo soluci&oacute;n ideal ser&iacute;a el uso del protocolo HTTPS que encriptar&iacute;a toda nuestra conexi&oacute;n, pero si esto no es posible,  podemos crear una serie de comprobaciones en las que intentemos asegurarnos de la real identidad de cada usuario.</p>
<p>Para ello podemos guardar una serie de variables de sesi&oacute;n de los datos que el usuario nos proporciona en cada visita, como son la direcci&oacute;n IP o la informaci&oacute;n de su navegador, etc. Si estos cambian significar&iacute;a que es un intento de <em>session hijacking</em> y por tanto es un usuario que realiza un ataque. En el siguiente ejemplo tenemos dos archivos, en el que en el primer archivo realizamos un login satisfactorio y guardamos los datos iniciales de direcci&oacute;n IP y tipo del navegador con el que lo hemos hecho:</p>
<pre class="code php">session_start();
$_SESSION['REMOTE_ADDR'] = $_SERVER['REMOTE_ADDR'];
$_SESSION['HTTP_USER_AGENT'] = $_SERVER['HTTP_USER_AGENT'];
</pre>
<p>En pantallas posteriores, comprobaremos si en cada pantalla los datos actuales de direcci&oacute;n IP y datos del navegador se corresponden con los que se realiz&oacute; el login como usuario en la web:</p>
<pre class="code php">session_start();
if($_SESSION['REMOTE_ADDR'] != $_SERVER['REMOTE_ADDR'] || $_SESSION['HTTP_USER_AGENT'] != $_SERVER['HTTP_USER_AGENT']) {
	exit();
}
</pre>
<h3>Par&aacute;metros GET/POST explotables</h3>
<p>Para finalizar, si hacemos uso de par&aacute;metros GET y POST deberemos comprobar siempre que se correspondan con el usuario actual o si tiene permisos.</p>
<p>Por ejemplo, si tenemos un archivo que edita productos llamado editarProducto.php y recibe el par&aacute;metro GET idproducto, que se corresponde con el identificador &uacute;nico del producto a editar y llamamos al archivo de la siguiente manera:</p>
<pre class="code">http://www.miweb.com/editarProducto.php?idproducto=15</pre>
<p>deberemos comprobar en cualquier caso que en primer lugar seamos un usuario registrado y <em>logueado</em> y despu&eacute;s que el producto de identificador &uacute;nico 15 corresponde a uno de los productos del usuario <em>logueado</em>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=29</wfw:commentRss>
			<slash:comments>4</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/seguridad-en-php-basica-escribiendo-aplicaciones-web-seguras.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Un editor de textos web: TinyMCE</title>
			<link>http://www.imaginanet.com/blog/un-editor-de-textos-web-tinymce.html</link>
			<guid>http://www.imaginanet.com/blog/un-editor-de-textos-web-tinymce.html</guid>
			<comments>http://www.imaginanet.com/blog/un-editor-de-textos-web-tinymce.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue, 23 Mar 2010 12:00:45 +0100</pubDate>
					<category><![CDATA[JavaScript]]></category>
					<description><![CDATA[TinyMCE es una aplicaci&oacute;n escrita en Javascript que nos permite crear un editor de textos en nuestra web con una gran variedad de personalizaci&oacute;n y con caracter&iacute;sticas (que lo hacen interesante para usarlo en sistemas de gesti&oacute;n de contenido web), como pueden ser: 

Open Source
Ligero de peso
Ampliable...]]></description>
			<content:encoded><![CDATA[>TinyMCE es una aplicaci&oacute;n escrita en Javascript que nos permite crear un editor de textos en nuestra web con una gran variedad de personalizaci&oacute;n y con caracter&iacute;sticas (que lo hacen interesante para usarlo en <a title="imaginaCMS, sistema de gesti&oacute;n de contenido web a medida" href="/programacion-web/gestor-de-contenidos-web.html">sistemas de gesti&oacute;n de contenido web</a>), como pueden ser:<br /> 
<ul>
<li>Open Source</li>
<li>Ligero de peso</li>
<li>Ampliable mediante plugins</li>
<li>Usable en todos los navegadores.</li>
</ul>
En nuestro caso, vamos a configurarlo de tal manera que tenga el aspecto de un editor de textos simple cubriendo las funcionalidades b&aacute;sicas del editor.<br /><br />El primer paso ser&aacute; descargarlo de la <a title="editor de textos web" href="http://tinymce.moxiecode.com/" target="_blank">web oficial</a> y descomprimirlo en el disco duro. Crearemos un archivo de extensi&oacute;n html en la carpeta descomprimida con el siguiente c&oacute;digo:<br />
<pre class="code">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;head&gt;
&lt;title&gt;Ejemplo de un editor de textos Web simple con TinyMCE&lt;/title&gt;

&lt;!-- TinyMCE --&gt;

&lt;script type="text/javascript" src="jscripts/tiny_mce/tiny_mce.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;
	tinyMCE.init({
		mode : "exact",
		elements : "editor_texto",
		theme : "advanced",
		theme_advanced_buttons1:"bold,italic,underline,|,undo,redo,|,bullist,numlist",
		theme_advanced_buttons2:"",
		theme_advanced_buttons3:""

	});
&lt;/script&gt;
&lt;!-- /TinyMCE --&gt;

&lt;/head&gt;
&lt;body&gt;

&lt;h3&gt;Editor de textos Web&lt;/h3&gt;

&lt;textarea id="editor_texto" name="editor_texto" style="width: 30%;"&gt;Texto de prueba&lt;/textarea&gt;

&lt;/body&gt;
&lt;/html&gt;
</pre>
Si visualizamos el archivo en cualquier navegador web, podemos observar que tenemos un editor de textos que podemos usar en nuestra p&aacute;gina web. A continuaci&oacute;n explicaremos las opciones de configuraci&oacute;n que hemos usado:<br /> 
<ul>
<li><strong>mode "exact"</strong> y <strong>elements "editor_texto"</strong>: con estas dos l&iacute;neas indicamos que queremos aplicar el editor de textos s&oacute;lo al elemento de la web de identificador editor_texto</li>
<li><strong>theme "advanced"</strong>: elegimos utilizar el tema avanzado del editor para poder seleccionar los botones concretos que queremos que aparezcan mediante <strong>theme_advanced_buttons1</strong>, <strong>theme_advanced_buttons2</strong> y <strong>theme_advanced_buttons3</strong> donde seleccionaremos dentro de las tres posibles filas de botones del editor, que botones aparecer&aacute;n. En este caso negrita, cursiva, subrayado, una separaci&oacute;n, deshacer, rehacer, una separaci&oacute;n, lista y lista numerada respectivamente.</li>
</ul>
<br />]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=28</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/un-editor-de-textos-web-tinymce.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Cómo utilizar PayPal para realizar compras en tu web</title>
			<link>http://www.imaginanet.com/blog/como-utilizar-paypal-para-realizar-compras-en-tu-web.html</link>
			<guid>http://www.imaginanet.com/blog/como-utilizar-paypal-para-realizar-compras-en-tu-web.html</guid>
			<comments>http://www.imaginanet.com/blog/como-utilizar-paypal-para-realizar-compras-en-tu-web.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed, 17 Feb 2010 09:32:57 +0100</pubDate>
					<category><![CDATA[Comercio electrónico]]></category>
					<description><![CDATA[Vamos a explicar c&oacute;mo llamar al API de PayPal para realizar pagos en tu p&aacute;gina web. En primer lugar deberemos crear una cuenta como desarrollador de PayPal Sandbox (https://developer.paypal.com/) que usaremos para verificar que lo hacemos de manera correcta antes de hacerlo funcionar en la tienda virtual de nuestra...]]></description>
			<content:encoded><![CDATA[><p>Vamos a explicar c&oacute;mo llamar al <strong>API de PayPal</strong> para realizar pagos en tu p&aacute;gina web. En primer lugar deberemos crear una cuenta como desarrollador de <strong>PayPal Sandbox</strong> (<a href="https://developer.paypal.com/">https://developer.paypal.com/</a>) que usaremos para verificar que lo hacemos de manera correcta antes de hacerlo funcionar en la <a title="Desarrollo de aplicaciones e-commerce a medida" href="/diseno-web/tiendas-virtuales.html">tienda virtual</a> de nuestra p&aacute;gina web.</p>
<p>Tras hacerla y meternos en nuestra cuenta de desarrollador, deberemos seleccionar la opci&oacute;n <em>Create a preconfigured buyer or seller account</em> donde rellenaremos con nuestros datos el formulario teniendo en cuenta que debe ser una cuenta de vendedor.</p>
<p>Una vez creada, entraremos a nuestro listado de cuentas de PayPal Sandbox. Estas cuentas no son cuentas reales de PayPal y s&oacute;lo funcionar&aacute;n dentro de su Sandbox. Para entrar en ella pulsaremos el bot&oacute;n de <em>Enter Sandbox Test Site</em> y podremos introducir el usuario y contrase&ntilde;a para esta cuenta de prueba. Una vez dentro podemos observar que es como si fuera una cuenta de PayPal  pero los pagos que se hagan a ella no ser&aacute;n reales.</p>
<h4>Ejemplo de pago con el API de PayPal</h4>
<p>Para realizar el pago utilizaremos un documento HTML en el que le pasaremos los par&aacute;metros que PayPal necesita (importe, c&oacute;digo de venta, etc.) y otros opcionales como los datos del usuario que compra para que le aparezcan rellenados en el formulario de pago. Un ejemplo ser&iacute;a el siguiente:</p>
<pre class="code">&lt;html&gt;

&lt;head&gt;

&lt;title&gt;Ejemplo de pago mediante la API de PayPal&lt;/title&gt;

&lt;/head&gt;

&lt;body&gt;

&lt;form name='formTpv' method='post' action='https://www.sandbox.paypal.com/cgi-bin/webscr'&gt;

	&lt;input type='hidden' name='cmd' value='_xclick'&gt;
	&lt;input type='hidden' name='business' value='mi_cuenta_sandbox@mi_pagina.com'&gt;
	&lt;input type='hidden' name='item_name' value='Nueva compra en mi web'&gt;
	&lt;input type='hidden' name='item_number' value='VENTA-X2561'&gt;
	&lt;input type='hidden' name='amount' value='10.15'&gt;
	&lt;input type='hidden' name='page_style' value='primary'&gt;
	&lt;input type='hidden' name='no_shipping' value='1'&gt;
	&lt;input type='hidden' name='return' value='http://mi_pagina/exito.html'&gt;
	&lt;input type='hidden' name='rm' value='2'&gt;
	&lt;input type='hidden' name='cancel_return' value='http://mi_pagina/cancelada.html'&gt;
	&lt;input type='hidden' name='no_note' value='1'&gt;
	&lt;input type='hidden' name='currency_code' value='EUR'&gt;
	&lt;input type='hidden' name='cn' value='PP-BuyNowBF'&gt;
	&lt;input type='hidden' name='custom' value=''&gt;
	&lt;input type='hidden' name='first_name' value='NOMBRE'&gt;
	&lt;input type='hidden' name='last_name' value='APELLIDOS'&gt;
	&lt;input type='hidden' name='address1' value='DIRECCI&Oacute;N'&gt;
	&lt;input type='hidden' name='city' value='POBLACI&Oacute;N'&gt;
	&lt;input type='hidden' name='zip' value='C&Oacute;DIGO POSTAL'&gt;
	&lt;input type='hidden' name='night_phone_a' value=''&gt;
	&lt;input type='hidden' name='night_phone_b' value='TEL&Eacute;FONO'&gt;
	&lt;input type='hidden' name='night_phone_c' value=''&gt;
	&lt;input type='hidden' name='lc' value='es'&gt;
	&lt;input type='hidden' name='country' value='ES'&gt;
&lt;/form&gt;
&lt;script type='text/javascript'&gt;
	document.formTpv.submit();
&lt;/script&gt;

&lt;/body&gt;

&lt;/html&gt;
</pre>
<p>La direcci&oacute;n de llamada del formulario de pruebas es <span style="text-decoration: underline;">https://www.sandbox.paypal.com/cgi-bin/webscr</span> pero al pasar a ventas reales deberemos indicar <span style="text-decoration: underline;">https://www.paypal.com/cgi-bin/webscr</span></p>
<p>Como podemos ver, existente multitud de par&aacute;metros en el formulario que son f&aacute;ciles de ver cuales son su prop&oacute;sito (nombre, direcci&oacute;n, etc.). A continuaci&oacute;n detallamos los m&aacute;s importantes o que podemos tener duda de qu&eacute; son realmente:</p>
<ul>
<li><strong>business:</strong> indicaremos la cuenta de PayPal asociada al vendedor. Mientras estemos de pruebas indicaremos la cuenta de pruebas del Sandbox, pero para ventas reales deberemos indicar nuestra cuenta de vendedor.</li>
<li><strong>item_name:</strong> t&iacute;tulo que aparecer&aacute; en la pantalla de pago.</li>
<li><strong>item_number:</strong> c&oacute;digo de la venta, actuar&aacute; como identificador &uacute;nico de cada venta.</li>
<li><strong>amount:</strong> importe a pagar, donde si hay decimales no podr&aacute;n indicarse con una coma ni con m&aacute;s de dos n&uacute;meros.</li>
<li><strong>return:</strong> p&aacute;gina de vuelta a nuestra web indicando &eacute;xito en el pago.</li>
<li><strong>cancel_return:</strong> p&aacute;gina de vuelta a nuestra web indicando que no se realiz&oacute; el pago por que el usuario lo cancel&oacute;.</li>
<li><strong>currency_code:</strong> c&oacute;digo de la moneda usada en el pago. Para el caso del euro es EUR.</li>
<li><strong>lc:</strong> idioma de la pantalla de pago.</li>
<li><strong>country:</strong> c&oacute;digo ISO del pa&iacute;s del cliente.</li>
</ul>
<h3>Art&iacute;culos relacionados</h3>
<ul>
<li><a title="Pagos y transferencias masivas con PayPal" href="http://www.imaginanet.com/blog/pagos-en-serie-de-paypal.html">Pagos en serie de PayPal</a></li>
<li><a title="PayPal Instant Payment Notification" href="http://www.imaginanet.com/blog/controlar-los-pagos-por-paypal-mediante-notificacion-de-pago-instantanea.html">Controlar los pagos por PayPal mediante Notificaci&oacute;n de Pago Instant&aacute;nea</a></li>
</ul>
<ul>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=27</wfw:commentRss>
			<slash:comments>42</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/como-utilizar-paypal-para-realizar-compras-en-tu-web.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Usando AJAX: Un simple ejemplo con PHP y jQuery.</title>
			<link>http://www.imaginanet.com/blog/usando-ajax-un-simple-ejemplo-con-php-y-jquery.html</link>
			<guid>http://www.imaginanet.com/blog/usando-ajax-un-simple-ejemplo-con-php-y-jquery.html</guid>
			<comments>http://www.imaginanet.com/blog/usando-ajax-un-simple-ejemplo-con-php-y-jquery.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed, 10 Feb 2010 10:48:36 +0100</pubDate>
					<category><![CDATA[jQuery]]></category>
					<category><![CDATA[Ajax]]></category>
					<description><![CDATA[Descrito de una manera muy resumida, AJAX es una tecnolog&iacute;a que nos permite realizar acciones en una p&aacute;gina web que necesiten respuesta del servidor sin recargarla. Con ello conseguimos que nuestra web sea din&aacute;mica y por tanto obtener un dise&ntilde;o m&aacute;s atractivo. Algunos ejemplos de lo que podemos...]]></description>
			<content:encoded><![CDATA[>Descrito de una manera muy resumida, <a href="http://es.wikipedia.org/wiki/AJAX">AJAX</a> es una tecnolog&iacute;a que nos permite realizar acciones en una p&aacute;gina web que necesiten respuesta del servidor sin recargarla. Con ello conseguimos que nuestra web sea din&aacute;mica y por tanto obtener un dise&ntilde;o m&aacute;s atractivo. Algunos ejemplos de lo que podemos hacer:                 
<ul>
<li>Un enlace que compruebe si un valor existe ya en una base de datos.</li>
<li>Completar un campo de texto de b&uacute;squeda con valores sugeridos por nuestra web.</li>
<li>Un chat web</li>
<li>etc.</li>
</ul>
<p>En este art&iacute;culo vamos a describir como realizar una sencilla llamada AJAX a una fichero externo que ejecutar&aacute; un proceso (una suma entre dos valores enviados mediante POST) y nos devolver&aacute; la salida correspondiente apoy&aacute;ndonos con la librer&iacute;a <a href="http://jquery.com/">jQuery</a>, que aunque no es necesario su uso, lo haremos sobre ella para aprovechar la potencia que nos proporciona. Se podr&iacute;a decir que es el t&iacute;pico <em>Hola mundo</em> en AJAX.</p>
<p>El c&oacute;digo se compone de dos archivos: un archivo donde mostraremos los formularios con datos de entrada y otro con el archivo de procesamiento.</p>
<p>A continuaci&oacute;n mostramos el c&oacute;digo del fichero de entrada de datos (habr&aacute; que tener cuidado con escribir correctamente la ruta a la librer&iacute;a jQuery):</p>
<pre class="code">&lt;html&gt;

&lt;head&gt;

&lt;title&gt;Ejemplo sencillo de AJAX&lt;/title&gt;

&lt;script type="text/javascript" src="/js/jquery.js"&gt;&lt;/script&gt;

&lt;script&gt;
function realizaProceso(valorCaja1, valorCaja2){
        var parametros = {
                "valorCaja1" : valorCaja1,
                "valorCaja2" : valorCaja2
        };
        $.ajax({
                data:  parametros,
                url:   'ejemplo_ajax_proceso.php',
                type:  'post',
                beforeSend: function () {
                        $("#resultado").html("Procesando, espere por favor...");
                },
                success:  function (response) {
                        $("#resultado").html(response);
                }
        });
}
&lt;/script&gt;

&lt;/head&gt;

&lt;body&gt;

Introduce valor 1

&lt;input type="text" name="caja_texto" id="valor1" value="0"/&gt; 


Introduce valor 2

&lt;input type="text" name="caja_texto" id="valor2" value="0"/&gt;

Realiza suma

&lt;input type="button" href="javascript:;" onclick="realizaProceso($('#valor1').val(), $('#valor2').val());return false;" value="Calcula"/&gt;

&lt;br/&gt;

Resultado: &lt;span id="resultado"&gt;0&lt;/span&gt;

&lt;/body&gt;

&lt;/html&gt;

</pre>
<p>&nbsp;</p>
<p>En este c&oacute;digo, utilizamos los id de las cajas de texto para pasarle sus valores a la funci&oacute;n <em>realizaProceso</em>. En esta funci&oacute;n recogemos los valores de entrada en un array parametros y enviamos mediante AJAX especificando el par&aacute;metro <em>data</em> (datos que mandamos), <em>url</em> (direcci&oacute;n del archivo de proceso) y <em>type</em> (POST o GET).</p>
<p>Por &uacute;ltimo vemos que tenemos dos eventos: <em>beforeSend</em> y <em>success</em> donde podemos indicar la acci&oacute;n a realizar mientras se procesan los datos y tras terminar de procesarlos (en este caso jugar con el contenido HTML del id resultado).</p>
<p>Ahora vemos el archivo de procesamiento de datos (<em>ejemplo_ajax_proceso.php</em>) que &uacute;nicamente suma los datos recibidos por POST:</p>
<pre class="code php">
&lt;?php 
$resultado = $_POST['valorCaja1'] + $_POST['valorCaja2']; 
echo $resultado;
?&gt;
</pre>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=26</wfw:commentRss>
			<slash:comments>20</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/usando-ajax-un-simple-ejemplo-con-php-y-jquery.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Crear plugins de jquery</title>
			<link>http://www.imaginanet.com/blog/plugins-jquery.html</link>
			<guid>http://www.imaginanet.com/blog/plugins-jquery.html</guid>
			<comments>http://www.imaginanet.com/blog/plugins-jquery.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Sat,  6 Feb 2010 21:09:29 +0100</pubDate>
					<category><![CDATA[JavaScript]]></category>
					<category><![CDATA[jQuery]]></category>
					<description><![CDATA[Jquery es una de las bibliocas javascript m&aacute;s simples e utilizadas. Crear plugins para esta biblioteca es muy sencillo. Vamos a ver los pasos necesarios: 

Primero tenemos que incluir la biblioteca jquery en la cabecera. Nos la descargamos desde su web y la a&ntilde;adimos de la siguiente forma:
			
		


Luego creamos...]]></description>
			<content:encoded><![CDATA[><a href="http://www.jquery.com" target="_blank">Jquery</a> es una de las bibliocas javascript m&aacute;s simples e utilizadas. Crear plugins para esta biblioteca es muy sencillo. Vamos a ver los pasos necesarios:<br /><br /> 
<ul>
<li>Primero tenemos que incluir la biblioteca jquery en la cabecera. Nos la descargamos desde su web y la a&ntilde;adimos de la siguiente forma:<br />
<pre class="code">			<script src="/ruta_a_jquery/jquery.js" type="text/javascript"></script>
		</pre>
</li>
<li>
<p>Luego creamos nuestro archivo del plugin, que luego tambi&eacute;n tendremos que a&ntilde;adirlo en la cabecera para utilizarlo.</p>
<pre class="code">			$.fn.duplicar = function () {
				this.each(function () {
					var html = "<br />"+$(this).html();
					$(this).append(html);
				});
			}
		</pre>
<p>Lo que hace este plugin es duplicar el contenido de los elementos seleccionados.<br /> $.fn es el objeto de jquery que contiene las funciones que nosotros le definimos. Dentro del c&oacute;digo de la funci&oacute;n, el this es un array con los elementos seleccionados con jquery. Con la funci&oacute;n each, recorremos ese array.</p>
</li>
<li> Para utilizarlo:
<pre class="code">			$("div.doble").duplicar();
		</pre>
<p>As&iacute; duplicar&iacute;amos el contenido de todos los divs con la clase "doble"</p>
</li>
</ul>
<p>&Eacute;ste es un ejemplo muy b&aacute;sico. Para m&aacute;s informaci&oacute;n s&oacute;lo hay que pasarse por la web de jquery la cual tiene una bastante buena <a href="http://docs.jquery.com/Main_Page" target="_blank">documentaci&oacute;n</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=25</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/plugins-jquery.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Display inline-block e internet explorer.</title>
			<link>http://www.imaginanet.com/blog/display-inline-block-e-internet-explorer.html</link>
			<guid>http://www.imaginanet.com/blog/display-inline-block-e-internet-explorer.html</guid>
			<comments>http://www.imaginanet.com/blog/display-inline-block-e-internet-explorer.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Sat,  6 Feb 2010 19:41:50 +0100</pubDate>
					<category><![CDATA[XHTML]]></category>
					<category><![CDATA[CSS]]></category>
					<category><![CDATA[Internet Explorer]]></category>
					<category><![CDATA[Navegadores]]></category>
					<description><![CDATA[La propiedad display de css (en la versi&oacute;n 2.1), puede contener un valor muy interesante, inline-block. Con este valor conseguimos que el elemento con esa propiedad se comporte como una caja, pero mostrandose en la misma l&iacute;nea, como si tuviese display: inline.
&iquest;Y esto de qu&eacute; nos sirve?, pues si no...]]></description>
			<content:encoded><![CDATA[><p>La propiedad display de css (en la versi&oacute;n 2.1), puede contener un valor muy interesante, <strong>inline-block</strong>. Con este valor conseguimos que el elemento con esa propiedad se comporte como una caja, pero mostrandose en la misma l&iacute;nea, como si tuviese display: inline.</p>
<p>&iquest;Y esto de qu&eacute; nos sirve?, pues si no usamos esta propiedad tendr&iacute;amos que a&ntilde;adirle a la caja un "float: left", por ejemplo, pero esto trae unas consecuencias, a veces, muy molestas. Por ejemplo, si queremos mostrar contenido dividido en cajas y que se muestren filas de 3 cajas, si &eacute;stas var&iacute;an con la altura, pasar&iacute;a esto:</p>
<img src="http://www.imaginanet.com/blog_files/inline-block/confloat.png" alt="con float" />
<p>Esto pasa porque al tener "float:left", las cajas "buscan" el primer espacio disponible a su izquierda. &Eacute;sto podr&iacute;a solucionarse desde el html, a&ntilde;adiendo cada tres cajas un elemento que tenga la propiedad "clear:both". Pero si queremos que el n&uacute;mero de cajas por fila var&iacute;e dependiendo de la anchura de nuestra ventana del navegador, ya no valdr&iacute;a esta soluci&oacute;n. Adem&aacute;s si usamos la propiedad "display: inline-block", podemos alinear las cajas arriba, abajo, al centro , con tan solo cambiar la propiedad vertical-align. Si ponemos "vertical-align:top", tendremos esto:</p>
<img src="http://www.imaginanet.com/blog_files/inline-block/deseable.png" alt="con float" />
<h2>Hacks para conseguir "display: inline-block" en internet explorer 6 y 7</h2>
<p>Nuestros amigos Ie6 e Ie7, como siempre, mostrandonos su tecnolog&iacute;a punta (recordemos que &eacute;sto es CSS 2.1), no implementan esta propiedad completamente.</p>
<p>De todas formas es muy sencillo hacerlo funcionar con un peque&ntilde;o truco. En vez de usar "display: inline-block", tendr&iacute;amos que ponerles "display: inline" y a&ntilde;adirles la propiedad "zoom:1"</p>
<pre class="code">	div.block {
		display: inline-block;
		#display: inline;
		_display: inline;
		zoom: 1;
	}
</pre>
<p>La "#" es un hack para que solo aplique esa propiedad IE7 y el "_" para IE6. La propiedad zoom solo la cojeran esos 2 navegadores, puesto que no es est&aacute;ndar, haciendo que el elemento se comporte como una caja.</p>
<a href="http://www.imaginanet.com/blog_files/inline-block/inline-block.htm" target="_blank">Ver ejemplo en funcionamiento.</a><br /> <a href="http://www.imaginanet.com/blog_files/inline-block/inline-block.htm" target="_blank"><img src="http://www.imaginanet.com/blog_files/inline-block/ejemplo.png" alt="con float" /></a>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=24</wfw:commentRss>
			<slash:comments>6</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/display-inline-block-e-internet-explorer.html</feedburner:origLink>
		</item>
				
		<item>
			<title>HTML 5 y el famoso tag "video"</title>
			<link>http://www.imaginanet.com/blog/html-5-y-el-famoso-tag-video.html</link>
			<guid>http://www.imaginanet.com/blog/html-5-y-el-famoso-tag-video.html</guid>
			<comments>http://www.imaginanet.com/blog/html-5-y-el-famoso-tag-video.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Thu, 28 Jan 2010 08:27:06 +0100</pubDate>
					<category><![CDATA[HTML5]]></category>
					<category><![CDATA[Navegadores]]></category>
					<description><![CDATA[HTML5 ha llegado, y aunque sea pronto para que el usuario pueda disfrutar de todo su potencial, los programadores hace ya unos meses que podemos ir viendo como ser&aacute;n las webs de dentro de unos a&ntilde;os. El tag &lt;video/&gt; es el que m&aacute;s revuelo est&aacute; teniendo, y no solo por su integraci&oacute;n en sitios...]]></description>
			<content:encoded><![CDATA[>HTML5 ha llegado, y aunque sea pronto para que el usuario pueda disfrutar de todo su potencial, los programadores hace ya unos meses que podemos ir viendo como ser&aacute;n las webs de dentro de unos a&ntilde;os.<br /><br /> El tag &lt;video/&gt; es el que m&aacute;s revuelo est&aacute; teniendo, y no solo por su integraci&oacute;n en sitios como Youtube o Vimeo, sin&oacute; por los est&aacute;ndares soportados por cada navegador.<br /><br /> Mozilla se ha puesto firme al respecto y ha anunciado que no piensa incluir el estandar h264, ya que este no es un codec abierto y existen otros que si lo son y pueden ofrecer mejor calidad.<br /> Esto nos deja en una situaci&oacute;n en la que los navegadores web que actualmente soportan el tag  de HTML5:<br /><br /> &bull;Presto/Opera: HTML5 mediante GStreamer (incluye s&oacute;lo Ogg/Theora).<br /> &bull;WebKit/Chrome: HTML5 mediante ffmpeg (Ogg/Theora y H.264/MP4).<br /> &bull;Gecko/Firefox: HTML5 con Ogg/Theora.<br /> &bull;WebKit/Epiphany: HTML5 mediante GStreamer (Ogg/Theora garantizado).<br /> &bull;WebKit/Safari: HTML5 mediante QuickTime (H.264/MOV/M4V, puede reproducir Ogg/Theora con XiphQT components).<br /><br /> Nos encontramos frente a una guerra en la que empresas como Apple y Microsoft, forman parte de la MPEG-LA, empresa que tiene la patente del codec h264, frente a Mozilla (por el momento) que se ha posicionado en contra de usar una tecnolog&iacute;a propietaria que condicione la red.<br /><br />Por su parte, Youtube no da su brazo a torcer. A pesar de que hay decenas de peticiones y de comentarios pidiendo el soporte de Ogg Theora, no sueltan prenda al respecto.]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=23</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/html-5-y-el-famoso-tag-video.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Menú desplegable con CSS</title>
			<link>http://www.imaginanet.com/blog/menu-desplegable-con-css.html</link>
			<guid>http://www.imaginanet.com/blog/menu-desplegable-con-css.html</guid>
			<comments>http://www.imaginanet.com/blog/menu-desplegable-con-css.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 28 Dec 2009 18:28:03 +0100</pubDate>
					<category><![CDATA[XHTML]]></category>
					<category><![CDATA[CSS]]></category>
					<description><![CDATA[Vamos a crear un men&uacute; desplegable utilizando &uacute;nicamente CSS. En principio no necesitaremos nada de javascript. Este men&uacute; funcionar&aacute; en las &uacute;ltimas versiones de firefox, chrome, safari, opera, e internet explorer (versi&oacute;n 8). Para que funcione en Internet explorer 7 s&oacute;lo...]]></description>
			<content:encoded><![CDATA[>Vamos a crear un men&uacute; desplegable utilizando &uacute;nicamente <a href="/diseno-web/desarrollo-web/maquetacion-html-css.html" target="_blank">CSS</a>. En principio no necesitaremos nada de javascript. Este men&uacute; funcionar&aacute; en las &uacute;ltimas versiones de firefox, chrome, safari, opera, e internet explorer (versi&oacute;n 8). Para que funcione en Internet explorer 7 s&oacute;lo necesitaremos a&ntilde;adir unos peque&ntilde;os <a href="#hacks">hacks</a>. En explorer 6 necesitaremos utilizar javascript, puesto que este navegador no reconoce el selector ":hover" en elementos que no sean "a", los cuales no pueden contener elementos de tipo bloque dentro, si queremos cumplir los est&aacute;ndares, claro. Al final se explican los <a href="#hacks">hacks necesarios</a>.<br /><br /> Para comenzar definimos la estructura del men&uacute;, bas&aacute;ndonos en listas desordenadas (ul, li):<br /><br />
<pre class="code"><ul class="menu">
	<li>
		<a class="item" href="#">Item 1</a>
		<ul>
			<li>
				<a class="item" href="#">Option 1</a>
			</li>
			<li>
				<a class="item" href="#">Option 2</a>
			</li>
		</ul>
	</li>
</ul>
</pre>
<br /> Cada li tendr&aacute; un "a" con clase "item", y si queremos a&ntilde;adirle un submen&uacute;, un "ul", en este caso le tendremos que a&ntilde;adir la clase more al "a" por cuesti&oacute;n de estilo, as&iacute; mostrar&aacute; una flecha a la derecha, indicando que hay un submen&uacute; oculto. <br /><br /> Ahora tenemos que ocultar los submen&uacute;s desde la hoja de estilos, para eso le a&ntilde;adimos la propiedad "display:none" a los "ul" dentro del "ul" principal: <br /><br />
<pre class="code">ul.menu {
	display: inline-block;
	margin: 0;
	padding: 0;
	list-style-type: none;
	white-space: nowrap;
}
ul.menu ul {
	display: none;
}
ul.menu li {
	position: relative;
	display: inline-block;
}
ul.menu ul li {
	display: block;
}
</pre>
<br /> A los li del primer nivel les aplicamos la propiedad "display: inline-block", para que se muesten en una sola l&iacute;nea, a los dem&aacute;s les ponemos "display:block". El primer ul tiene la propiedad "white-space: nowrap", para forzar a que sus "li" no salten de l&iacute;nea. Ahora ya tenemos los submen&uacute;s ocultos, falta hacerlos aparecer:<br /><br />
<pre class="code">ul.menu &gt; li:hover &gt; ul {
	display: block;
	position: absolute;
	top: 100%;
	left: 0;
}

ul.menu ul li:hover &gt; ul {
	display: block;
	position: absolute;
	top: 0;
	left: 100%;
}
</pre>
<br /> Los submen&uacute;s est&aacute;n posicionados absolutamente con respecto al "li" que los contiene, ya que &eacute;stos est&aacute;n posicionados relativamente. En el caso de los submen&uacute;s del primer nivel los colocamos con "top:100%,left:0", para que salgan justo debajo del item padre. Para los dem&aacute;s submen&uacute;s ponemos "top: 0; left: 100%", con lo que saldr&aacute;n justo a la derecha del item padre.<br /><br /> Al final nos quedar&aacute; algo parecido a esto:<br /><br />
<div><img title="men&uacute;" src="/blog_files/menu-css/captura.png" alt="men&uacute;" /></div>
<br /> <br /><strong></strong>
<h3><strong><a name="hacks"></a></strong>Hacks para Internet explorer 6 y 7:</h3>
<br /> <a href="/blog/display-inline-block-e-internet-explorer.html">En Internet explorer 6 y 7, no funciona la propiedad "display: inline-block" en elementos que tienen por defecto display: block</a>, pero con un sencillo truco podemos conseguir el mismo efecto:<br /><br />
<pre class="code">ul.menu li {
	position: relative;
	display: inline-block;
	_display: inline;
	_zoom: 1;
	#display: inline;
	#zoom: 1;
}
</pre>
<br /> Para hacer que los submen&uacute;s aparezcan en internet explorer 6, tendremos que utilizar javascript, como coment&aacute;bamos al principio. Utilizando la librer&iacute;a jquery, por ejemplo, har&iacute;amos lo siguiente:<br /><br />
<pre class="code">$("ul.submenu li").hover(
	function () {
		$(this).addClass("hover");
	},
	function () {
		$(this).removeClass("hover");
	}
);
</pre>
<br /> Como tampoco funciona el selector "&gt;" en IE6, necesitaremos hacer unos cambios en la hoja de estilos: <br /><br />
<pre class="code">ul.menu li.hover ul {
	display: block;
	position: absolute;
	top: 100%;
	left: 0;
}

ul.menu li.hover ul ul {
	display: none;
}

ul.menu ul li.hover ul {
	display: block;
	position: absolute;
	top: 0;
	left: 100%;
}

ul.menu ul li.hover ul ul {
	display: none;
}
</pre>
<br /> Para probar este men&uacute; accede <a href="/blog_files/menu-css/index.htm" target="&quot;_blank&quot;">aqu&iacute;</a>.<br /> Para descargarte los archivos utilizados haz click <a href="/blog_files/menu-css/menu-css.zip">aqu&iacute;</a>.<br />]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=22</wfw:commentRss>
			<slash:comments>6</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/menu-desplegable-con-css.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Creando un buscador para tu página usando Yahoo! Query Language</title>
			<link>http://www.imaginanet.com/blog/creando-un-buscador-para-tu-pagina-usando-yahoo-query-language.html</link>
			<guid>http://www.imaginanet.com/blog/creando-un-buscador-para-tu-pagina-usando-yahoo-query-language.html</guid>
			<comments>http://www.imaginanet.com/blog/creando-un-buscador-para-tu-pagina-usando-yahoo-query-language.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Thu, 24 Dec 2009 11:01:31 +0100</pubDate>
					<category><![CDATA[Buscadores]]></category>
					<description><![CDATA[Hace un par de semanas vi un vídeo tutorial en el que se muestra la potencia y la facilidad de uso de Yahoo! Query Language donde creando un código HTML y Javascript muy simple obtiene como respuesta (por cierto una respuesta muy rápida) la búsqueda en los buscadores de Yahoo!, Google y Bing. El vídeo en cuestión es el...]]></description>
			<content:encoded><![CDATA[><!-- 		@page { margin: 2cm } 		P { margin-bottom: 0.21cm } 		A:link { so-language: zxx } -->
<p style="margin-bottom: 0cm;">Hace un par de semanas vi un <a href="http://ajaxian.com/archives/three-search-engines-one-interface-25-minutes-live-code">vídeo tutorial</a> en el que se muestra la potencia y la facilidad de uso de <a href="http://developer.yahoo.com/yql/">Yahoo! Query Language</a> donde creando un código HTML y Javascript muy simple obtiene como respuesta (por cierto una respuesta muy rápida) la búsqueda en los buscadores de Yahoo!, Google y Bing. El vídeo en cuestión es el siguiente:</p>
<p style="margin-bottom: 0cm;"> </p>
<div>
<object width="400" height="275" data="http://vimeo.com/moogaloop.swf?clip_id=8075850&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" type="application/x-shockwave-flash">
<param name="data" value="http://vimeo.com/moogaloop.swf?clip_id=8075850&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" />
<param name="allowfullscreen" value="true" />
<param name="allowscriptaccess" value="always" />
<param name="src" value="http://vimeo.com/moogaloop.swf?clip_id=8075850&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" />
</object>
</div>
<p><a href="http://vimeo.com/8075850">Building a search mashup with YQL using Google, Yahoo and Bing - live :)</a> from <a href="http://vimeo.com/user574521">Christian Heilmann</a> on <a href="http://vimeo.com">Vimeo</a>.</p>
<!-- 		@page { margin: 2cm } 		P { margin-bottom: 0.21cm } 		A:link { so-language: zxx } -->
<p style="margin-bottom: 0cm;">Tras verlo empecé a realizar pruebas con la <a href="http://developer.yahoo.com/yql/console/">consola de YQL</a> para ver que nos permite hacer esta API y realicé la primera consulta:</p>
<pre class="code">select * from search.web(20) where query="PHP";</pre>
Después probé a realizar la misma búsqueda en todos los buscadores:<br />
<pre class="code">select * from query.multi where queries='
  select *  from microsoft.bing.web(20) where query="PHP";
  select *  from search.web(20) where query="PHP";
  select *  from google.search(20) where q="PHP"
'
</pre>
<br />Lo más interesante, es que en la consola nos proporciona <a href="http://query.yahooapis.com/v1/public/yql?q=%09select%20*%20from%20query.multi%20where%20queries%3D'%0A%09%20%20select%20*%20%20from%20microsoft.bing.web(20)%20where%20query%3D%22PHP%22%3B%0A%09%20%20select%20*%20%20from%20search.web(20)%20where%20query%3D%22PHP%22%3B%0A%09%20%20select%20*%20%20from%20google.search(20)%20where%20q%3D%22PHP%22%0A'&format=xml&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys">la dirección para obtener esta consulta</a> y devuelve los datos en formato XML, por lo que hacer una aplicación que realice la llamada y obtenga la respuesta es realmente fácil de realizar.<br /><br />Tras buscar por la documentación no he encontrado ninguna opción de poder filtrar los resultados por país o idioma, por lo que habrá que esperar hasta que añadan esta característica y podamos realizarlas en otros idiomas.<br /><br /> Finalmente, viendo <a href="http://developer.yahoo.com/yql/guide/index.html">la documentación</a> observamos que tiene posibilidades muy variadas como añadir un post a tu blog Wordpress, interactuar con Flickr, con Yahoo! Maps, Amazon o Facebook entre otras, pudiendo usar YQL como API para estos servicios, por lo que es un servicio a tener en cuenta para integrarlo con otro uso que no sea el de realizar búsquedas.<br /><br /> <br />
<p style="margin-bottom: 0cm;"> </p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=21</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/creando-un-buscador-para-tu-pagina-usando-yahoo-query-language.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Como usar Google Apps en tu web</title>
			<link>http://www.imaginanet.com/blog/como-usar-google-apps-en-tu-web.html</link>
			<guid>http://www.imaginanet.com/blog/como-usar-google-apps-en-tu-web.html</guid>
			<comments>http://www.imaginanet.com/blog/como-usar-google-apps-en-tu-web.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Thu, 24 Dec 2009 10:41:10 +0100</pubDate>
					<category><![CDATA[Google Apps]]></category>
					<description><![CDATA[Si alguna vez necesitas incluir google apps en tu dominio, aqui tienes una sencilla explicación de como puedes empezar.
1.Regístrate y accede a tu cuenta
En la página  principal de Google Apps, haz clic en "Comparar ediciones y registrarse"  para empezar a utilizar el programa y acceder al panel de  control.Más  información...]]></description>
			<content:encoded><![CDATA[>Si alguna vez necesitas incluir google apps en tu dominio, aqui tienes una sencilla explicación de como puedes empezar.<br /><br />
<h3 style="font-size: 1.17em;">1.Regístrate y accede a tu cuenta</h3>
En la <a href="http://www.google.com/a/help/intl/en/business/applications.html">página  principal de Google Apps</a>, haz clic en "Comparar ediciones y registrarse"  para empezar a utilizar el programa y acceder al panel de  control.<br /><br /><strong><a href="http://www.google.com/support/a/bin/answer.py?answer=107246">Más  información <br /></a></strong><br />
<h3 style="font-size: 1.17em;">2.Verifica la propiedad del dominio</h3>
Confirma que eres el propietario del dominio con el que te has registrado para  habilitar Google Apps.<br /><br />
<h3 style="font-size: 1.17em;">3.Personaliza Google Apps</h3>
Google Apps permite modificar fácilmente varias configuraciones para aplicarlas  a toda tu organización.<br /><br />
<h3 style="font-size: 1.17em;">4.Crea cuentas de usuario</h3>
En el panel de control, crea tantas cuentas de usuario como necesite tu  organización.<br /><br />
<h3 style="font-size: 1.17em;">5.Migrar datos y activa el correo electrónico</h3>
Configura los registros Mail Exchange (MX) de tu dominio para habilitar la  entrega de correo electrónico.<br /><br />
<h3 style="font-size: 1.17em;">6.Implanta Google Apps</h3>
Ahora que has creado cuentas de usuario y has activado los servicios, ha llegado  el momento de ayudar a tus usuarios para que empiecen a utilizar Google Apps.<br /><br />
<h3 style="font-size: 1.17em;">¿Cómo ver el correo de nuestra cuenta?</h3>
- Podemos usar las funciones de php imap. Aquí va un pequeño ejemplo de como sacar un listado de los últimos 7 mensajes de correo.<br /><br />
<pre class="code php">function fix_text($str)
{
    $subject = '';
    $subject_array = imap_mime_header_decode($str);

    foreach ($subject_array AS $obj)
        $subject .= rtrim($obj->text, "t");

    return $subject;
} 


$mail = imap_open('{imap.gmail.com:993/novalidate-cert/ssl}', 'cuenta de correo', 'contraseña de la cuenta');
$last = imap_num_msg($mail);

echo '&lt;strong&gt;&lt;a href=&quot;/url_dominio_google/?account_id=cuenta_de_correo&quot; target=&quot;_blank&quot;&gt;Mensajes de correo ('.$last.') / &lt;span style=&quot;color: #e71d02;&quot;&gt;Nuevos ('.$nuevos.')&lt;/span&gt;&lt;/a&gt;&lt;/strong&gt;';

if ($last>7) $ini=($last-7);
else $ini=1;

$nuevos=0;
for ($i=$last;$i>=$ini;$i--){
	$header = imap_header($mail, $i);
	$from=$header->from;
	if (is_array($from)){
	        $de=$from[0]->personal;
	}

	$asunto=fix_text($header->subject);
	$asunto='<span title="'.$asunto.'">'.$asunto."</span>";

	if ($header->Unseen=="U"){
		$de='<strong>'.$de.'</strong>';
		$asunto='<strong>'.$asunto."</strong>";
		$nuevos++;
	}
	echo '<span title="'.$from[0]->personal.'">'.$de.'</span> - '.$asunto.' '.date('d/m', $header->udate);
}

imap_close($mail);<br />
</pre>
En el ejemplo conectamos con la cuenta de correo con la contraseña y obtenemos los últimos 7 mensajes de correo.<br />Luego vamos sacando mensaje a mensaje con el formato html que más no interese.<br />La condición de la linea 32 es para saber si el mensaje ha sido visto por el usuario o todavía no.<br /><br />
<h3 style="font-size: 1.17em;">¿Cómo ver el google calendar?</h3>
Para esta opción hay que tener requerido en nuestro php las librerías de Zend que podemos descargar de la web http://www.zend.com<br />A continuación nos logueamos con nuestro usuario y contraseña de google apps y pedimos la información del tramo de fechas de google calendar que queremos obtener.<br />A continuación tenéis un ejemplo de como obtener los datos de google calendar del mes de enero de 2010<br /> 
<pre class="code php">require_once('Zend/Loader.php');
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_AuthSub');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Calendar');

$service = Zend_Gdata_Calendar::AUTH_SERVICE_NAME;
$client = Zend_Gdata_ClientLogin::getHttpClient('usuario google apps', 'contraseña', $service);
$service = new Zend_Gdata_Calendar($client);
$dominioGapps=explode('@','usuario google apps');

echo 'http://www.google.com/calendar/hosted/'.trim($dominioGapps[1]).'/render?account_id='.urlencode('usuario google apps');

$query = $service->newEventQuery();
$query->setUser('id del calendario'); //Tambien se puede poner la opcion 'default' para el calendario común

$query->setVisibility('private');
$query->setProjection('full');
$query->setOrderby('starttime');
//$query->setFutureevents('true');// Retrieve the event list from the calendar server
$query->setStartMin('2010-01-01');
$query->setStartMax('2010-01-30');
try {    
	$eventFeed = $service->getCalendarEventFeed($query);
} catch (Zend_Gdata_App_Exception $e) {
	echo "Error: " . $e->getResponse();
}

foreach ($eventFeed as $event) {
	$valor=$event->when;
	$donde=$event->where;
	$autor=$event->author;
	$categoria=$event->category;
	$idevento=$event->link;
	$diaEvento=$valor[0]->startTime;
	$diaMesEvento = intval(substr($diaEvento,8,2));
	$dias[$diaMesEvento] .= $event->title->text.". Hora: ".substr($diaEvento,11,5)." (".substr($diaEvento,23,6).")n";
	$enlaceEvento[$diaMesEvento]=$idevento[0]->href;
}
</pre>
En este ejemplo obtenemos un array con los eventos que hay por dia]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=20</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/como-usar-google-apps-en-tu-web.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Usando el API de Google Analytics para mejorar nuestra web</title>
			<link>http://www.imaginanet.com/blog/usando-el-api-de-google-analytics-para-mejorar-nuestra-web.html</link>
			<guid>http://www.imaginanet.com/blog/usando-el-api-de-google-analytics-para-mejorar-nuestra-web.html</guid>
			<comments>http://www.imaginanet.com/blog/usando-el-api-de-google-analytics-para-mejorar-nuestra-web.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed, 23 Dec 2009 16:11:32 +0100</pubDate>
					<category><![CDATA[Google Analytics]]></category>
					<category><![CDATA[SEO]]></category>
					<description><![CDATA[Desde que Google sac&oacute; su herramienta Analytics nos proporcion&oacute; una nueva perspectiva gratuita para ver nuestra web desde los ojos de las personas que la visitan permiti&eacute;ndonos conocer lo que "realmente opinan" los usuarios de tu web.
A primera vista desde el panel de control de Google Analytics, la gran...]]></description>
			<content:encoded><![CDATA[><p>Desde que Google sac&oacute; su herramienta <a href="http://www.google.com/analytics/">Analytics</a> nos proporcion&oacute; una nueva perspectiva gratuita para ver nuestra web desde los ojos de las personas que la visitan permiti&eacute;ndonos conocer lo que "realmente opinan" los usuarios de tu web.</p>
<p>A primera vista desde el panel de control de Google Analytics, la gran cantidad de opciones y men&uacute;s que tenemos resulta hasta confusa para entender realmente que nos est&aacute;n diciendo y m&aacute;s a&uacute;n para gente inexperta. As&iacute; que tras un tiempo trabajando con ella, decid&iacute; ponerme manos a la obra para simplificar esta gran herramienta para hacerla un poco m&aacute;s sencilla.</p>
<h3>&iquest;C&oacute;mo usar el API?</h3>
<p>En primer lugar, damos por supuesto que tenemos una cuenta de Google Analytics y un sitio web <a href="http://www.google.com/support/googleanalytics/bin/static.py?page=guide.cs&amp;guide=19779&amp;topic=19783">con el c&oacute;digo Javascript</a> que nos haga recolectar las estad&iacute;sticas en nuestra cuenta.</p>
<p>En segundo lugar deberemos elegir unas librer&iacute;as que nos ayuden a usar el API en funci&oacute;n del lenguaje de programaci&oacute;n que vayamos a usar. Para ello, podemos encontrar en la <a href="http://code.google.com/intl/es-ES/apis/analytics/docs/gdata/gdataLibraries.html">secci&oacute;n de librer&iacute;as de Google Analytics</a> una buena cantidad de librer&iacute;as para diferentes lenguajes (Java, Python, PHP, etc.).</p>
<p>Tras estos dos pasos iniciales, tenemos todo listo para empezar a utilizar el API. Podemos echar un vistazo a la <a href="http://code.google.com/intl/es-ES/apis/analytics/docs/gdata/gdataReferenceDimensionsMetrics.html">documentaci&oacute;n del API</a>&nbsp; y como era de esperar las posibilidades que nos ofrece esta complet&iacute;sima API son muchas.</p>
<p>Lo que m&aacute;s nos interesa es conocer los par&aacute;metros con los que podemos utilizarla: <strong>dimensiones</strong> qu&eacute; es lo que vamos a medir y las <strong>m&eacute;tricas</strong> son en qu&eacute; unidad lo vamos a medir. Estas dimensiones y m&eacute;tricas las podemos agrupar de la manera que queramos, aunque para obtener unos buenos resultados deberemos hacerlo con sentido y adem&aacute;s, podemos hacer el uso de <strong>filtros</strong>, que nos permite filtrar los valores devueltos por una m&eacute;trica o una dimensi&oacute;n (por ejemplo una direcci&oacute;n web en concreto).</p>
<p>A continuaci&oacute;n vamos a hablar de los datos b&aacute;sicos que se desprenden de su uso.</p>
<h3><strong>&iquest;Tiene buen contenido o dise&ntilde;o mi web?</strong></h3>
<p>Tras interpretar los datos que obtenemos, podemos considerar si nuestra web tiene buenos contenidos o no desde dos puntos de vista, globalmente o espec&iacute;ficamente para una p&aacute;gina determinada.</p>
<p><span style="text-decoration: underline;">Desde el punto de vista global</span>, deberemos prestar atenci&oacute;n al grupo de m&eacute;tricas <code>ga:bounces</code> y <code>ga:entrances</code> que nos dir&aacute; el tanto por cien de rebote de nuestra web. Este c&aacute;lculo lo haremos realizando la divisi&oacute;n de&nbsp; <code>ga:bounces</code> entre <code>ga:entrances</code> d&aacute;ndonos como resultado el n&uacute;mero de cuantas personas abandonan la web tras visitar nuestra p&aacute;gina inicial.</p>
<p>Un alto n&uacute;mero en el tanto por cien de rebotes nos indica que la p&aacute;gina inicial no contiene o no muestra de manera correcta lo que el usuario esperaba encontrar en ella y por tanto vuelve a la p&aacute;gina anterior por donde lleg&oacute;.</p>
<p>Otra valoraci&oacute;n que podemos hacer es si estos contenidos globales son interesantes o no para el usuario mediante la m&eacute;trica <code>ga:timeOnSite</code> que nos proporciona la cantidad de tiempo que estuvo el usuario en nuestra web y la dimensi&oacute;n <code>ga:pageDepth</code>, que nos dice la cantidad media que los usuarios ven cuando entran en nuestra web.</p>
<span style="text-decoration: underline;">Desde el punto de vista espec&iacute;fico para una determinada p&aacute;gina</span>, si existe un alto n&uacute;mero n&uacute;mero de rebotes significa que al llegar a esa p&aacute;gina es confusa o no tiene inter&eacute;s para el usuario as&iacute; que deber&iacute;amos mejorar los aspectos donde falle. Este c&aacute;lculo lo realizaremos realizando la divisi&oacute;n de las dimensiones <code>ga:bounces</code> entre <code>ga:uniquePageviews</code> a&ntilde;adiendo la dimensi&oacute;n <code>ga:pagePath</code> a la consulta.
<h3><strong>&iquest;Son buenas las palabras clave que utilizo para cada p&aacute;gina?</strong></h3>
<p>Las palabras claves nos sirven junto al contenido de cada p&aacute;gina para describirla de cara a los buscadores. Para ver si las palabras claves que describen nuestras p&aacute;ginas son buenas podemos utilizar las dimensiones <code>ga:source</code> filtrando por <code>ga:pagePath</code>, especificando en esta &uacute;ltima la p&aacute;gina deseada a comprobar.</p>
<p>Si el resultado que nos devuelve es alto desde los buscadores Google, Yahoo, Bing, etc. significa que de cara a los buscadores las palabras clave describen bien el contenido.</p>
<h3><strong>&iquest;Cu&aacute;l es el comportamiento de los visitantes de mi web?</strong></h3>
<p>Un valor interesante es el que nos proporciona la dimensi&oacute;n <code>ga:secondPagePath</code>, que nos dice cu&aacute;l fue la segunda p&aacute;gina que visit&oacute; el usuario tras ver nuestra web. &Eacute;sto nos indica que es lo que m&aacute;s llama la atenci&oacute;n en nuestra web pudiendo potenciar otras p&aacute;ginas que deber&iacute;an tener mejores resultados.</p>
<p>Podemos observar tambi&eacute;n la navegaci&oacute;n que realizan los usuarios para p&aacute;ginas determinadas y ver desde qu&eacute; p&aacute;gina llegaron y a qu&eacute; p&aacute;gina fueron desde ella. En este caso, para saber desde qu&eacute; p&aacute;gina llegaron a otra deberemos usar como par&aacute;metros la dimensi&oacute;n <code>ga:previousPagePath</code>,m&eacute;trica <code>ga:pageviews</code> y el filtro <code>ga:nextPagePath</code> especificando la p&aacute;gina objetivo.</p>
<p>Por el contrario, para saber qu&eacute; p&aacute;gina visitaron desde la actual usaremos la dimensi&oacute;n <code>ga:nextPagePath</code>, m&eacute;trica <code>ga:pageviews</code> y filtro <code>ga:previousPagePath</code> con la p&aacute;gina que queremos consultar</p>
<p>Los datos obtenidos nos dir&aacute;n si la navegaci&oacute;n que realiza el usuario es la que esperamos o por el contrario no lo es y por tanto el contenido no le interesa.</p>
<h3><strong>Conclusiones</strong>&nbsp;</h3>
Aunque esta herramienta es muy potente para el marketing web y s&oacute;lo hemos comentado algunas de las m&aacute;s importantes posibilidades que nos ofrece el API, tambi&eacute;n nos ofrece muchas m&aacute;s como seguimiento de campa&ntilde;as, comercio electr&oacute;nico, fidelizaci&oacute;n de clientes, etc.<br />
<p>Todo estos datos sobre el patr&oacute;n de comportamiento de los usuarios nos sirve para conseguir un mejor <a title="&iquest;C&oacute;mo hacemos el posicionamiento web?" href="/marketing-online/posicionamiento-web.html">posicionamiento web</a> y por tanto tener m&aacute;s posibilidades de &eacute;xito. Estas t&eacute;cnicas, mezcladas con los conocimientos de marketing tradicional, las utilizamos en Imaginanet para la consecuci&oacute;n de los objetivos planteados en los proyectos de <a title="Agencia de marketing online. &iquest;Qu&eacute; aportamos?" href="/marketing-online.html">marketing online</a> en que participamos.</p>
<p>En pr&oacute;ximas entradas, hablaremos de posibilidades m&aacute;s avanzadas que nos ofrece.</p>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px;"><!-- 		@page { margin: 2cm } 		P { margin-bottom: 0.21cm } 		A:link { so-language: zxx } -->
<p style="margin-bottom: 0cm;"><span style="font-family: Verdana,sans-serif;">Desde que Google sac&oacute; su herramienta Analytics nos proporcion&oacute; una nueva perspectiva para ver nuestra web desde los ojos de las personas que la visitan con un mont&oacute;n de estad&iacute;sticas de todo tipo. </span></p>
<p style="margin-bottom: 0cm;">&nbsp;</p>
<p style="margin-bottom: 0cm;"><span style="font-family: Verdana,sans-serif;">A primera vista desde el panel de control de Google Analytics, la gran cantidad de opciones y men&uacute;s que tenemos resulta hasta confusa para entender realmente que nos est&aacute;n diciendo y m&aacute;s a&uacute;n para gente inexperta. As&iacute; que tras un tiempo trabajando con ella, decid&iacute; ponerme manos a la obra para simplificar esta gran herramienta para hacerla un poco m&aacute;s sencilla.</span></p>
<p style="margin-bottom: 0cm;">&nbsp;</p>
<p style="margin-bottom: 0cm;"><span style="font-family: Verdana,sans-serif;">En primer lugar ech&eacute; un vistazo a la documentaci&oacute;n del API en la direcci&oacute;n <a href="http://code.google.com/intl/es-ES/apis/analytics/">http://code.google.com/intl/es-ES/apis/analytics/</a></span> <span style="font-family: Verdana,sans-serif;">y como era de esperar las posibilidades que nos ofrece esta complet&iacute;sima API son numerosas. A continuaci&oacute;n hablaremos de las conclusiones b&aacute;sicas que podemos obtener con ella, aunque en primer lugar deberemos conocer que estos datos est&aacute;n divididos en dos grupos, dimensiones que es lo que vamos a medir y las m&eacute;tricas, que es en qu&eacute; unidad lo vamos a medir.</span></p>
<p style="margin-bottom: 0cm;">&nbsp;</p>
<p style="margin-bottom: 0cm;"><span style="font-family: Verdana,sans-serif;">&iquest;Tiene buen contenido o dise&ntilde;o mi web?</span></p>
<p style="margin-bottom: 0cm;">&nbsp;</p>
<p style="margin-bottom: 0cm;"><span style="font-family: Verdana,sans-serif;">Tras interpretar los datos que obtenemos, podemos considerar si nuestra web tiene buenos contenidos o no desde dos puntos de vista, globalmente y espec&iacute;ficamente para una p&aacute;gina determinada.</span></p>
<p style="margin-bottom: 0cm;">&nbsp;</p>
<p style="margin-bottom: 0cm;"><span style="font-family: Verdana,sans-serif;">Desde el punto de vista global, deberemos prestar atenci&oacute;n al grupo de m&eacute;tricas M1. Visitor que nos dir&aacute; el tanto por cien de rebote de nuestra web. Este c&aacute;lculo lo haremos realizando la divisi&oacute;n de las m&eacute;tricas <code>ga:bounces</code> entre <code>ga:entrances</code> d&aacute;ndonos como resultado el n&uacute;mero de cuantas personas abandonan la web tras visitar nuestra p&aacute;gina inicial.</span></p>
<p style="margin-bottom: 0cm;">&nbsp;</p>
<p style="margin-bottom: 0cm;"><span style="font-family: Verdana,sans-serif;">Un alto n&uacute;mero en el tanto por cien de rebotes nos indica que la p&aacute;gina inicial no contiene o no muestra de manera correcta lo que el usuario esperaba encontrar en ella y por tanto se va a otra. </span></p>
<p style="margin-bottom: 0cm;">&nbsp;</p>
<p style="margin-bottom: 0cm;"><span style="font-family: Verdana,sans-serif;">Una vez determinado que el tanto por cien de rebote es lo m&aacute;s bajo posible, podemos estimar si estos contenidos globales son interesantes o no para el usuario mediante la m&eacute;trica </span><code>ga:timeOnSite</code> que nos proporciona la cantidad de tiempo que estuvo el usuario en nuestra web y la dimensi&oacute;n <span style="font-family: Verdana,sans-serif;"><code>ga:pageDepth</code>, que nos dice la cantidad media que los usuarios ven cuando entran en nuestra web.</span></p>
<p style="margin-bottom: 0cm;">&nbsp;</p>
<p style="margin-bottom: 0cm;">&nbsp;</p>
<p style="margin-bottom: 0cm;"><span style="font-family: Verdana,sans-serif;">Desde el punto de vista espec&iacute;fico para una determinada p&aacute;gina, si existe un alto n&uacute;mero n&uacute;mero de rebotes significa que al llegar a esa p&aacute;gina es confusa o no tiene inter&eacute;s para el usuario as&iacute; que deber&iacute;amos mejorar los aspectos donde falle.</span></p>
<p style="margin-bottom: 0cm;">&nbsp;</p>
<p style="margin-bottom: 0cm;"><span style="font-family: Verdana,sans-serif;">&iquest;Son buenas las palabras clave que utilizo para cada p&aacute;gina?</span></p>
<p style="margin-bottom: 0cm;">&nbsp;</p>
<p style="margin-bottom: 0cm;"><span style="font-family: Verdana,sans-serif;">Las palabras claves nos sirven junto al contenido de cada p&aacute;gina para describirla de cara a los buscadores. Para ver si las palabras claves que describen nuestras p&aacute;ginas son buenas podemos utilizar la m&eacute;trica <code>ga:entrances</code> junto a la dimensi&oacute;n <code>ga:landingPagePath</code> y as&iacute; indicarnos si hemos conseguido nuevas visitas desde buscadores a una p&aacute;gina concreta.</span></p>
<p style="margin-bottom: 0cm;">&nbsp;</p>
<p style="margin-bottom: 0cm;"><span style="font-family: Verdana,sans-serif;">&iquest;Cu&aacute;l es el comportamiento de los visitantes de mi web?</span></p>
<p style="margin-bottom: 0cm;">&nbsp;</p>
<p style="margin-bottom: 0cm;"><span style="font-family: Verdana,sans-serif;">Un valor interesante es el que nos proporciona la dimensi&oacute;n <code>ga:secondPagePath</code>, que nos dice cu&aacute;l fue la segunda p&aacute;gina que visit&oacute; el usuario tras ver nuestra web. &Eacute;sto nos indica que es lo que m&aacute;s llama la atenci&oacute;n en nuestra web pudiendo potenciar otras p&aacute;ginas que deber&iacute;an tener mejores resultados.</span></p>
<p style="margin-bottom: 0cm;">&nbsp;</p>
<p style="margin-bottom: 0cm;"><span style="font-family: Verdana,sans-serif;">Podemos observar tambi&eacute;n la navegaci&oacute;n que realizan los usuarios para p&aacute;ginas determinadas y ver desde qu&eacute; p&aacute;gina llegaron y a qu&eacute; p&aacute;gina fueron desde ella. Para ello tenemos que utilizar una gran caracter&iacute;stica de esta API que son los filtros, que nos permiten obtener una combinaci&oacute;n de dimensiones y m&eacute;tras filtrando los resultados para una dimensi&oacute;n o m&eacute;trica determinada.</span></p>
<p style="margin-bottom: 0cm;">&nbsp;</p>
<p style="margin-bottom: 0cm;"><span style="font-family: Verdana,sans-serif;">En este caso, para saber desde qu&eacute; p&aacute;gina llegaron a otra deberemos usar como par&aacute;metros</span></p>
<p style="margin-bottom: 0cm;"><span style="font-family: Verdana,sans-serif;">dimensi&oacute;n <code>ga:previousPagePath</code> m&eacute;trica <code>ga:pageviews</code> </span></p>
<p style="margin-bottom: 0cm;"><span style="font-family: Verdana,sans-serif;"><code>filtro <code>ga:nextPagePath</code> pagina_objetivo.html</code></span></p>
<p style="margin-bottom: 0cm;">&nbsp;</p>
<p style="margin-bottom: 0cm;"><span style="font-family: Verdana,sans-serif;">y para saber qu&eacute; p&aacute;gina visitaron desde la actual</span></p>
<p style="margin-bottom: 0cm;">&nbsp;</p>
<p style="margin-bottom: 0cm;"><span style="font-family: Verdana,sans-serif;"><code>dimensi&oacute;n <code>ga:nextPagePath</code><br />m&eacute;trica <code>ga:pageviews</code> </code></span></p>
<p style="margin-bottom: 0cm;"><span style="font-family: Verdana,sans-serif;"><code>filtro <code>ga:previousPagePath%3D~test.html</code></code></span></p>
<p style="margin-bottom: 0cm;">&nbsp;</p>
<p style="margin-bottom: 0cm;"><span style="font-family: Verdana,sans-serif;">Los datos obtenidos nos dir&aacute;n si la navegaci&oacute;n que realiza el usuario es la que esperamos o por el contrario no lo es y por tanto el contenido no le interesa.</span></p>
<p style="margin-bottom: 0cm;">&nbsp;</p>
<p style="margin-bottom: 0cm;">&nbsp;</p>
<p style="margin-bottom: 0cm;"><span style="font-family: Verdana,sans-serif;">Finalmente, debo decir que aunque esta herramienta es muy potente y que s&oacute;lo hemos comentado algunas de las m&aacute;s importantes posibilidades que nos ofrece el API y que podemos ver todo lo que podemos hacer aqu&iacute; </span></p>
<p style="margin-bottom: 0cm;"><span style="font-family: Verdana,sans-serif;">http://code.google.com/intl/es-ES/apis/analytics/docs/gdata/gdataReferenceDimensionsMetrics.html</span></p>
<p style="margin-bottom: 0cm;"><span style="font-family: Verdana,sans-serif;">, nos sirve para conseguir un mejor posicionamiento web y por tanto tener m&aacute;s posibilidades de &eacute;xito. Estas t&eacute;cnicas las utilizamos desde Imaginanet para conseguir que nuestros clientes tengan &eacute;xito <a href="http://www.imaginanet.com/posicionamiento-seo.html">http://www.imaginanet.com/posicionamiento-seo.html</a></span></p>
<p style="margin-bottom: 0cm;">&nbsp;</p>
<p style="margin-bottom: 0cm;"><span style="font-family: Verdana,sans-serif;">En pr&oacute;ximas entradas, hablaremos de posibilidades m&aacute;s avanzadas que nos ofrece.</span></p>
</div>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=19</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/usando-el-api-de-google-analytics-para-mejorar-nuestra-web.html</feedburner:origLink>
		</item>
				
		<item>
			<title>La vida más fácil con Google Mail (Gmail y Google Apps for your domain)</title>
			<link>http://www.imaginanet.com/blog/la-vida-mas-facil-con-google-mail-gmail-y-google-apps-for-your-domain.html</link>
			<guid>http://www.imaginanet.com/blog/la-vida-mas-facil-con-google-mail-gmail-y-google-apps-for-your-domain.html</guid>
			<comments>http://www.imaginanet.com/blog/la-vida-mas-facil-con-google-mail-gmail-y-google-apps-for-your-domain.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed, 16 Dec 2009 11:05:45 +0100</pubDate>
					<category><![CDATA[Google Apps]]></category>
					<description><![CDATA[Acabo de darme cuenta de que en GMail, aparece una novedad en color rojo que dice "&iexcl;Nuevo! Videos de Gmail" y veo que es una campa&ntilde;a que Google est&aacute; haciendo a sus usuarios ense&ntilde;&aacute;ndoles todo lo que pueden hacer con GMail. Podeis verla aqu&iacute;.En los v&iacute;deos se explican las distintas...]]></description>
			<content:encoded><![CDATA[>Acabo de darme cuenta de que en GMail, aparece una novedad en color rojo que dice "&iexcl;Nuevo! Videos de Gmail" y veo que es una campa&ntilde;a que Google est&aacute; haciendo a sus usuarios ense&ntilde;&aacute;ndoles todo lo que pueden hacer con GMail. <a title="Abrir en una ventana nueva" href="http://www.google.es/videosgmail" target="_blank">Podeis verla aqu&iacute;.</a><br /><br />En los v&iacute;deos se explican las distintas maravillas del cliente de correo electr&oacute;nico y del servidor. <br />Valorando todo lo que dicen, realmente es aplicable a Google Apps. Nosotros usamos Google Apps y estamos encantados, pero resulta que somos <a title="Ver servicios de integraci&oacute;n de Google Apps" href="/soluciones-on-line/google-apps.html">integradores de Google Apps</a>&nbsp; - para <a title="Ver soluciones de intranet en las que se puede integrar Google Apps" href="/soluciones-on-line/intranet-extranet/intranet.html">intranets</a>, <a title="Ver soluciones de extranet en las que se puede integrar Google Apps" href="/soluciones-on-line/intranet-extranet/extranet.html">extranets</a>, gestores de contenido, y hasta en <a title="Ver servicios de dise&ntilde;o y programaci&oacute;n de p&aacute;ginas web" href="/diseno-web.html">las p&aacute;ginas web que dise&ntilde;amos y desarrollamos</a> -&nbsp; y los clientes que tambi&eacute;n utilizan Google Apps for your Domain, tambi&eacute;n est&aacute;n muy contentos.<br />Razones que tenemos para ello son las explicadas en esta p&aacute;gina que ha creado Google, pero adem&aacute;s incluimos una serie de ventajas adicionales:<br />- Google Mail. Al poder configurarlo como servidor IMAP, es fant&aacute;stico, te permite sincronizar el correo desde cualquier dispositivo. Cuando leo un email en mi tel&eacute;fono m&oacute;vil, me lo marca como le&iacute;do en el resto de clientes de correo, si env&iacute;o un email, lo veo en la bandeja de enviados de todos mis clientes de correo. Es algo muy c&oacute;modo.<br />- Google Calendar. Permite tener calendarios de empresa para distintas tareas, por ejemplo, podemos tener el calendario de trabajos de dise&ntilde;o web, el cual est&aacute; compartido con dise&ntilde;adores y maquetadores, el calendario de entrega de proyectos que est&aacute; compartido con las personas encargadas de hacer seguimiento de proyectos, ... Adem&aacute;s, con cada cliente compartimos un calendario con los diferentes hitos del proyecto, conforme el proyecto va avanzando, el calendario se actualiza inmediatamente. Y todo sincronizado con el tel&eacute;fono m&oacute;vil, portatil, ...<br />- Google Docs. Qu&eacute; podemos decir de una herramienta ofim&aacute;tica que permite compartir con clientes y compa&ntilde;eros de trabajo hojas de c&aacute;lculo con presupuestos, documentos de texto con el seguimiento o la funcionalidad de un proyecto, etc.<br />- Google Talk. Una herramienta imprescindible en una intranet, permite mantener conversaciones privadas entre usuario y entre distintas sucursales de la empresa, con la gran ventaja de que todo el texto que hemos escrito nos lo env&iacute;a por email a nuestra cuenta de correo y de nuestro compa&ntilde;ero de charlas.<br /><br />...<br /><br />Y lo que cuentan en los v&iacute;deos colgados explican los siguientes temas:<br />- Cadenas de conversaci&oacute;n de Gmail. Aqu&iacute; vemos c&oacute;mo al iniciar un mensaje, las respuestas que este tiene se guardan todas agrupadas de forma que la conversaci&oacute;n est&eacute; toda en el mismo mensaje. Esta utilidad est&aacute; muy bien, aunque a veces genera peque&ntilde;as confusiones, es muy &uacute;til os lo aseguro.<br /> 
<object width="425" height="344" data="http://www.youtube.com/v/2LoeyPlAnvo&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1" type="application/x-shockwave-flash">
<param name="data" value="http://www.youtube.com/v/2LoeyPlAnvo&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1" />
<param name="allowFullScreen" value="true" />
<param name="allowScriptAccess" value="always" />
<param name="src" value="http://www.youtube.com/v/2LoeyPlAnvo&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1" />
<param name="allowfullscreen" value="true" />
</object>
<br /><br />- &iquest;No hay conexi&oacute;n a internet? Sin problemas, usando Google Gears podemos trabajar con nuestro Google Mail y cuando tengamos conexi&oacute;n a internet, autom&aacute;ticamente lo detectar&aacute; y recibir&aacute; los mensajes pendientes de recibir, as&iacute; como enviar&aacute; aquellos que est&eacute;n pendientes de env&iacute;o.<br /> 
<object width="425" height="344" data="http://www.youtube.com/v/ymXEr9Zs37w&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1" type="application/x-shockwave-flash">
<param name="data" value="http://www.youtube.com/v/ymXEr9Zs37w&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1" />
<param name="allowFullScreen" value="true" />
<param name="allowScriptAccess" value="always" />
<param name="src" value="http://www.youtube.com/v/ymXEr9Zs37w&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1" />
<param name="allowfullscreen" value="true" />
</object>
<br /><br />- AntiSpam. Una aplicaci&oacute;n anti-spam que funciona muy fina.<br /> 
<object width="425" height="344" data="http://www.youtube.com/v/q_CzSr3QL5Y&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1" type="application/x-shockwave-flash">
<param name="data" value="http://www.youtube.com/v/q_CzSr3QL5Y&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1" />
<param name="allowFullScreen" value="true" />
<param name="allowScriptAccess" value="always" />
<param name="src" value="http://www.youtube.com/v/q_CzSr3QL5Y&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1" />
<param name="allowfullscreen" value="true" />
</object>
<br /><br />- Chat de video y voz.<br />
<object width="425" height="344" data="http://www.youtube.com/v/Ijy3HMDygzo&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1" type="application/x-shockwave-flash">
<param name="allowFullScreen" value="true" />
<param name="allowScriptAccess" value="always" />
<param name="src" value="http://www.youtube.com/v/Ijy3HMDygzo&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1" />
<param name="allowfullscreen" value="true" />
</object>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=18</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/la-vida-mas-facil-con-google-mail-gmail-y-google-apps-for-your-domain.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Texto a voz usando el elemento Audio de HTML5</title>
			<link>http://www.imaginanet.com/blog/texto-a-voz-usando-el-elemento-audio-de-html5.html</link>
			<guid>http://www.imaginanet.com/blog/texto-a-voz-usando-el-elemento-audio-de-html5.html</guid>
			<comments>http://www.imaginanet.com/blog/texto-a-voz-usando-el-elemento-audio-de-html5.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue, 15 Dec 2009 11:18:24 +0100</pubDate>
					<category><![CDATA[HTML5]]></category>
					<category><![CDATA[Accesibilidad]]></category>
					<description><![CDATA[Weston Ruter ha creado un mashup que enlaza el soporte de Audio en HTML5 en navegadores modernos (no more Internet Explorer please) con la nueva API de traducción de Google.Hace poco que Google Translate anunció la posibilidad de escuchar traducciones habladas en inglés via texto a voz (TTS - Text To Speech). Buscando en el...]]></description>
			<content:encoded><![CDATA[>Weston Ruter ha creado un mashup que <a title="Abrir en una ventana nueva" href="http://weston.ruter.net/projects/google-tts/" target="_blank">enlaza el soporte de Audio en HTML5</a> en navegadores modernos (no more Internet Explorer please) con la nueva <a title="Abrir en una ventana nueva" href="http://googleblog.blogspot.com/2009/11/new-look-for-google-translate.html" target="_blank">API de traducción de Google</a>.<br /><br />Hace poco que Google Translate anunció la posibilidad de escuchar traducciones habladas en inglés via texto a voz (TTS - Text To Speech). Buscando en el panel de red de Firebug de donde estaban llegando los datos TTS, se ve que el audio está en formato MP3 y se ejecuta con una consulta HTTP GET: http://translate.google.com/translate_tts?tl=en&q=text.<br /><br />Google Translate, advierte de que el servicio sólo está disponible para pequeñas traducciones a inglés, y el servicio web de texto a voz se limita a una cantidad de texto no superior a 100 caracteres.<br /><br />Otra restricción es que el servicio devuelve un error 404 si la petición incluye un Referer en el header (parece ser que el referer debe ser translate.google.com).<br /><br />Según dice Weston Ruter, creó este mashup viendo las limitaciones del web service TTS que sólo puede usarlo Google Translate, para utilizarlo desde cualquier navegador que admita el elemento Audio de HTML5. El mashup web utiliza este último y un atributo rel="noreferrer".<br /><br />Hay otros experimentos de texto a voz, <a title="Abrir en una ventana nueva" href="http://www.clochix.net/post/2009/03/14/Et-en-plus-il-parle" target="_blank">por ejemplo esta página</a>. Ójala que Google haga pública su API de traducción.<br />]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=17</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/texto-a-voz-usando-el-elemento-audio-de-html5.html</feedburner:origLink>
		</item>
				
		<item>
			<title>jQuery ColorPicker. Tres plugins que merece la pena tener en cuenta.</title>
			<link>http://www.imaginanet.com/blog/jquery-colorpicker-tres-plugins-de-jquery-que-merece-la-pena-tener-en-cuenta.html</link>
			<guid>http://www.imaginanet.com/blog/jquery-colorpicker-tres-plugins-de-jquery-que-merece-la-pena-tener-en-cuenta.html</guid>
			<comments>http://www.imaginanet.com/blog/jquery-colorpicker-tres-plugins-de-jquery-que-merece-la-pena-tener-en-cuenta.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue, 15 Dec 2009 10:47:35 +0100</pubDate>
					<category><![CDATA[Web 2.0]]></category>
					<category><![CDATA[JavaScript]]></category>
					<category><![CDATA[jQuery]]></category>
					<description><![CDATA[Todos alguna vez, hemos necesitado inclu&iacute;r campos de selecci&oacute;n de color (colorpicker) cuando realizamos zonas de administraci&oacute;n o backOffice.Est&aacute; muy pasado de moda y queda demasiado rudimentario incluir campos de texto donde se introduzca el c&oacute;digo hexadecimal del color deseado, adem&aacute;s,...]]></description>
			<content:encoded><![CDATA[>Todos alguna vez, hemos necesitado inclu&iacute;r campos de selecci&oacute;n de color (colorpicker) cuando realizamos zonas de administraci&oacute;n o backOffice.<br />Est&aacute; muy pasado de moda y queda demasiado rudimentario incluir campos de texto donde se introduzca el c&oacute;digo hexadecimal del color deseado, adem&aacute;s, de esta forma es un poco complicado explicar lo qu&eacute; significa el c&oacute;digo #ff0000. Si queremos hacer las cosas f&aacute;ciles de usar, y proporcionar al usuario algo f&aacute;cil e intuitivo, hay que incluir una aplicaci&oacute;n de selecci&oacute;n de color desde donde el usuario seleccione el color deseado de forma visual.<br /><br />En este art&iacute;culo mencionamos tres plugins de jQuery para la inclusi&oacute;n de un colorPicker en campos de formularios.<br /><br /><a title="Abrir en una ventana nueva" href="http://acko.net/dev/farbtastic" target="_blank">Farbtastic</a> est&aacute; escrito por Steven Writtens con licencia GPL. Si quieres m&aacute;s informaci&oacute;n sobre el plugin, <a title="Abrir en una ventana nueva" href="http://acko.net/dev/farbtastic" target="_blank">pulsa aqu&iacute;</a>. Es muy f&aacute;cil de incluir:<br />1. Incluir los archivos javaScript y CSS en el HTML de tu p&aacute;gina web.<br />
<pre class="code xml">
  <script src="/imaginanet/farbtastic.js" type="text/javascript"></script>
  <link rel="stylesheet" href="farbtastic.css" type="text/css" />
</pre>
<br />2. A&ntilde;adir un elemento que sea el contenedor del gr&aacute;fico y el campo de texto, y asignarles un identificador a cada uno de ellos.<br />
<pre class="code xml"><form>
  <input id="color" name="color" type="text" value="#123456" />
</form>
<div id="colorpicker"></div>
</pre>
3. A&ntilde;adir al evento ready() un controlador que inicializa el color picker y lo enlaza con el campo de texto.<br />
<pre class="code xml">
&lt;script type="text/javascript"&gt;
  $(document).ready(function() {
    $('#colorpicker').farbtastic('#color');
  });
&lt;/script&gt;
</pre>
<a title="Abrir en una ventana nueva" href="http://www.eyecon.ro/colorpicker/" target="_blank">ColorPicker</a>, est&aacute; programado por Stefan Petre. Con dos tipos de licencia, MIT y GPL. Puedes ver su p&aacute;gina web <a title="Abrir en una ventana nueva" href="http://www.eyecon.ro/colorpicker/" target="_blank">pulsando aqu&iacute;</a>.<br />Si quieres ver la gu&iacute;a r&aacute;pida de implementaci&oacute;n, pulsa aqu&iacute;. La inclusi&oacute;n en tu p&aacute;gina web es muy r&aacute;pida, cargas los archivos javaScript y CSS necesarios, creas un campo de texto que sea el que incluya el colorPicker y le asignas un identificador, a continuaci&oacute;n, en el evento ready(), lo inicializamos asign&aacute;ndoselo al identificador del campo creado.<br />
<pre class="code js">$('idCampoDeTexto').ColorPicker();
</pre>
Si queremos activarlo con opciones personalizadas:<br />
<pre class="code js">$('idCampoDeTexto').ColorPicker({option1:val1,opt2:val2,...});
</pre>
<br /><a title="Abrir en una ventana nueva" href="http://www.digitalmagicpro.com/jPicker/" target="_blank">jPicker</a> es una migraci&oacute;n del <a title="Abrir en una ventana nueva" href="http://johndyer.name/post/2007/09/PhotoShop-like-JavaScript-Color-Picker.aspx" target="_blank">plugin escrito para Prototype por John Dyers</a> (fant&aacute;stico plugin). Puedes ver m&aacute;s informaci&oacute;n sobre el plugin en la <a title="Abrir en una ventana nueva" href="http://www.digitalmagicpro.com/jPicker/" target="_blank">p&aacute;gina de jPicker</a>.<br /><br /><br />]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=16</wfw:commentRss>
			<slash:comments>2</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/jquery-colorpicker-tres-plugins-de-jquery-que-merece-la-pena-tener-en-cuenta.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Rendimiento de las URIs con datos</title>
			<link>http://www.imaginanet.com/blog/rendimiento-de-las-uris-con-datos.html</link>
			<guid>http://www.imaginanet.com/blog/rendimiento-de-las-uris-con-datos.html</guid>
			<comments>http://www.imaginanet.com/blog/rendimiento-de-las-uris-con-datos.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 14 Dec 2009 11:55:47 +0100</pubDate>
					<category><![CDATA[JavaScript]]></category>
					<category><![CDATA[CSS]]></category>
					<category><![CDATA[Navegadores]]></category>
					<description><![CDATA[En el blog de Ravelrumba, han hecho un peque&ntilde;o experimento con URIs de datos y su rendimiento en la carga de una p&aacute;gina web. En el estudio s&oacute;lo se ha utilizado Firefox 3.5 con la cach&eacute; vac&iacute;a.Los resultados no son interesantes por las respuestas que nos proporcionan, sino por las preguntas que...]]></description>
			<content:encoded><![CDATA[>En el <a title="Abrir en una ventana nueva" href="http://www.ravelrumba.com/blog/data-uris-for-css-images-more-tests-more-questions/" target="_blank">blog de Ravelrumba</a>, han hecho un peque&ntilde;o experimento con URIs de datos y su rendimiento en la carga de una p&aacute;gina web. En el estudio s&oacute;lo se ha utilizado Firefox 3.5 con la cach&eacute; vac&iacute;a.<br /><br />Los resultados no son interesantes por las respuestas que nos proporcionan, sino por las preguntas que hacen aparecer al respecto.<br /><br />En el experimento se han usado 31 im&aacute;genes y se han convertido a data URIs con <a title="Abrir en una ventana nueva" href="http://github.com/nzakas/cssembed" target="_blank">CSSEmbed</a>. En un caso adicional, se ha usado <a title="Abrir en una ventana nueva" href="http://duris.ru/" target="_blank">DURIS</a> para separar todas las URIs de datos en un archivo CSS aparte, as&iacute;, la etiqueta &lt;head&gt; se queda mucho m&aacute;s peque&ntilde;a y as&iacute;, carga m&aacute;s r&aacute;pido.<br /><br />Los tres escenarios planteados, llevan a un rendimiento muy parecido (usando HTTPWatch, los tiempos de carga son 1,35 s, 1,13 s y 1,13 s), viendo que los escenarios con data URI son un poco mejores. Es m&aacute;s interesante ver que un usuario que deja un comentario desde Sur&aacute;frica proporciona unos resultados bastante distintos: 4,04 s, 1,44 s, 1,92 s. En este caso, el retardo que existe para cargar 31 im&aacute;genes, puede conllevar estos tiempos de carga.<br /><br />Otro factor importante es la velocidad que percibe el usuario, al fin y al cabo, lo que m&aacute;s tiene que ver con el rendimiento. Los dos escenarios funcionan con la misma velocidad percibida, el segundo de ellos parece ser mejor ya que las im&aacute;genes se cargan en una hoja de estilos al final de la p&aacute;gina, despu&eacute;s de haberse cargado un script.<br /><br />El estudio saca a la luz preguntas sobre la carga de URIs con datos. Otro usuario del web, comenta que ha enviado un gr&aacute;fico que muestra como las URIs a im&aacute;genes tardan m&aacute;s en cargar que las im&aacute;genes descargadas de una forma convencional. Este es el tipo de cosas que ser&iacute;a bueno investigar.<br /><br />En el mismo blog se puede ver un estudio sobre el <a title="Abrir en una ventana nueva" href="http://www.ravelrumba.com/blog/a-look-at-how-browsers-download-and-render-css-background-images/" target="_blank">rendimiento de las im&aacute;genes de fondo</a> en distintos navegadores.]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=14</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/rendimiento-de-las-uris-con-datos.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Google: más búsquedas en tiempo real.</title>
			<link>http://www.imaginanet.com/blog/google-mas-busquedas-en-tiempo-real.html</link>
			<guid>http://www.imaginanet.com/blog/google-mas-busquedas-en-tiempo-real.html</guid>
			<comments>http://www.imaginanet.com/blog/google-mas-busquedas-en-tiempo-real.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 14 Dec 2009 11:22:11 +0100</pubDate>
					<category><![CDATA[Google]]></category>
					<category><![CDATA[Buscadores]]></category>
					<category><![CDATA[Web 2.0]]></category>
					<description><![CDATA[En abril de este año, Google empezó a mostrar resultados de búsquedas en Twitter en tiempo real y así ver lo que dice la gente en el mismo momento.Ahora, los usuarios podrán ver que en la parte superior de una búsqueda de resultados y siempre que tenga sentido para la búsqueda, actualizaciones en direto de los contenidos...]]></description>
			<content:encoded><![CDATA[>En abril de este año, Google empezó a mostrar resultados de búsquedas en Twitter en tiempo real y así ver lo que dice la gente en el mismo momento.<br />Ahora, los usuarios podrán ver que en la parte superior de una búsqueda de resultados y siempre que tenga sentido para la búsqueda, actualizaciones en direto de los contenidos que la gente escribe en Twitter, FriendFeed, Facebook, MySpace, FriendFeed, Jaiku e Identi.ca.<br /><br />Además, incluirá los artículos que se hayan rastreado para este tema en los medios que rastrea <a title="Abrir en una ventana nueva" href="http://news.google.com/" target="_blank">Google News</a> o el <a title="Abrir en una ventana nueva" href="http://blogsearch.google.com/" target="_blank">buscador de blogs de Google</a>.<br /><br />En <a title="Abrir en una ventana nueva" href="http://www.google.com/trends" target="_blank">Google Trends</a> se ha incluído también esta opción para ver estadísticas de las palabras que más se consultan en el buscador en tiempo real.<br /><br />En el video siguiente se ve como una búsqueda se va llenando de comentarios de Twitter que van dejando los usuarios sobre el tema:<br /><br /> 
<object width="425" height="344" data="http://www.youtube.com/v/WRkYmx4A9Do&color1=0xb1b1b1&color2=0xcfcfcf&hl=en_US&feature=player_embedded&fs=1" type="application/x-shockwave-flash">
<param name="data" value="http://www.youtube.com/v/WRkYmx4A9Do&color1=0xb1b1b1&color2=0xcfcfcf&hl=en_US&feature=player_embedded&fs=1" />
<param name="allowFullScreen" value="true" />
<param name="allowScriptAccess" value="always" />
<param name="src" value="http://www.youtube.com/v/WRkYmx4A9Do&color1=0xb1b1b1&color2=0xcfcfcf&hl=en_US&feature=player_embedded&fs=1" />
<param name="allowfullscreen" value="true" />
</object>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=12</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/google-mas-busquedas-en-tiempo-real.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Google Goggles. Usa imágenes para buscar en la web.</title>
			<link>http://www.imaginanet.com/blog/google-goggles--usa-imagenes-para-buscar-en-la-web-.html</link>
			<guid>http://www.imaginanet.com/blog/google-goggles--usa-imagenes-para-buscar-en-la-web-.html</guid>
			<comments>http://www.imaginanet.com/blog/google-goggles--usa-imagenes-para-buscar-en-la-web-.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Sat, 12 Dec 2009 17:29:13 +0100</pubDate>
					<category><![CDATA[Google]]></category>
					<category><![CDATA[Buscadores]]></category>
					<description><![CDATA[Como una imagen vale más que mil palabras, en Google acaban de lanzar un servicio de búsqueda a partir de una foto. Sácale una foto y te devolverá resultados relacionados con el tema.Sólo funciona en dispositivos con Android y reconoce lugares, obras de arte, logotipos… incluso, si estás en un lugar destacado, sólo has de...]]></description>
			<content:encoded><![CDATA[>Como una imagen vale más que mil palabras, en Google acaban de lanzar un <a title="Abrir en ventana nueva. Google goggles." href="http://www.google.com/mobile/goggles/" target="_blank">servicio de búsqueda a partir de una foto</a>. Sácale una foto y te devolverá resultados relacionados con el tema.<br />Sólo funciona en dispositivos con Android y reconoce lugares, obras de arte, logotipos… incluso, si estás en un lugar destacado, sólo has de activar el GPS, mandar la localización y se te devolverá la información sobre el lugar donde te encuentres..<br /><br />    
<object width="560" height="340" data="http://www.youtube.com/v/Hhgfz0zPmH4&hl=es_ES&fs=1&rel=0" type="application/x-shockwave-flash">
<param name="data" value="http://www.youtube.com/v/Hhgfz0zPmH4&hl=es_ES&fs=1&rel=0" />
<param name="allowFullScreen" value="true" />
<param name="allowscriptaccess" value="always" />
<param name="src" value="http://www.youtube.com/v/Hhgfz0zPmH4&hl=es_ES&fs=1&rel=0" />
<param name="allowfullscreen" value="true" />
</object>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=11</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/google-goggles--usa-imagenes-para-buscar-en-la-web-.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Búsquedas personalizadas para todos los usuarios.</title>
			<link>http://www.imaginanet.com/blog/busquedas-personalizadas-para-todos-los-usuarios-.html</link>
			<guid>http://www.imaginanet.com/blog/busquedas-personalizadas-para-todos-los-usuarios-.html</guid>
			<comments>http://www.imaginanet.com/blog/busquedas-personalizadas-para-todos-los-usuarios-.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 14 Dec 2009 11:34:54 +0100</pubDate>
					<category><![CDATA[Google]]></category>
					<category><![CDATA[SEO]]></category>
					<category><![CDATA[Web 2.0]]></category>
					<description><![CDATA[Hace unos a&ntilde;os, nac&iacute;an las b&uacute;squedas personalizadas de Google, en donde se comenzaba a modificar los resultados en funci&oacute;n de los intereses del usuario. Un a&ntilde;o m&aacute;s tarde, se comenzaba a almacenar y a mostrar el historial de b&uacute;squedas de cada usuario que se hab&iacute;a registrado...]]></description>
			<content:encoded><![CDATA[><p>Hace unos a&ntilde;os, nac&iacute;an las b&uacute;squedas personalizadas de Google, en donde se comenzaba a modificar los resultados en funci&oacute;n de los intereses del usuario. Un a&ntilde;o m&aacute;s tarde, se comenzaba a almacenar y a mostrar el historial de b&uacute;squedas de cada usuario que se hab&iacute;a registrado previamente con una cuenta de usuario de Google.</p>
<p>El buscador ven&iacute;a almacenando, por cuestiones t&eacute;cnicas, las b&uacute;squedas que se realizan desde cada una de las direcciones IP que se conectan al servicio. Sin embargo, la compa&ntilde;&iacute;a ha anunciado oficialmente que el historial de b&uacute;squedas se va a almacenar durante 6 meses para todos los usuarios, y no se relacionar&aacute; con nuestra direcci&oacute;n IP, sino con una 'cookie' de nuestro navegador web, incluso cuando el usuario no dispone de cuenta en Google.</p>
<p>Con esta 'cookie' (que se puede borrar en cualquier momento), Google va a distinguirnos no ya por nuestra direcci&oacute;n IP, sino por el navegador web que utilicemos. De esta manera, aunque nuestro proveedor de Internet nos cambie la direcci&oacute;n IP, o aunque estemos con nuestro port&aacute;til en otro pa&iacute;s, Google va a saber durante 180 d&iacute;as las b&uacute;squedas que hemos realizado.</p>
<p>El objetivo es, seg&uacute;n <a title="Abrir en una ventana nueva" href="http://googleblog.blogspot.com/2009/12/personalized-search-for-everyone.html" target="_blank">este post oficial</a> personalizar nuestras b&uacute;squedas, y ofrecernos los resultados m&aacute;s adecuados a nuestros gustos y preferencias. As&iacute;, por ejemplo, si cuando buscamos 'barcelona' siempre acabamos haciendo click en las p&aacute;ginas de hoteles, la siguiente vez que lo consultemos quiz&aacute; veamos sitios web de hoteles en las primeras posiciones.</p>
<p>Esta nueva caracter&iacute;stica del buscador nos trae consigo de nuevo la duda acerca de si Google va a tener en cuenta estos clicks para modificar los resultados tambi&eacute;n del resto de usuarios y cambiar el posicionamiento general de las b&uacute;squedas. Pero tambi&eacute;n traer&aacute; consigo una importante pol&eacute;mica sobre la privacidad de todos nosotros, puesto que desde ahora, en caso de que queramos cuidar un poco m&aacute;s los datos expuestos ante Google, habr&aacute; que preocuparse de eliminar la 'cookie' de 'google.com' (o el dominio de la versi&oacute;n local que utilicemos).</p>
<p>Para borrar esta 'cookie' existen varias soluciones, para Firefox, est&aacute;n las extensiones '<a title="Abrir en una ventana nueva" href="https://addons.mozilla.org/en-US/firefox/addon/10354" target="_blank">Google-anon</a>' o '<a title="Abrir en una ventana nueva" href="https://addons.mozilla.org/en-US/firefox/addon/1243" target="_blank">Cookie Manager</a>', <a title="Abrir en una ventana nueva" href="http://support.microsoft.com/kb/278835" target="_blank">este link</a> sobre las cookies en MS IExplorer, o <a title="Abrir en una ventana nueva" href="http://www.aboutcookies.org/Default.aspx?page=2" target="_blank">esta p&aacute;gina</a> m&aacute;s gen&eacute;rica sobre 'cookies'.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=13</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/busquedas-personalizadas-para-todos-los-usuarios-.html</feedburner:origLink>
		</item>
				
		<item>
			<title>HighCharts. Un API de gráficos bastante buena.</title>
			<link>http://www.imaginanet.com/blog/highcharts-un-api-de-graficos-bastante-buena.html</link>
			<guid>http://www.imaginanet.com/blog/highcharts-un-api-de-graficos-bastante-buena.html</guid>
			<comments>http://www.imaginanet.com/blog/highcharts-un-api-de-graficos-bastante-buena.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 14 Dec 2009 15:46:27 +0100</pubDate>
					<category><![CDATA[JavaScript]]></category>
					<category><![CDATA[jQuery]]></category>
					<description><![CDATA[Todos queremos mejores librer&iacute;as javascript de gr&aacute;ficos. Dojo tiene una buena opci&oacute;n que es Protovis, y por ah&iacute; hay muchas librer&iacute;as (deja un comentario con tu favorita).La &uacute;ltima en aparecer es HighCharts que usa tanto jQuery como MooTools para las tareas JavaScript m&aacute;s frecuentes....]]></description>
			<content:encoded><![CDATA[>Todos queremos mejores librer&iacute;as javascript de gr&aacute;ficos. Dojo tiene una buena opci&oacute;n que es <a title="Abrir en una ventana nueva" href="http://vis.stanford.edu/protovis/" target="_blank">Protovis</a>, y por ah&iacute; hay muchas librer&iacute;as (deja un comentario con tu favorita).<br />La &uacute;ltima en aparecer es <a title="Abrir en una ventana nueva" href="http://highcharts.com/" target="_blank">HighCharts</a> que usa tanto jQuery como MooTools para las tareas JavaScript m&aacute;s frecuentes. Adem&aacute;s, Internet Explorer necesita ExCanvas que emula al elemento Canvas.<br />Un ejemplo de gr&aacute;fica:<br />
<pre class="code js">var chart1 = new Highcharts.Chart({
         chart: {
            renderTo: 'chart-container-1',
            defaultSeriesType: 'bar'
         },
         title: {
            text: 'Fruit Consumption'
         },
         xAxis: {
            categories: ['Apples', 'Bananas', 'Oranges]
         },
         yAxis: {
            title: {
               text: 'Fruit eaten'
            }
         },
         series: [{
            name: 'Jane',
            data: [1, 0, 4]
         }, {
            name: 'John',
            data: [5, 7, 3]
         }]
      });
</pre>
<br />Devuelve algo as&iacute;:<br /><br /><img title="HighCharts ejemplo" src="/blog_files/images/highcharts.png" alt="HighCharts ejemplo" />]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=15</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/highcharts-un-api-de-graficos-bastante-buena.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Google Analytics desbloquea la carga de webs lanzando el modo asíncrono (Async Mode)</title>
			<link>http://www.imaginanet.com/blog/google-analytics-desbloquea-la-carga-de-webs-lanzando-el-modo-asincrono-async-mode.html</link>
			<guid>http://www.imaginanet.com/blog/google-analytics-desbloquea-la-carga-de-webs-lanzando-el-modo-asincrono-async-mode.html</guid>
			<comments>http://www.imaginanet.com/blog/google-analytics-desbloquea-la-carga-de-webs-lanzando-el-modo-asincrono-async-mode.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed,  2 Dec 2009 16:10:25 +0100</pubDate>
					<category><![CDATA[JavaScript]]></category>
					<category><![CDATA[Google Analytics]]></category>
					<description><![CDATA[Gran noticia la que acabo de leer que Google Analytics lanza un modo de seguimiento as&iacute;ncrono "Google analytics launches Asynchronous Tracking" (click aqu&iacute; para ver art&iacute;culo original).Al fin nuestro navegador no se va a enganchar cargando el c&oacute;digo JavaScript.El sistema har&aacute; que las webs...]]></description>
			<content:encoded><![CDATA[>Gran noticia la que acabo de leer que Google Analytics lanza un modo de seguimiento as&iacute;ncrono "<em>Google analytics launches Asynchronous Tracking</em>" (<a title="Abrir en una ventana nueva" href="http://googlecode.blogspot.com/2009/12/google-analytics-launches-asynchronous.html" target="_blank">click aqu&iacute; para ver art&iacute;culo original</a>).<br /><br />Al fin nuestro navegador no se va a enganchar cargando el c&oacute;digo JavaScript.<br /><br /><strong>El sistema har&aacute; que las webs funcionen m&aacute;s r&aacute;pido:</strong><br />El mayor problema de cargar archivos JavaScript es que bloquea el renderizado de la p&aacute;gina web y la descarga de otros recursos. En el nuevo modelo as&iacute;ncrono de Google Analytics, se utiliza el elemento Script del DOM.<br />Google Analytics, con su archivo ga.js, es un ejemplo perfecto de un script que debiera cargarse de forma as&iacute;ncrona, ya que no a&ntilde;ade contenido alguno a la p&aacute;gina, con lo cual, ser&iacute;a ideal cargarlo sin bloquear las im&aacute;genes y hojas de estilo que har&aacute;n que los usuarios vean lo que realmente han venido a ver: nuestra p&aacute;gina web.<br /><strong><br />Se ha mejorado la estabilidad:</strong><br />&iquest;Qu&eacute; pasa si un script tarda mucho tiempo en cargarse, o falla su carga? El usuario se encuentra ante una p&aacute;gina en blanco, ya que los scripts bloquean el renderizado de la web. Aunque Google Analytics tiene una infraestructura muy grande tras &eacute;l, cualquier recurso, sobre todo de terceros, tiene que a&ntilde;adirse con cautela. Es una gran noticia que GA est&aacute; proporcionando patrones que permite el renderizado de las webs mientras se carga ga.js.&nbsp;<br /><br /><strong>&iquest;Qu&eacute; hay que hacer para incluir ga.js en modo as&iacute;ncrono?</strong> cambia tu script para que sea de la forma siguiente:
<pre class="code js">var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-XXXXX-X']);
_gaq.push(['_trackPageview']);
(function() {
   var ga = document.createElement('script');
   ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
   ga.setAttribute('async', 'true');
   document.documentElement.firstChild.appendChild(ga);
})();
</pre>
<br /> 
<ul>
<li>L&oacute;gicamente, tienes que sustituir "UA-XXXXX-X" por tu ID.</li>
<li>Al cargarse ga.js de forma as&iacute;ncrona, tiene que existir una forma para que algunas funciones de GA se puedan utilizar cuando el c&oacute;digo se termina de cargar. Esto se hace introduciendo comandos en la cola del objeto de Google Analytics, _gaq.</li>
<li>Una vez que todos los comandos callback se han puesto en cola, se carga el script ga.js. Esto se empaqueta en una funci&oacute;n as&iacute;ncrona para as&iacute; evitar conflictos de namespace.</li>
<li>Se crea un elemento "script" y su fuente "src" se pone al valor correcto de la URL de ga.js. Mirando m&aacute;s alla, en el soporte que se incluye en HTML5 a los scripts as&iacute;ncronos, el atributo "async" se pone a "true", muy bueno! La ventaja m&aacute;s importante es que le dice al navegador que los siguientes scripts se pueden ejecutar de forma inmediata (no tienen que esperar a que se carge ga.js). La &uacute;ltima l&iacute;nea a&ntilde;ade el elemento script al DOM. Esto es lo que ejecuta la descarga de ga.js. En muchos c&oacute;digos se hace document.getElementsByTagName(&rdquo;head&rdquo;)[0].appendChild, pero esto falla si el documento no tiene elemento head. Esta forma de hacerlo, es m&aacute;s robusta.</li>
</ul>
<br />
<p>&nbsp;</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=9</wfw:commentRss>
			<slash:comments>1</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/google-analytics-desbloquea-la-carga-de-webs-lanzando-el-modo-asincrono-async-mode.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Galería de fotos polaroid, sólo usando CSS 3</title>
			<link>http://www.imaginanet.com/blog/galeria-de-fotos-polaroid-solo-usando-css-3.html</link>
			<guid>http://www.imaginanet.com/blog/galeria-de-fotos-polaroid-solo-usando-css-3.html</guid>
			<comments>http://www.imaginanet.com/blog/galeria-de-fotos-polaroid-solo-usando-css-3.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed,  2 Dec 2009 10:55:49 +0100</pubDate>
					<category><![CDATA[Web 2.0]]></category>
					<category><![CDATA[JavaScript]]></category>
					<category><![CDATA[CSS]]></category>
					<category><![CDATA[jQuery]]></category>
					<description><![CDATA[Viendo la galer&iacute;a de fotos con estilo polaroid que han creado en el blog de Tutorialzine, la cual utiliza jQuery y un m&iacute;nimo CSS3, que es una sombra "box-shadow" y una rotaci&oacute;n que utiliza "-webkit-transform". As&iacute; hemos creado una galer&iacute;a de fotos similar pero que &uacute;nicamente utiliza CSS 3,...]]></description>
			<content:encoded><![CDATA[>Viendo la galer&iacute;a de fotos con estilo polaroid que han creado en el <a title="Abrir en ventana nueva" href="http://tutorialzine.com/2009/11/hovering-gallery-css3-jquery/" target="_blank">blog de Tutorialzine</a>, la cual utiliza jQuery y un m&iacute;nimo CSS3, que es una sombra "box-shadow" y una rotaci&oacute;n que utiliza "-webkit-transform". <br />As&iacute; hemos creado una galer&iacute;a de fotos similar pero que &uacute;nicamente utiliza CSS 3, pero aplicando las diferentes opciones que permite este.<br /><br />El c&oacute;digo XHTML creado, &uacute;nicamente consta de una lista de im&aacute;genes (ul &gt; li) con su respectivo pie de imagen:
<pre class="code"><ul class="thumb">
    <li>
        <img src="/imaginanet/images/photo_1.jpg" alt="" width="480" height="340" />Globos
    </li>
    <li>
        <img src="/imaginanet/images/photo_2.jpg" alt="" width="480" height="332" />Coche
    </li>
    <li>
        <img src="/imaginanet/images/photo_3.jpg" alt="" width="480" height="321" />Niebla
    </li>
    <li>
        <img src="/imaginanet/images/photo_4.jpg" alt="" width="480" height="315" />Molino de viento
    </li>
    <li>
        <img src="/imaginanet/images/photo_5.jpg" alt="" width="480" height="324" />Bosque
    </li>
</ul>
</pre>
La hoja de estilos, la teneis <a title="Ver hoja de estilo en ventana nueva" href="/blog_files/css/galeria-polaroid.css" target="_blank">aqu&iacute;</a>, en ella, lo m&aacute;s destacable es:<br />Por un lado, tenemos el contenedor de todas las im&aacute;genes (UL), al cual le aplicamos un gradiente de fondo utilizando "<em>-webkit-gradient</em>" en la propiedad "<em>background</em>" del elemento. Aplicamos un gradiente circular o radial con una posici&oacute;n y tama&ntilde;o, que va de un gris m&aacute;s oscuro, a un gris m&aacute;s claro.
<pre class="code css">ul.thumb {
   position: relative;
   list-style: none;
   background: -webkit-gradient(radial, 45 45, 50, 50 10, 640, from(#555), to(#222)) !important;
   background: #666;
}
</pre>
<br />Tambi&eacute;n tenemos el posicionamiento y la rotaci&oacute;n que damos a cada LI, con su respectiva imagen y texto. Posicionamos el elemento centrado tanto en altura como en anchura, lo redimensionamos y le aplicamos sombra, adem&aacute;s, es importante tener en cuenta que este elemento tiene un efecto "ease-in-out" en el "-webkit-transition" con una duraci&oacute;n de 3 segundos, es el que hace que en WebKit, se amplien y reduzcan con el efecto de zoom . Adem&aacute;s, con el selector "<em>:nth-child()</em>", cambiamos la posici&oacute;n y giramos cada imagen, adem&aacute;s de aplicar a cada imagen una sombra.<br />
<pre class="code css">ul.thumb li {
   position: absolute;
   top: 50%;
   left: 50%;
   padding: 6px 6px 24px 6px;
   background: #FFF;
   width: 150px;
   height: 130px;
   -moz-box-shadow:1px 1px 6px #222;
   -webkit-box-shadow:1px 1px 6px #222;
   box-shadow:1px 1px 6px #222;
   -webkit-transition: all 3s ease-in-out;
   z-index: 0;
}
ul.thumb li img {
   width: 100%;
   height: 100%;
}
ul.thumb li:nth-child(1) {
   margin-top: -130px;
   margin-left: -130px;
   -moz-transform: rotate(30deg);
   -webkit-transform: rotate(30deg);
   transform: rotate(30deg);
}
</pre>
<br />Para terminar, tambi&eacute;n es muy destacable el estilo que aplicamos al estado ":hover" de cada imagen, en este, utilizamos "-webkit-transform" para cambiar la rotaci&oacute;n y poner la imagen completamente horizontal:
<pre class="code css">ul.thumb li:hover{
   font-size: 1.3em;
   z-index: 10;
   width: 480px;
   height: 322px;
   margin-top: -151px;
   margin-left: -240px;
   -moz-box-shadow:8px 8px 24px #111;
   -webkit-box-shadow:8px 8px 24px #111;
   box-shadow:8px 8px 24px #111;
   -moz-transform: rotate(0deg);
   -webkit-transform: rotate(0deg);
   transform: rotate(0deg);
}
</pre>
<br />La galer&iacute;a de fotos <a title="Ver demo de galer&iacute;a" href="/blog_files/galeria-polaroid.htm" target="_blank">podeis visualizarla aqu&iacute;</a> y es &uacute;nicamente funcional desde FireFox 3.5 (no veremos efecto de ampliaci&oacute;n alguno) y desde navegadores utilizando &uacute;ltimas versiones de WebKit, como por ejemplo Safari y Google Chrome (en estos, el efecto de ampliaci&oacute;n funciona gracias a -webkit-transition).<br /><br />La raz&oacute;n por la que no funcionar&aacute; en Internet Explorer (cualquier versi&oacute;n), es que este, ni en su &uacute;ltima versi&oacute;n cumple con el estandar CSS 3, por ejemplo, el selector :nth-child(N) no es reconocido por IE.<br />]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=7</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/galeria-de-fotos-polaroid-solo-usando-css-3.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Lo más buscado durante 2009</title>
			<link>http://www.imaginanet.com/blog/lo-mas-buscado-durante-2009.html</link>
			<guid>http://www.imaginanet.com/blog/lo-mas-buscado-durante-2009.html</guid>
			<comments>http://www.imaginanet.com/blog/lo-mas-buscado-durante-2009.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed,  2 Dec 2009 17:39:31 +0100</pubDate>
					<category><![CDATA[Buscadores]]></category>
					<category><![CDATA[Google]]></category>
					<description><![CDATA[Se ha publicado la informaci&oacute;n con las palabras que m&aacute;s se han buscado o consultado en los motores de b&uacute;squeda m&aacute;s populares.Como seguro que a cada uno le interesa una cosa distinta, os dejo una lista de enlaces a cada uno de los casos:AOLAskBingGoogle Espa&ntilde;aGoogleYahoo!Yahoo! Respuestas]]></description>
			<content:encoded><![CDATA[>Se ha publicado la informaci&oacute;n con las palabras que m&aacute;s se han buscado o consultado en los motores de b&uacute;squeda m&aacute;s populares.<br /><br />Como seguro que a cada uno le interesa una cosa distinta, os dejo una lista de enlaces a cada uno de los casos:<br /><a title="Abrir en una ventana nueva" href="http://hot.aol.com/" target="_blank">AOL</a><br /><a title="Abrir en una ventana nueva" href="http://sp.ask.com/2009/topquestions" target="_blank">Ask</a><br /><a title="Abrir en una ventana nueva" href="http://www.bing.com/community/blogs/search/archive/2009/11/30/top-bing-searches-in-2009.aspx" target="_blank">Bing</a><br /><a title="Abrir en una ventana nueva" href="http://www.google.com/intl/es_es/press/zeitgeist2009/index.html" target="_blank">Google Espa&ntilde;a</a><br /><a title="Abrir en una ventana nueva" href="http://www.google.com/intl/en_us/press/zeitgeist2009/index.html" target="_blank">Google</a><br /><a title="Abrir en una ventana nueva" href="http://yearinreview.yahoo.com/" target="_blank">Yahoo!</a><br /><a title="Abrir en una ventana nueva" href="http://yanswersblog.com/index.php/archives/2009/11/30/download-the-2009-answers-highlights-book/" target="_blank">Yahoo! Respuestas</a><br />]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=10</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/lo-mas-buscado-durante-2009.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Aumenta la longitud de búsqueda. Sobre todo en Google.</title>
			<link>http://www.imaginanet.com/blog/aumenta-la-longitud-de-busqueda--sobre-todo-en-google-.html</link>
			<guid>http://www.imaginanet.com/blog/aumenta-la-longitud-de-busqueda--sobre-todo-en-google-.html</guid>
			<comments>http://www.imaginanet.com/blog/aumenta-la-longitud-de-busqueda--sobre-todo-en-google-.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Wed,  2 Dec 2009 12:18:42 +0100</pubDate>
					<category><![CDATA[Buscadores]]></category>
					<category><![CDATA[SEO]]></category>
					<description><![CDATA[En el blog que Alan Long tiene en Hitwise, han sacado un nuevo estudio sobre la longitud de las b&uacute;squedas en los distintos buscadores web.En el informe se ve c&oacute;mo la longitud de las frases de b&uacute;squeda est&aacute; aumentando paulatinamente, y sobre todo, donde m&aacute;s est&aacute; aumentando es en Google....]]></description>
			<content:encoded><![CDATA[>En el blog que <a title="Ver en ventana nueva" href="http://weblogs.hitwise.com/alan-long/2009/11/searches_getting_longer.html" target="_blank">Alan Long tiene en Hitwise</a>, han sacado un nuevo estudio sobre la longitud de las b&uacute;squedas en los distintos buscadores web.<br /><br />En el informe se ve c&oacute;mo la longitud de las frases de b&uacute;squeda est&aacute; aumentando paulatinamente, y sobre todo, donde m&aacute;s est&aacute; aumentando es en Google. Esto &uacute;ltimo nos lleva a pensar si realmente esto est&aacute; asociado a la cada vez menor calidad de los resultados que obtenemos al realizar b&uacute;squedas con el buscador.<br />Y es que la larga cola est&aacute; comenzando a entrar en la mente de los usuarios, que pasan de querer algo poco definido a realizar consultas cada vez m&aacute;s elaboradas para llegar a la informaci&oacute;n que realmente quieren conseguir.<br /><br />El informe, adem&aacute;s de otros detalles, nos revela que la longitud de las consultas ha aumentado poco a poco con el paso del tiempo, y conforme aumenta el n&uacute;mero de personas que se erigen como profetas del posicionamiento en buscadores, y &uacute;nicamente buscan un posicionamiento, pero que para nada creo que se pueda llamar org&aacute;nico, sino posicionamiento que &uacute;nicamente genere tr&aacute;fico. No importa si el tr&aacute;fico generado es de buena, mediana o mala calidad.<br /><br />En mi opini&oacute;n, la longitud de b&uacute;squeda aumenta por una simple raz&oacute;n, los resultados tienen mucho posicionamiento, aunque el posicionamiento lo &uacute;nico que busque sea el click y no el cliente de calidad, esto, hace que los resultados iniciales tengan cada vez menos relevancia, y el usuario cada vez tenga que aumentar el n&uacute;mero de palabras de b&uacute;squeda para hacerla m&aacute;s espec&iacute;fica para lo que est&aacute; buscando.<br /><br />Tengo que decir adem&aacute;s, que es curioso ver c&oacute;mo la calidad del tr&aacute;fico generado por otros buscadores como puede ser Yahoo, es mucho mejor, y los usuarios captados a trav&eacute;s de estos, tienen un perfil de usuario que se ajusta much&iacute;simo mejor al perfil deseado.<br /><br />Para terminar, os incluyo una tabla resumen de las longitudes de b&uacute;squeda:<br /><br /><img title="Longitud de la cadena de b&uacute;squeda, tabla resumen." src="http://www.imaginanet.com/blog_files/images/srchtermlenght_xtended.png" alt="Longitud de la cadena de b&uacute;squeda, tabla resumen." /><br /><br /><br />El siguiente gr&aacute;fico muestra la longitud media de b&uacute;squeda, para todos los buscadores en general:<br /><br /><a onclick="window.open('/blog_files/images/searchtermlength.png','popup','width=849,height=450,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false" href="/blog_files/images/searchtermlength.png"><img title="Longitud de la cadena de b&uacute;squeda, media para todos los buscadores." src="http://www.imaginanet.com/blog_files/images/searchtermlength_small.png" alt="Longitud de la cadena de b&uacute;squeda, media para todos los buscadores." /></a><br /><br /><br />Mientras que en la siguiente, se muestra para los buscadores m&aacute;s importantes. En &eacute;l se puede apreciar c&oacute;mo dependiendo del buscador, hay bastante diferencia en longitudes de cadena de b&uacute;squeda:<br /><br /><a onclick="window.open('/blog_files/images/sengines_length.png','popup','width=849,height=450,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false" href="/blog_files/images/sengines_length.png"><img title="Longitud de la cadena de b&uacute;squeda, principales buscadores." src="http://www.imaginanet.com/blog_files/images/sengines_length_sml.png" alt="Longitud de la cadena de b&uacute;squeda, principales buscadores." width="429" height="222" /></a>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=8</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/aumenta-la-longitud-de-busqueda--sobre-todo-en-google-.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Haciendo páginas web atractivas y usables.</title>
			<link>http://www.imaginanet.com/blog/haciendo-paginas-web-atractivas-y-usables.html</link>
			<guid>http://www.imaginanet.com/blog/haciendo-paginas-web-atractivas-y-usables.html</guid>
			<comments>http://www.imaginanet.com/blog/haciendo-paginas-web-atractivas-y-usables.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue, 24 Nov 2009 10:05:37 +0100</pubDate>
					<category><![CDATA[Web 2.0]]></category>
					<category><![CDATA[XHTML]]></category>
					<category><![CDATA[CSS]]></category>
					<category><![CDATA[Ajax]]></category>
					<description><![CDATA[El presente artículo ha sido traducido del publicado en http://www.lazycat.org/postcards/  Diseños abiertos y elegantes, menores costes de ancho de banda y un mantenimiento mucho más fácil. ¿Os gusta la idea? Leed este artículo para conocer pequeños trucos que puedes aplicar al código, diseño y contenidos de tus páginas...]]></description>
			<content:encoded><![CDATA[><p style="display: inline; float: left;"><img style="display: inline; float: left; margin-right: 10px;" title="Haciendo páginas web atractivas y usables." src="/ftp/articulos_web/nakkeTattis.jpg" alt="Haciendo páginas web atractivas y usables." width="232" height="310" /> El presente artículo ha sido traducido del publicado en <a href="http://www.lazycat.org/postcards/">http://www.lazycat.org/postcards/</a><br /> <br /> Diseños abiertos y elegantes, menores costes de ancho de banda y un mantenimiento mucho más fácil.<br /> <br />¿Os gusta la idea? Leed este artículo para conocer pequeños trucos que puedes aplicar al código, diseño y contenidos de tus páginas web, y si alguno de los sitios web que visitas normalmente no da la talla, ¿porqué no comentarles que pueden hacer un cambio limpio, rápido y con muchas ventajas sobre lo que tiene?<br /> <br />Muchas páginas web incluyen enlaces a artículos relacionados y más información. Envíales URLs que creas les puedan ayudar y pienses que son útiles.</p>
<h3>Hojas de estilo alternativas</h3>
Son distintos puntos de vista. Añadir la posibilidad de visualizar una página web en formato impreso, o por ejemplo, en terminales de mano (pocket pc, palm os, ...), hacen que un sitio web sea visible por una mayor audiencia y así, aumente la satisfacción del cliente. De esta forma, los usuarios no tienen porque buscar una versión para imprimir (si existe claro) ya que las hojas de estilo para imprimir se cargan de forma automática en cualquier navegador web. <br /> Si está vendiendose algo, una disposición dedicada a la impresión, ahorra el esfuerzo y coste de crear y mantener archivos PDF independientes. Las hojas de estilo para medio impreso, pueden incluir reglas que impriman las urls junto con los enlaces, expandan los acrónimos y muestren la información de copyright. <br /> Existen hojas de estilo para TV, proyectores, lectores de texto, ... <br />
<h3>Fondos</h3>
Una imagen de fondo puede ser la diferencia entre una página web que atraiga todas las miradas y una página web que genere dolores de tripa. La elección de imagenes que puedan estirarse con el fondo, es esencial, así como el uso de colores apropiados y el hecho de asegurarse de que ls imágenes de fondo permanecen en el fondo.<br /> Si tienes dudas, quítala: un diseño simple y limpio, a veces funciona mejor que un diseño complejo y visualmente rico en grafismos. A veces, una página web diseñada de forma pobre da peor imagen que no tener página web.<br /> Hay que recordad que cualquier elemento puede tener una imagen de fondo o color de fondo si usa CSS, aprovechar esta ventaja permite la construcción de webs ricas en grafismo.<br />
<h3>Elección de los colores</h3>
Con los colores, como con muchas otras cosas, cuanto menos, a veces es mejor. Lo ideal es elegir entre tres y cinco colores para un diseño o para una sección del sitio web si se desea que estas sean distintas.<br /> Hay que ser cuidadoso con las connotaciones de los colores y amoldarlos a la audiencia que se espera atraer. Por ejemplo los visitantes del este pueden estar buscando colores vivos como rojos y amarillos para estar cómodos, por otro lado, los visitantes de occidente los pueden encontrar demasiado chillones para sus ojos e incluso ofencivos. Por ejemplo, Ladbrokes, amolda su esquema de colores a la procedencia de sus visitantes; si quieres una página web global, esta es posible.<br />
<h3>Tablas</h3>
Si todavia alguien está diseñando páginas web con tablas HTML, ¿cuantos años llevas perdido por el mundo? ¿dónde has estado? La comida ya se ha terminado y también te has perdido los postres, esto hace que no conozcas lo fácil y cómodo que puede ser hacer páginas web con CSS (hojas de estilo). Cuando alguien quiere atornillar un tornillo, que usa, ¿un martillo o un destornillador? Por la misma razón, porqué usar tablas HTML para maquetar páginas web. <br /> Es aconsejable diseñar de acuerdo con las especificaciones web estandares del momento, y además, conseguiras mayor control de la maqueta si la haces usando hojas de estilo. Las páginas web modernas estan basadas en los estandards web, cargan mucho más rápido, se ven más bonitas y te harán ahorrar dinero. Si tu jefe se entera de que no has estado cenando, ve pensando la explicación que vas a darle.]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=5</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/haciendo-paginas-web-atractivas-y-usables.html</feedburner:origLink>
		</item>
				
		<item>
			<title>19 consejos para construir páginas web</title>
			<link>http://www.imaginanet.com/blog/19-consejos-para-construir-paginas-web.html</link>
			<guid>http://www.imaginanet.com/blog/19-consejos-para-construir-paginas-web.html</guid>
			<comments>http://www.imaginanet.com/blog/19-consejos-para-construir-paginas-web.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 23 Nov 2009 20:25:48 +0100</pubDate>
					<category><![CDATA[Web 2.0]]></category>
					<description><![CDATA[Esto significa, que no pretendas re-inventar la navegaci&oacute;n por los sitios web. Pon las cosas a la izquierda, arriba, abajo, donde quieras, pero no reinventes la forma en que la gente interactua con entornos o interfaces digitales si lo que quieres es vender tu marca, tus productos o tus servicios. No confundas al usuario,...]]></description>
			<content:encoded><![CDATA[>Esto significa, que no pretendas re-inventar la navegaci&oacute;n por los sitios web. Pon las cosas a la izquierda, arriba, abajo, donde quieras, pero no reinventes la forma en que la gente interactua con entornos o interfaces digitales si lo que quieres es vender tu marca, tus productos o tus servicios. No confundas al usuario, puede sentirse mal y abandonar la web.<br />
<h3>Introducci&oacute;n</h3>
Este art&iacute;culo se ha extraido del original (<a href="http://www.josiahcole.com/2007/02/14/a-webmasters-19-commandments/">click aqu&iacute;</a>) titulado <a href="http://www.josiahcole.com/2007/02/14/a-webmasters-19-commandments/"><em>19 Things NOT To Do When Building a Website</em></a><em>.</em> El art&iacute;culo es muy did&aacute;ctico y creemos que expone cada uno de los casos con criterio y desde el punto de vista de la usabilidad.<br /> El autor ha recopilado una peque&ntilde;a lista de reglas b&aacute;sicas y fundamentales que todo webmaster debe tener en cuenta a la hora de desarrollas un sitio web que pretenda llegar a su p&uacute;blico con un m&iacute;nimo de &eacute;xito. Esta lista tambi&eacute;n pueden usarla las empresas que esten pensando en la creaci&oacute;n o re-estructuraci&oacute;n de su sitio web.<br />
<h3>No redimensionar la ventana del navegador</h3>
No cambiar el tama&ntilde;o de la ventana del navegador del usuario. Todos sabemos que se puede modificar el tama&ntilde;o de la ventana del usuario, y sabemos lo bien que uno se siente cuando tras poner un peque&ntilde;o trozo de c&oacute;digo Javascript ocurre un <em>milagro</em> que redimensiona la ventana al tama&ntilde;o que queremos, pero NO. Esta mala t&eacute;cnica web se ve en la mayor&iacute;a de casos con sitios web denominados <em>spam</em> o cuando un dise&ntilde;ador gr&aacute;fico no acostumbrado al entorno web, dise&ntilde;a un sitio web, es decir, alguien del sector de la fotograf&iacute;a, video o art&iacute;stico que tambi&eacute;n hace sitios web (ver consejo n&uacute;mero 6 para conocer m&aacute;s cosas sobre estos), pero a decir verdad no tiene idea alguna de c&oacute;mo crear un web exitoso y usable.<br /><img title="No redimensionar la ventana del navegador" src="http://farm1.static.flickr.com/150/391487797_e7749ccade.jpg?v=0" alt="No redimensionar la ventana del navegador" width="325" height="294" /><br />
<h3>Si quieres cargar una home, y a continuaci&oacute;n tu web en un pop-up, para nada te lo recomendamos.</h3>
Si tu web necesita que el visitante carge una p&aacute;gina de inicio y entonces acceda a la verdadera p&aacute;gina web en un pop up (ventana emergente), estas mareando al usuario, le das la bienvenida pero no es as&iacute;, le vuelves a dar la bienvenida. Si tu web no carga de forma inmediata con un inicio que aporte valor al visitante, es muy dificil que espere a que termine tu show de inicio (no le preocupa lo bonita y espectacular que es la p&aacute;gina de introducci&oacute;n). Esta t&eacute;cnica se ve con la mayor&iacute;a de desarrolladores web con Flash, los cuales, por alguna raz&oacute;n piensan que todos los sitios web en flash tienen que abrirse en una ventana emergente (estan dando por hecho que burlan los programas que bloquean ventanas emergentes) y tienen 30 segundos de carga de una introducci&oacute;n como <a href="http://www.2advanced.net/" target="_blank">www.2advanced.net</a><br />
<h3>Si preguntas que versi&oacute;n quieres: versi&oacute;n flash, html, alta resoluci&oacute;n, baja resoluci&oacute;n. Tambi&eacute;n pierdes oportunidad.</h3>
<p>Es como si le preguntases a alguien que quiere entrar en tu tienda, si quiere pasar a la tienda mala o a la buena (pero claro, hay que tener en cuenta que para entrar en la tienda buena hacen falta unas gafas especiales y una peque&ntilde;a espera de 30 segundos... MMM, NO gracias), lo que les estas preguntando es: "&iquest;Quieres irte y comprar en mi competencia? porque te estoy poniendo una muralla que tienes que saltar antes de que conozcas los productos o servicios que te ofrezco.</p>
<h3>Si tienes una web, toda en flash, hazla de nuevo.</h3>
Si tu web est&aacute; toda en Flash, echa a tu dise&ntilde;ador web y si la hiciste t&uacute;, a&ntilde;&aacute;dela a tu curriculum bajo la secci&oacute;n de "Proyectos sin utilidad que he realizado" y empieza de nuevo a hacer la web.&nbsp;<br /> Flash es una herramienta, una herramienta con much&iacute;simas posibilidades como animaciones, v&iacute;deo, carritos de la compra, interfaces, etc, la lista es muy grande pero las cosas en su medida. Esto no quiere decir que tengas que hacer un sitio web todo en Flash y si lo haces tendr&aacute;s una gran desventaja con tu competencia. F&iacute;jate en una cosa, hasta el propietario de Flash, <a href="http://www.adobe.com/">Macromedia/Adobe</a> no tiene su web toda en Flash, &iquest;sabes porqu&eacute;? Quieren hacer negocio y no hacen caso a los <em>dise&ntilde;adores</em>.<br /><img title="No hagas una web toda en flash" src="http://farm1.static.flickr.com/132/391506482_f6a6bdc635.jpg?v=0" alt="No hagas una web toda en flash" width="450" height="415" /><br />
<h3>NO intentes REinventar la navegaci&oacute;n por p&aacute;ginas web</h3>
<p>Situa los elementos gr&aacute;ficos en la zona de tu p&aacute;gina web que quieras, ponlos arriba, a la izquierda, tambi&eacute;n en la parte derecha puedes colocar elementos, pero sobre todo, no inventes la l&oacute;gica de navegaci&oacute;n, esto es, la manera en que las personas interactuan con interfaces digitales, a la misma vez que est&aacute;s intentando vender un producto o servicios. El usuario se confundir&aacute;, se enfadar&aacute;, y se ir&aacute;.</p>
<h3>&nbsp;Este trabajo me va a dar bastantes dolores de cabeza</h3>
<p>Si eres un dise&ntilde;ador gr&aacute;fico, y "de paso ofreces p&aacute;ginas web", estas dando consejos sobre dise&ntilde;o web, a tus clientes de trabajos gr&aacute;ficos impresos, se cauto con este tema. El dise&ntilde;o gr&aacute;fico para impresi&oacute;n se parece al dise&ntilde;o web lo mismo que un anuncio de un coche de carreras a conducir y construir ese coche de carreras. No cometamos errores, el dise&ntilde;o gr&aacute;fico es fant&aacute;stico por si mismo, sabes hacer gr&aacute;ficas perfectas y perfectos slogans para impresi&oacute;n. Un usuario no puede comprarte el producto con un anuncio impreso (por el momento), no pueden comunicarse con tu negocio a trav&eacute;s de un anuncio impreso. Ded&iacute;cate al dise&ntilde;o gr&aacute;fico y no metas tus narices en un medio que no conoces ni entiendes (lo mismo les digo a esos "t&eacute;cnicos" que haces websites "aprovechando la situaci&oacute;n")</p>
<h4>Si una p&aacute;gina de inicio no tiene contenido o cualquier texto Real (no incluido en una imagen) y esto mismo es extensible a todo el sitio web. Contrata a una persona que dote de contenido a la p&aacute;gina web y despide a tu webmaster.</h4>
<p>El contenido es el rey. Los buscadores no indexan gr&aacute;ficos o animaciones flash deslumbrantes, s&oacute;lo indexan texto. Contrata una persona que de contenidos relevantes y vinculados con tu negocio (es b&aacute;sico para tener un buen ranking y poder vender / ofrecer tus productos o servicios a trav&eacute;s de una p&aacute;gina web)</p>
<h4>Si tu p&aacute;gina web no funciona con Firefox, da la bienvenida a la metedura de pata m&aacute;s com&uacute;n de 2007.</h4>
<p>Realmente, Firefox s&oacute;lo genera entre el 10-15% de la cuota de mercado de los navegadores de usuario, pero en el caso de algunos sitios web, esta cuota es mucho m&aacute;s alta, por ejemplo, oomny.com tiene m&aacute;s del 80% de sus usuarios con Firefox. Adem&aacute;s, si quien hizo tu p&aacute;gina web, no la hizo compatible y funcional con Firefox, obviamente no tienen idea de lo que est&aacute;n haciendo y se est&aacute;n saliendo del juego. No hay raz&oacute;n por la que se necesite un sitio web s&oacute;lo compatible y totalmente dependiente de Internet Explorer para que no funcione en Firefox, y francamente, no hay raz&oacute;n alguna para ello. Que un webmaster no conozca Firefox, quiere decir que no est&aacute; en la cultura de Internet y esto puede hacer que tu imagen y la de tu negocio en Internet se vean afectados.</p>
<h3>Este punto es una colecci&oacute;n de peque&ntilde;as cosas que han hecho desaparecer a otros sitios web.</h3>
<p>Son principios b&aacute;sicos pero repetidos, como no mostrar texto parpadeante, no usar Frontpage, no utilizar pop-ups o ventanas emergentes, no hacer texto con scroll, obligar a la descarga de fuentes o tipograf&iacute;as especiales, utilizar introducciones Flash, ...</p>
<h3>Si utilizas m&uacute;sica en tu p&aacute;gina web cerciorarte de que el usuario pueda detenerla,</h3>
<p>y es MEJOR NO cargarla con la p&aacute;gina web sin que la solicite el usuario. Esto mismo, es aplicable al v&iacute;deo con audio, muchos usuarios de p&aacute;ginas web navegan desde su trabajo y no les hace mucha gracia que sus altavoces empiecen a sonar con tu espantosa m&uacute;sica de forma totalmente intrusiva en su ordenador, y m&aacute;s si su jefe est&aacute; pendiente y con ganas de darle a alguien una patada en el trasero.</p>]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=4</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/19-consejos-para-construir-paginas-web.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Activado automático de componentes en IE (Actualización de los cambios en componentes ActiveX de IE)</title>
			<link>http://www.imaginanet.com/blog/activado-automatico-de-componentes-en-ie-actualizacion-de-los-cambios-en-componentes-activex-de-ie.html</link>
			<guid>http://www.imaginanet.com/blog/activado-automatico-de-componentes-en-ie-actualizacion-de-los-cambios-en-componentes-activex-de-ie.html</guid>
			<comments>http://www.imaginanet.com/blog/activado-automatico-de-componentes-en-ie-actualizacion-de-los-cambios-en-componentes-activex-de-ie.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Thu, 29 Oct 2009 13:28:38 +0100</pubDate>
					<category><![CDATA[Internet Explorer]]></category>
					<category><![CDATA[Navegadores]]></category>
					<category><![CDATA[ActiveX]]></category>
					<description><![CDATA[Si miramos a abril de 2006, hicimos un cambio en la forma en que Internet Explorer manejaba los controles incrustados (embed) en bastantes p&aacute;ginas web. Algunos sitios web obligaban a los usuarios a "pulsar para activar" antes de que pudieran interactuar con el control. A dia de hoy, Microsoft ha obtenido la licencia de...]]></description>
			<content:encoded><![CDATA[>Si miramos a abril de 2006, hicimos un cambio en la forma en que Internet Explorer manejaba los controles incrustados (embed) en bastantes p&aacute;ginas web. Algunos sitios web obligaban a los usuarios a "pulsar para activar" antes de que pudieran interactuar con el control. A dia de hoy, Microsoft ha obtenido la licencia de Eolas, eliminando con esta el requisito de Internet Explorer de "pulsa para activar". Por esto, vamos a quitar el comportamiento "pulsar para activar el control" que ahora tiene IE.<br /> <br /> Es importante tener en cuenta que este cambio no necesitar&aacute; que se modifiquen&nbsp;las p&aacute;ginas web existentes hoy en d&iacute;a , ni acciones nuevas a tomar por parte de quienes crean y desarrollan p&aacute;ginas web. Simplemente estamos retrocediendo al comportamiento anterior. Una vez se actualice Internet Explorer, todas las p&aacute;ginas que ahora necesitan del "pulsar para activar" dejar&aacute;n de necesitarlo para que el control se active. Simplemente funcionar&aacute;. <br /> <img src="/ftp/articulos_web/activex_ie/clicktoactivate.png" alt="" /><br />Lo m&aacute;s normal es que actualmente te preguntes para cuando est&aacute; previsto lanzar esta actualizaci&oacute;n.<br /> <br /> La primera versi&oacute;n en pruebas, saldr&aacute; con una actualizaci&oacute;n opcional llamada Activaci&oacute;n de Componentes Autom&aacute;tica para Internet Explorer (Internet Explorer Automatic Component Activation Preview), y estar&aacute; disponible en Diciembre de 2007 en el Centro de Descargas de Microsoft. Adem&aacute;s, este cambio formar&aacute; parte de las pr&oacute;ximas versi&oacute;nes pre-release de Windows Vista SP1 y Windows XP SP3. Despu&eacute;s de haber dado tiempo a que los usuarios se preparen para este cambio, haremos que este comportamiento forme parte de la "Cumulative Update" de Internet Explorer en Abril de 2008, as&iacute;, todos los clientes que instalen esta actualizaci&oacute;n, aplicar&aacute;n este cambio a su IE.<br /> <br /> Si tienes una aplicaci&oacute;n a medida usando WebOC o MSHTML, habr&aacute; algunos cambios que afectar&aacute;n tu aplicaci&oacute;n. Por ejemplo:<br /> - Si la aplicaci&oacute;n usa el flag&nbsp;DOCHOSTUI para el "pulsar para activar", ese comportamiento se respetar&aacute; y tu aplicaci&oacute;n seguir&aacute; necesitando del "pulsar para activar".<br /> - Si la aplicaci&oacute;n usa la clave del registro FEATURE_ENABLE_ACTIVEX_INACTIVE_MODE para optar por el "pulsar para activar", esta clave de registro no ser&aacute; mantenida. Si quieres seguir utilizando el "pulsar para activar", por favor, utilliza el flag DOCHOSTUI.<br /> <br /> En las pr&oacute;ximas semanas actualizaremos en <a href="http://msdn.microsoft.com/ieupdate">art&iacute;culo en MSDN</a> con las descripciones del nuevo comportamiento. Estate atento en este enlace para saber cuando sale la preview.<br />]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=2</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/activado-automatico-de-componentes-en-ie-actualizacion-de-los-cambios-en-componentes-activex-de-ie.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Haciendo funcionar a las hojas de estilos alternativas</title>
			<link>http://www.imaginanet.com/blog/haciendo-funcionar-a-las-hojas-de-estilos-alternativas.html</link>
			<guid>http://www.imaginanet.com/blog/haciendo-funcionar-a-las-hojas-de-estilos-alternativas.html</guid>
			<comments>http://www.imaginanet.com/blog/haciendo-funcionar-a-las-hojas-de-estilos-alternativas.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Tue, 20 Oct 2009 12:35:41 +0100</pubDate>
					<category><![CDATA[JavaScript]]></category>
					<category><![CDATA[CSS]]></category>
					<description><![CDATA[Autor Original: Paul Sowden  URL ORIGINAL: http://www.alistapart.com/stories/alternate/  TÍTULO ORIGINAL: A List Apart: CSS: Making Alternate Style Sheets Work  Traducción al castellano: http://kusor.net/traducciones/ala.es/alternate/  Así, TIENES UN DOCUMENTO XHTML. Has sido un diseñador web bueno y utilizado hojas de estilos...]]></description>
			<content:encoded><![CDATA[><em><span style="text-decoration: underline;">Autor Original</span>: Paul Sowden <br /> <span style="text-decoration: underline;">URL ORIGINAL</span>: http://www.alistapart.com/stories/alternate/ <br /> <span style="text-decoration: underline;">TÍTULO ORIGINAL</span>: A List Apart: CSS: Making Alternate Style Sheets Work <br /> <span style="text-decoration: underline;">Traducción al castellano</span>: http://kusor.net/traducciones/ala.es/alternate/</em><br /> <br /> Así, TIENES UN DOCUMENTO XHTML. Has sido un diseñador web bueno y utilizado hojas de estilos para controlar el aspecto de tu documento. Incluso has ido mucho más allá y has creado varias hojas de estilo alternativas para demostrar lo duro que eres. <br /> <br /> Estupendo. Pero ahora necesitas un modo cross–browser de elegir dinámicamente entre las distintas hojas de estilos. <br /><br />
<h3>Dándole estilo a tu sitio</h3>
Las hojas de estilos pueden ser asociadas con los documentos usando una lista de elementos link en la cabecera del documento. Hay tres tipos de relación distintos que pueden tener las hojas de estilos externas con el documento: persistentes, preferridas, y alternativas.<br />
<h4>Persistentes</h4>
Estas hojas de estilos están habilitadas siempre (siempre están “encendidas”) y son combinadas con la hoja de estilos activa. Pueden utilizarse para compartir reglas comunes a todas las hojas de estilos. Para hacer una hoja de estilos persistente, el atributo rel es fijado a “stylesheet” y no se fija ningún atributo title. <br /> <br /> Para hacer persistente la hoja de estilos paul.css, el siguente elemento link debería ser incluido en la cabecera del documento:
<h4>Preferidas</h4>
Estas hojas de estilo están habilitadas por defecto (están “encendidas” cuando se ha cargado la página). Pueden ser deshabilitadas entonces, si el usuario eleige una hoja de estilos alternativa. <br /> <br /> Para hacer una hoja de estilos preferida, el atributo rel se fija a “stylesheet” y a la hoja de estilos se le asigna un nombre con el atributo title. <br /> <br /> Varias hojas de estilo preferidas pueden ser agrupadas dándoles atributos title idénticos. Estas hojas de estilos agrupadas serán entonces habilitadas y deshabilitadas juntas. Si se declara más de un grupo de hojas de estilo preferidas, el primero que se declare tendrá preferencia. <br /> <br /> Para hacer preferida a paul.css, es añadido un atributo title, dándole al estilo por defecto un nombre.<br />
<h4>Alternativas</h4>
Estas hojas de estilo pueden ser seleccionadas por el visitante como alternativas a la hoja de estilos preferida. Esto permite al visitante personalizar un sitio y elegir su disposición favorita. También pueden ser utilizadas para accesibilidad (por ejemplo, ALA tiene la hoja de estilos “friendly fonts” que proporciona fuentes mayores). <br /> <br /> Para especificar una hoja de estilos alternativa, el atributo rel se fija a “alternate stylesheet” y la hoja de estilos se nombra con un atributo title. Como pasa con las hojas de etilo preferidas, estas hojas de estilos pueden ser agrupadas juntas también dándoles atributos title idénticos. <br /> <br /> Usando de nuevo el ejemplo previo; para convertir paul.css en una hoja de estilos alternativa, la palabra “alternate” es añadida al atributo rel.<br /> Notar que estas relaciones sólo se aplican a hojas de estilo externas que hayan sido incluidas usando el elemento link.<br />
<h3>Intercambiando estilos</h3>
Cuando un documento es cargado inicialmente, las hojas de estilo persistentes y preferidas son aplicadas al documento. Las hojas de estilo alternativas pueden ser seleccionadas por el usuario. El W3C nos dice que el navegador debería proporcionarnos un medio de elegir la hoja de estilos que queremos utilizar, y sugiere que quizá un menú sesplegable o un abarra de herramientas debería ser proporcionada. <br /> <br /> Hasta aquí, muy bien. Tenemos varias hojas de estilos y el visitante puede elegir sus favoritas desde un menú. Pero entonces nos encontramos con un prolema. Uno importante. Mozilla proporciona un menú para seleccionar las hojas de estilos que queremos usar bajo un item del menú ver. Pero Microsoft Internet Explorer (MSIE) no proporciona ningún menú. Por lo que tenemos varias hojas de estilos, y ningún modo de acceder a ellas en MSIE. <br /> <br /> Aquí es donde un poco de JavaScript puede ser utilizado junto con el DOM para proporcionar un modo mediante el cuál los usuarios de MSIE y Mozilla puedan seleccionar la hoja de estilos que quieran utilizar. Sus preferencias pueden guardarse también en una cookie. Y como estamos utilizando las etiquetas link tal como nos dice el W3C, JavaScript no va a interferir con el menú en Mozilla, y va a degradar grácilmente. <br />
<h3>El Script</h3>
Primero necesitamos que el script sea capaz de diferenciar entre tres tipos diferentes de hojas de estilo. Esto es relativamente fácil de hacer, dado que sólo necesitamos comprobar dos de los atributos de cada elemento link. <br /> <br /> ¿Hay algún enlace a un elemento link?<br />
<pre class="code">HTMLLinkElement.getAttribute("rel").indexOf("style") != -1 </pre>
¿Hay un atributo title?
<pre class="code">HTMLListElement.getAttribute("title")</pre>
¿Contiene el atributo rel la palabra clave "alternate"?
<pre class="code">HTMLLinkElement.getAttribute("rel").indexOf("alt") != -1</pre>
Notar que estamos buscando la cadena “alt” porque algunos navegadores aceptan la palabra reservada “alternative” en lugar de “alternate.” <br /> <br /> Usando estos tres tipos de chequeo podemos escribir una función para elegir las hojas de estilos. Esto implica buscar todos los elemoentos link en el documento, deshabilitando todas las hojas de estilo preferidas y alternativas que no queremos que estén activas, y habilitando todas las hojas de estilo preferidas y alternativas que queremos que estén activas. <br /> <br /> Notar que sólamente los elementos link de hojas de estilo alternativas y preferidas tendrán un atributo title. <br /> <br /> La función de cambio tiene el aspecto siguiente:
<pre class="code">function setActiveStyleSheet(title) { <br /> var i, a, main; <br />  for(i=0; (a = document.getElementsByTagName("link")[i]); i++) { <br />    if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title")) { <br />     a.disabled = true; <br />     if(a.getAttribute("title") == title) a.disabled = false; <br />    } <br />  } <br />}  </pre>
<h4>Cookies</h4>
Ahora podemos cambiar las hojas de estilo. Estupendo. Tenemos una página más personalizada. Excelente. Pero no tenemos un sitio personalizado. Las preferencias se aplican sólo a la página actual; cuando la dejemos las preferencias se irán con ella. De cualquier modo, esta situaciónpuede ser rectificada con una cookie. <br /> <br /> Para guardar una cookie necesitamos otra función que devuelva la hoja de estilo actual. También necesitamos dos funciones que guarden y lean la cookie. <br /> <br /> Para devolver la hoja de estilo actual buscaremos una hoja de estilo preferida o alternativa que esté activa y miraremos su atributo title. <br /> <br /> Primero buscaremos de nuevo a través de todos los elementos link en el documento. Entoncdes comprobaremos que el link es una hoja de estilo. Si es así, comprobaremos que la hoja de estilo tiene un atributo title. Esto nos dirá que la hoja de estilo es bien preferida, bien alternativa. <br /> <br /> La última comprobación es ver si la hoja de estilo está activa o no. Si las tres búsquedas devuelven verdadero, tendremos la hoja de estilo actual y podremos devolver su atributo title. <br /> <br /> La función terminada tiene este aspecto:
<pre class="code">function getActiveStyleSheet() { <br /> var i, a; <br />   for(i=0; (a = document.getElementsByTagName("link")[i]); i++) { <br />    if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title") && !a.disabled) <br />    return a.getAttribute("title"); <br />   } <br /> return null; <br />} </pre>
Como este es un artículo sobre estilos, y las cookies son un tópico completamente diferente, no voy a explicar las funciones de las cookies aquí, pero si voy a incluirlas para tu conveniencia (estas funciones fueron escritas por el autor de ALA Peter-Paul Koch).
<pre class="code">function createCookie(name,value,days) { <br />   if (days) { <br />    var date = new Date(); <br />    date.setTime(date.getTime()+(days*24*60*60*1000)); <br />    var expires = "; expires="+date.toGMTString(); <br />   } <br />   else expires = ""; <br /> document.cookie = name+"="+value+expires+"; path=/"; <br />} <br /> <br />function readCookie(name) { <br /> var nameEQ = name + "="; <br /> var ca = document.cookie.split(';'); <br />    for(var i=0;i < ca.length;i++) { <br />     var c = ca[i]; <br />     while (c.charAt(0)==' ') c = c.substring(1,c.length); <br />     if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length); <br />    } <br /> return null; <br />} </pre>
Para usar estas funciones de cookies, necesitamos agregar onload y onunload event listeners a la ventana.<br />
<h4>onLoad</h4>
Hay un atributo especificado por el w3c DOM Level 2, “disabled,” que se fija a false cuando una hoja de estilos se aplica al documento. Este atributo es implementado correctamente en Mozilla, pero desafortunadamente no lo es en MSIE. <br /> <br /> MSIE tiene un atributo HTML propietario, también llamado “disabled”, que se aplica a los elementos link. Este atribute es fijado inicialmente a false para todos los elementos link. <br /> <br /> Para fijar el atributo disabled de MSIE tal como el atributo disabled del DOM Level 2, podemos llamar a la función setActiveStyleSheet() con el nombre de la hoja de estilo preferida. <br /> <br /> Para encontrar qué hoja de estilo es la preferida, necesitamos otra función. Dado que esta función es bastante similar a la función getActiveStyleSheet() no voy a explicar como funciona, pero aquí está su aspecto:
<pre class="code">function getPreferredStyleSheet() { <br /> var i, a; <br />    for(i=0; (a = document.getElementsByTagName("link")[i]); i++) { <br />     if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("rel").indexOf("alt") == -1 && a.getAttribute("title")) <br />     return a.getAttribute("title"); <br />    } <br /> return null; <br />} </pre>
en la función onload, primero fijamos una variable title. Ésta guardará el valor de la hoja de estilos previa que está almacenada en la cookie, o si no hay ninguna, el título de nuestra hoja de estilos preferida. Para hacer las cosas lógicas, vamos a llamar a la cookie “style.” <br /> <br /> Lo siguiente será llamar a la función setActiveStyleSheet() pasándole la variable title como title. Nuestra función onload será algo parecido a esto:
<pre class="code">window.onload = function(e) { <br />   var cookie = readCookie("style"); <br />   var title = cookie ? cookie : getPreferredStyleSheet(); <br />   setActiveStyleSheet(title); <br />} </pre>
Notar que es muy deseable llamar a esta función antes del evento onload, haciendo al documento que “pinte” con nuestro estilo preferido. <br /> <br /> Si eleiges hacer esto, asegúrate que dicha función es llamada después de haber definido las otras funciones y que los elementos link han sido definidos.<br />
<h4>onUnload</h4>
Guardar la cookie en el evento onunload es simple. Todo lo que tenemos que hacer es usar la función getActiveStyleSheet() para que nos devuelva la hoja de estilos activa, y guardarla en una cookie. Usando la función para guardar una cookie tendríamos finalmente algo como esto:
<pre class="code">window.onunload = function(e) { <br />   var title = getActiveStyleSheet(); <br />   createCookie("style", title, 365); <br />} </pre>
<h3>Juntándolo todo</h3>
Para usar estas funciones para hacer tu sitio web más sexy, necesitas incluirlas en tu documento. Para hacerlo más fácil, las he puesto todas juntas en un fichero javascript, preparado para que lo descargues y lo añadas a tu sitio. <br /> » <a href="http://www.alistapart.com/d/alternate/styleswitcher.js" target="_blank">Descargar styleswitcher.js </a><br /> <br /> Para incluir el fichero javascript, necesitas añadir un elemento script a la cabecera de tu documento, asegurándote de que está puesto después de todos los elementos link pertenecientes a hojas de estilo que tengas. El código HTML debería tener este aspecto:
<pre class="code"><script src="/scripts/styleswitcher.js" type="text/javascript"><!--mce:0--></script> </pre>
Para permitir al visitante cambiar la hoja de estilos activa, podrías usar los eventos onClick de javascript. Por ejemplo, para tener la opción de elegir entre dos temas con los títulos “default” y “paul,” podrías usar el siguiente HTML:
<pre class="code"><a onclick="setActiveStyleSheet('default'); return false;" href="#">change style to default</a> <br /><a onclick="setActiveStyleSheet('paul'); return false;" href="#">change style to paul</a> </pre>
Una vez que el visitante ha seleccionado un tema, éste será almacenado en una cookie. Para usar el mismo tema en todo tu sitio web, los mismos elementos link javascript link deberían ser incluidos en la cabecera de cada página del sitio. <br /> ¡Eso es todo Gente! <br /> <br /> Ahí lo tienes, un sitio web personalizable que utiliza elementos link para enlazar hojas de estilo como el W3C nos ha dicho que deberíamos hacer. ¡Disfrútalo! <br /> <br /> ::: Paul Sowden tiene 17 años (Londres, Inglaterra), y cree que la web sería un lugar mejor si todos usásemos tecnicas de diseño que cumpliesen con los estándares.<br />]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=1</wfw:commentRss>
			<slash:comments>0</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/haciendo-funcionar-a-las-hojas-de-estilos-alternativas.html</feedburner:origLink>
		</item>
				
		<item>
			<title>Arreglando tu página web con el DOCTYPE correcto</title>
			<link>http://www.imaginanet.com/blog/arreglando-tu-pagina-web-con-el-doctype-correcto.html</link>
			<guid>http://www.imaginanet.com/blog/arreglando-tu-pagina-web-con-el-doctype-correcto.html</guid>
			<comments>http://www.imaginanet.com/blog/arreglando-tu-pagina-web-con-el-doctype-correcto.html#comentarios</comments>
			<dc:creator>Imaginanet S.L.</dc:creator>
			<pubDate>Mon, 23 Nov 2009 19:49:19 +0100</pubDate>
					<category><![CDATA[XHTML]]></category>
					<description><![CDATA[Autor Original: Jeffrey ZeldmanURL ORIGINAL: http://www.alistapart.com/articles/doctype/T&Iacute;TULO ORIGINAL: A List Apart: Fixing Your Site With the Right DOCTYPELO HAS HECHO TODO BIEN, pero tu sitio web no tiene el aspecto deseado o funciona como deber&iacute;a hacerlo en los &uacute;ltimos navegadores.Has escrito XHTML y CSS...]]></description>
			<content:encoded><![CDATA[><em><span style="text-decoration: underline;">Autor Original</span>: Jeffrey Zeldman<br /><span style="text-decoration: underline;">URL ORIGINAL</span>: http://www.alistapart.com/articles/doctype/<br /><span style="text-decoration: underline;">T&Iacute;TULO ORIGINAL</span>: A List Apart: Fixing Your Site With the Right DOCTYPE</em><br /><br />LO HAS HECHO TODO BIEN, pero tu sitio web no tiene el aspecto deseado o funciona como deber&iacute;a hacerlo en los &uacute;ltimos navegadores.<br /><br />Has escrito XHTML y CSS v&aacute;lidos. Has utilizado el Modelo de Objetos del Documento (DOM) est&aacute;ndar del W3C para manipular din&aacute;micamente los elementos de la p&aacute;gina. A pesar de todo, en navegadores dise&ntilde;ados para soportar todos estos est&aacute;ndares, tu sitio est&aacute; fallando. Un DOCTYPE - tipo de documento - defectuoso tiene la culpa de ello.<br /><br />Este peque&ntilde;o art&iacute;culo te proporcionar&aacute; DOCTYPEs que funcionen, y explicar&aacute; el efecto pr&aacute;ctico, en el mundo real de estas etiquetas aparentemente abstractas. <br />
<h3>&iquest;PORQU&Eacute; UN DOCTYPE?</h3>
Para los est&aacute;ndares HTML y XHTML, un DOCTYPE (abreviatura de &ldquo;declaraci&oacute;n de tipo de documento&rdquo;) informa al validador de la versi&oacute;n de (X)HTML que est&aacute;s utilizando, y deber&iacute;a aparecer al principio de cada p&aacute;gina web. Los DOCTYPEs son un componente clave de las p&aacute;ginas veb de conformidad: tu marcado y tus CSS no validar&aacute;n sin ellos.<br /><br />Como fu&eacute; mencionado en art&iacute;culos previos de ALA (y en otros lugares interesantes), los DOCTYPES tambi&eacute;n son esenciales para la apropiada renderizaci&oacute;n y funcionamiento de los documentos web en navegadores de conformidad como Mozilla, IE5/Mac, y IE6/Win.<br /><br />Un DOCTYPE reciente, que incluye una URI completa(una direcci&oacute;n web completa) les dice a estos navegadores que rendericen tu p&aacute;gina en modo conforme con los est&aacute;ndares, tratando tus (X)HTML, CSS, y DOM como esperas que deben ser tratados.<br /><br />Usando un DOCTYPE incompleto u obsoleto&mdash;o ning&uacute;n DOCTYPE&mdash;colocar&aacute; a los mismos navegadores en modo &ldquo;Caprichoso&rdquo;, bajo el que el navegador asume que has escrito a la vieja usanza, marcado inv&aacute;lido y c&oacute;digo para las deprimentes normas de la industria de finales de los 1990.<br /><br />Con esta configuraci&oacute;n, el navegador va a intentar parsear tu p&aacute;gina en modo compatible hacia atr&aacute;s, renderizando tus CSS como deber&iacute;an haber sido vistas en IE4, y revirtiendo a un DOM propietario, espec&iacute;fico de los navegadores. (IE revierte al DOM IE; Mozilla y Netscape 6 revierten a vaya usted a saber.)<br /><br />Claramente, esto no es lo que quer&iacute;as. Pero es frecuentemente lo que tienes, dada la preponderancia de informaci&oacute;n incompleta o incorrecta sobre el DOCTYPE que este art&iacute;culo espera corregir.<br /><br />(Nota: El navegador Opera no se rije por estas reglas; siempre trata de renderizar las p&aacute;ginas en modo conforme con los est&aacute;ndares. &iexcl;Vamos, Opera! En el otro lado, Opera todav&iacute;a no ofrece un soporte s&oacute;lido para el DOM del W3C. Pero est&aacute;n trabajando en ello.) <br />
<h3>&iquest;D&Oacute;NDE HAN IDO A PARAR TODOS LOS DOCTYPES?</h3>
Partiendo de que los DOCTYPES son vitales para el apropiado funcionamiento de los est&aacute;ndares de la web en los navegadores, y dado que el W3C es el principal creador de los est&aacute;ndares de la web, podr&iacute;as esperar que el <a href="http://w3.org/">sitio web</a> del W3C proporcionase un listado de DOCTYPEs apropiados, y podr&iacute;as esperar tambi&eacute;n ser capaza de encontrar esta informaci&oacute;n r&aacute;pida y f&aacute;cilmente en una localizaci&oacute;n &uacute;nica. Pero como que esto est&aacute; escrito, que no puedes. <br /> <br /> W3.org no es <a href="http://www.alistapart.com/">A List Apart</a>, <a href="http://webreference.com/">WebReference</a>, o <a href="http://www.webmonkey.com/">Webmonkey</a>. Su intenci&oacute;n no es ayudar a los dise&ntilde;adores web, desarrolladores, y gente que trabaja con contenidos similares a avanzar m&aacute;s r&aacute;pido en las &uacute;ltimas pr&aacute;cticas y recomendaciones tecnol&oacute;gicas. Ese no es su trabajo. <br /> <br /> W3C publica una serie de <a href="http://www.w3.org/2002/03/tutorials.html">tutoriales</a>, que la mayor&iacute;a de dise&ntilde;adores web ignoran. Sin embargo, el sitio web del W3C aloja principalmente una colecci&oacute;n de propuestas, borradores, y Recomendaciones, escritas por especialistas para especialistas. Y cuando digo especialistas, no quiero decir profesionales web ordinarios, como t&uacute; y como yo. Quiero decir especialistas que hacen que el resto de nosotros la Abuela el primer d&iacute;a que Ella Tuvo un Mail.&trade; <br /> <br /> Puedes buscar DOCTYPEs todo el d&iacute;a en w3.org sin encontrar una p&aacute;gina que ofrezca un listado completo de todos ellos. Y cuando consigues cazar un DOCTYPE (generalmente en relaci&oacute;n con una Recomendaci&oacute;n o Borrador de Trabajo), frecuentemente se trata de uno que no funciona en tu sitio web. <br /> <br /> Dispersos por el sitio web del W3C hay DOCTYPEs con URIs perdidas, y DOCTYPEs con URIs relativas que apuntan a documentos en el propio sitio web del W3C. Una vez que son desplazados del sitio del W3C y utilizados en tus propias p&aacute;ginas web, dichas URIs apuntan a documentos no existentes, haciendo por tanto que sean en vano tus mayores esfuerzos y que fallen los navegadores. <br /> <br /> Por ejemplo, mucho sitios muestran estos DOCTYPEs, copiados y pegados directamente de w3.org:<br />
<pre class="code"> <br /><br /></pre>
Si te fijas en la &uacute;ltima parte del DOCTYPE (&ldquo;DTD/xhtml1-strict.dtd&rdquo;), podr&aacute;s ver que es un link relativo a un documento en el sitio del W3C. Partiendo de que este documento est&aacute; en el sitio web del W3C pero no en el tuyo, la URI carece de utilidad para el navegador. <br /> <br /> El DOCTYPE que te gustar&iacute;a utilizar es:<br /> Debes observar que este &uacute;ltimo DOCTYPE incluye una URI completa al final de la etiqueta. Y como la etiqueta proporciona una localizaci&oacute;n v&aacute;lida en la web, el navegador sabe d&oacute;nde encontrarla, y renderizar&aacute; tu documento en modo conforme con los est&aacute;ndares.<br />
<h3>DOCTYPES QUE FUNCIONAN</h3>
Entonces, &iquest;qu&eacute; DOCTYPEs deber&iacute;amos utilizar? Me alegro de que lo preguntes. Los siguientes DOCTYPEs completos son los &uacute;nicos que necesitamos: <br />
<h4>HTML 4.01 Strict, Transitional, Frameset</h4>
<pre class="code">
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"&gt;
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"&gt;
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd"&gt;
</pre>
<h4>XHTML 1.0 Strict, Transitional, Frameset</h4>
<pre class="code">
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"&gt;
</pre>
<h4>XHTML 1.1 DTD</h4>
<pre class="code">
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"&gt;
</pre>
<h3>SIGUIENTES PASOS</h3>
&iquest;C&oacute;mo puedes colaborar a la mejora del soporte de los est&aacute;ndares en la web? Adem&aacute;s de agregar a favoriots esta p&aacute;gina (y copiar y pegar estos DOCTYPEs para tu propio uso), si tu editor web inserta DOCTYPEs, deber&iacute;as echarles un vistazo y compararlos con los listados arriba. <br /> <br /> Demasiados fabricantes de software bien-intencionados han copiado y pegado DOCTYPEs incompletos del W3C en su software. Resultado: cuando usas la funcionalidad de estos programas de insertar DOCTYPEs en tus p&aacute;ginas, los navegadores se ponen en modo Caprichoso, deshaciendo todo tu laborioso trabajo. <br /> <br /> Merece la pena contactar con la gente que hace tu paquete de autor favorito, mostr&aacute;ndoles los DOCTYPEs apropiados, y sugerirles cort&eacute;smente que tengan en cuenta este aspecto en la siguiente actualizaci&oacute;n. (En algunos casos, tambi&eacute;n ser&aacute;s capaz de <a href="http://www.alistapart.com/articles/dreamweaver/">modificar tu editor</a> por t&iacute; mismo.) <br /><br />Tenemos todas las razones para creer que el sitio del W3C lanzar&aacute; pronto una lista de DOCTYPES acertados, utilizables, y otra informaci&oacute;n esencial en una localizaci&oacute;n f&aacute;cil de encontrar. De hecho, Karl Dubost, Conformance Manager del equipo del W3C <a href="http://www.w3.org/QA/">Quality Assurance</a>, contribuy&oacute; a la informaci&oacute;n de este peque&ntilde;o art&iacute;culo. <br /> <br /> Del mismo modo, el relanzamiento de <a href="http://www.webstandards.org/">The Web Standards Project</a> proporciona en sus p&aacute;ginas <a href="http://www.webstandards.org/learn/templates/">esta informaci&oacute;n</a>.<br />]]></content:encoded>
			<wfw:commentRss>http://www.imaginanet.com/feeds.htm?blog=3</wfw:commentRss>
			<slash:comments>2</slash:comments>
			<feedburner:origLink>http://www.imaginanet.com/blog/arreglando-tu-pagina-web-con-el-doctype-correcto.html</feedburner:origLink>
		</item>
		</channel>
</rss>