Contenido

Google Analytics ya permite tracking asíncrono

2 dic

+ 1

Ayer Google Anlytics anunció en formato Beta como  usar el formato asíncrono para el tracking de nuestros datos. Haciendo caso de los estándares HTML5 nos permite especificar el atributo async al especificar la llamada a Google Analytics.

<script type="text/javascript">
  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);
  })();

</script>

Como vemos en el código, al elemento <script /> generado dinámicamente le añadimos el atributo async, igualado a true, que hará que el script se carge asíncronamente a la carga de la página.

Por otro lado, vemos que la variable _gaq pasa a ser un array al que le vamos añadiendo nuevos arrays con clave valor para indicar los datos, haciendo posible que una vez se termine de cargar el código procedente de Google evalue los datos encontrados en él y los procese uno tras otro, lo que permite que tengamos una serie de datos que pueden ser cargados incluso antes de cargar el código de ga.js.

En defensa de los derechos fundamentales en internet

2 dic

+ 10

Ante la inclusión en el Anteproyecto de Ley de Economía sostenible de modificaciones legislativas que afectan al libre ejercicio de las libertades de expresión, información y el derecho de acceso a la cultura a través de Internet, los periodistas, bloggers, usuarios, profesionales y creadores de internet manifestamos nuestra firme oposición al proyecto, y declaramos que:

  1. Los derechos de autor no pueden situarse por encima de los derechos fundamentales de los ciudadanos, como el derecho a la privacidad, a la seguridad, a la presunción de inocencia, a la tutela judicial efectiva y a la libertad de expresión.
  2. La suspensión de derechos fundamentales es y debe seguir siendo competencia exclusiva del poder judicial. Ni un cierre sin sentencia. Este anteproyecto, en contra de lo establecido en el artículo 20.5 de la Constitución, pone en manos de un órgano no judicial -un organismo dependiente del ministerio de Cultura-, la potestad de impedir a los ciudadanos españoles el acceso a cualquier página web.
  3. La nueva legislación creará inseguridad jurídica en todo el sector tecnológico español, perjudicando uno de los pocos campos de desarrollo y futuro de nuestra economía, entorpeciendo la creación de empresas, introduciendo trabas a la libre competencia y ralentizando su proyección internacional.
  4. La nueva legislación propuesta amenaza a los nuevos creadores y entorpece la creación cultural. Con Internet y los sucesivos avances tecnológicos se ha democratizado extraordinariamente la creación y emisión de contenidos de todo tipo, que ya no provienen prevalentemente de las industrias culturales tradicionales, sino de multitud de fuentes diferentes.
  5. Los autores, como todos los trabajadores, tienen derecho a vivir de su trabajo con nuevas ideas creativas, modelos de negocio y actividades asociadas a sus creaciones. Intentar sostener con cambios legislativos a una industria obsoleta que no sabe adaptarse a este nuevo entorno no es ni justo ni realista. Si su modelo de negocio se basaba en el control de las copias de las obras y en Internet no es posible sin vulnerar derechos fundamentales, deberían buscar otro modelo.
  6. Consideramos que las industrias culturales necesitan para sobrevivir alternativas modernas, eficaces, creíbles y asequibles y que se adecuen a los nuevos usos sociales, en lugar de limitaciones tan desproporcionadas como ineficaces para el fin que dicen perseguir.
  7. Internet debe funcionar de forma libre y sin interferencias políticas auspiciadas por sectores que pretenden perpetuar obsoletos modelos de negocio e imposibilitar que el saber humano siga siendo libre.
  8. Exigimos que el Gobierno garantice por ley la neutralidad de la Red, en España ante cualquier presión que pueda producirse, como marco para el desarrollo de una economía sostenible y realista de cara al futuro.
  9. Proponemos una verdadera reforma del derecho de propiedad intelectual orientada a su fin: devolver a la sociedad el conocimiento, promover el dominio público y limitar los abusos de las entidades gestoras.
  10. En democracia las leyes y sus modificaciones deben aprobarse tras el oportuno debate público y habiendo consultado previamente a todas las partes implicadas. No es de recibo que se realicen cambios legislativos que afectan a derechos fundamentales en una ley no orgánica y que versa sobre otra materia.

Este manifiesto, elaborado de forma conjunta por varios autores, es de todos y de ninguno. Se ha publicado en multitud de sitios web.

Si estás de acuerdo y quieres sumarte a él, difúndelo por Internet.

También está disponible en inglés, catalán, asturiano y gallego.

WordPress 2.9 beta 2

2 dic

+ 4

WordPress anuncia hoy la versión 2.9 beta 2, disponible para descargar desde ya.

En esta versión ya podemos ir testeando algunas de las mejoras que dispondremos al 100% en la versión final:

Para desarrolladores tenemos:

  • Tabla meta de comentarios (con add_comment_meta())
  • Mejoras en el soporte de los custom fields
  • register_theme_directory() para mejorar los themes
  • Mejora en la interconexión PHP/Javascript con JSON
  • y muchas más …

Los usuarios podrán disfrutar ya en esta versión de:

Emile, el framework JS para animaciones CSS de 55 líneas

1 dic

+ 1

Emile es una de esas maravillas que con tan solo 55 líneas nos permite disponer de efectos CSS con Javascript en nuestras aplicaciones.

<!-- Cargamos la librería -->
script src="emile.js"></script>

<!-- Definimos los elementos -->
<div id="test1" style="position:absolute;left:0px;background:#f00;opacity:0">test</div>
<div id="test2" style="border:0px solid #00ff00;position:absolute;left:0px;top:400px;background:#0f0">test</div>

<!-- definimos los efectos -->
<script>
// Aplicamos el efecto al elemento #test2
  emile('test2', 'left:300px;padding:10px;border:50px solid #ff0000', {
    duration: 500,
    after: function(){
      // Aplicamos el efecto al elemento #test1
      emile('test1', 'background:#0f0;left:100px;padding-bottom:100px;opacity:1', {
        duration: 4000, easing: bounce
      });
    }
  });
  // Función que cambia la posición del elemento
  function bounce(pos) {
    if (pos < (1/2.75)) {
        return (7.5625*pos*pos);
    } else if (pos < (2/2.75)) {
        return (7.5625*(pos-=(1.5/2.75))*pos + .75);
    } else if (pos < (2.5/2.75)) {
        return (7.5625*(pos-=(2.25/2.75))*pos + .9375);
    } else {
        return (7.5625*(pos-=(2.625/2.75))*pos + .984375);
    }
  }
</script>

El proyecto lo podeis descargar desde github.com y ver el ejemplo de uso que nos incluye.

¿Como detectan el navegador los diferentes frameworks Javascript?

1 dic

+ 2

Detectar el navegador no siempre es la mejor solución para condicionar nuestros scripts, siempre que podamos deberíamos detectar si las funcionalidades que vamos a ejecutar están disponibles y en caso de no estarlo ofrecer una alternativa, sin importar el navegador. Pero, como bien sabemos, no siempre podemos hacer lo correcto.

En estos casos, saber como lo hacen los frameworks Javascript más usados nos permitirá hacernos una idea de como actuar frente a este problema.

jQuery

Aunque desde la versión 1.3 el atributo browser está desaprovado, aún está disponible en el código para que se vayan migrando los scripts. Supongo que en breve dejará de estar, dejando paso a la detección de funcionalidades.

var userAgent = navigator.userAgent.toLowerCase();
// Figure out what browser is being used
jQuery.browser = {
	version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
	safari: /webkit/.test( userAgent ),
	opera: /opera/.test( userAgent ),
	msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
	mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
};

En este caso, hace uso del userAgent para comprobar mediante expresiones regulares el navegador del usuario. Se trata de una comprobación muy genérica y que no nos permite detectar móviles.

MooTools

Por otro lado, MooTools, nos ofrece un objeto (Browser) que nos permite detectar el motor de renderizado sin importar el navegador.

var Browser = $merge({
  Engine: {name: 'unknown', version: 0},
  Platform: {name: (window.orientation != undefined) ? 'ipod' : (navigator.platform.match(/mac|win|linux/i) || ['other'])[0].toLowerCase()},
  Features: {xpath: !!(document.evaluate), air: !!(window.runtime), query: !!(document.querySelector)},
  Plugins: {},
  Engines: {
    presto: function(){
      return (!window.opera) ? false : ((arguments.callee.caller) ? 960 : ((document.getElementsByClassName) ? 950 : 925));
    },
    trident: function(){
      return (!window.ActiveXObject) ? false : ((window.XMLHttpRequest) ? ((document.querySelectorAll) ? 6 : 5) : 4);
    },
    webkit: function(){
      return (navigator.taintEnabled) ? false : ((Browser.Features.xpath) ? ((Browser.Features.query) ? 525 : 420) : 419);
    },
    gecko: function(){
      return (!document.getBoxObjectFor && window.mozInnerScreenX == null) ? false : ((document.getElementsByClassName) ? 19 : 18);
    }
  }
}, Browser || {});

Como podemos ver, se encarga de realizar una serie de comprobaciones de funcionalidades para determinar el motor de renderizado que está usando el visitante.

Prototype

Prototype, al igual que MooTools nos ofrece un objeto (Browser) que nos ofrece la versión del navegador.

Browser: (function(){
   var ua = navigator.userAgent;
   // Opera (at least) 8.x+ has "Opera" as a [[Class]] of `window.opera`
   // This is a safer inference than plain boolean type conversion of `window.opera`
   var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
   return {
     IE: !!window.attachEvent && !isOpera,
     Opera: isOpera,
     WebKit: ua.indexOf('AppleWebKit/') > -1,
     Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
     MobileSafari: /Apple.*Mobile.*Safari/.test(ua)
   }
 })(),

Al igual que jQuery comprueba el navegador mediante expresiones regulares simples que no nos permite detectar versiones móviles.

YUI

YUI nos ofrece un atributo que nos indicará el navegador que está usando el usuario.

ua = nav && nav.userAgent,
if (ua) {

  if ((/windows|win32/i).test(ua)) {
    o.os = 'windows';
  } else if ((/macintosh/i).test(ua)) {
    o.os = 'macintosh';
  }

  // Modern KHTML browsers should qualify as Safari X-Grade
  if ((/KHTML/).test(ua)) {
    o.webkit=1;
  }
  // Modern WebKit browsers are at least X-Grade
  m=ua.match(/AppleWebKit\/([^\s]*)/);
  if (m&&m[1]) {
    o.webkit=numberfy(m[1]);

    // Mobile browser check
    if (/ Mobile\//.test(ua)) {
      o.mobile = "Apple"; // iPhone or iPod Touch
    } else {
      m=ua.match(/NokiaN[^\/]*|Android \d\.\d|webOS\/\d\.\d/);
      if (m) {
        o.mobile = m[0]; // Nokia N-series, Android, webOS, ex: NokiaN95
      }
    }

    m=ua.match(/AdobeAIR\/([^\s]*)/);
    if (m) {
      o.air = m[0]; // Adobe AIR 1.0 or better
    }

  }

  if (!o.webkit) { // not webkit
    // @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr)
    m=ua.match(/Opera[\s\/]([^\s]*)/);
    if (m&&m[1]) {
      o.opera=numberfy(m[1]);
      m=ua.match(/Opera Mini[^;]*/);
      if (m) {
        o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316
      }
    } else { // not opera or webkit
      m=ua.match(/MSIE\s([^;]*)/);
      if (m&&m[1]) {
        o.ie=numberfy(m[1]);
      } else { // not opera, webkit, or IE
        m=ua.match(/Gecko\/([^\s]*)/);
        if (m) {
          o.gecko=1; // Gecko detected, look for revision
          m=ua.match(/rv:([^\s\)]*)/);
          if (m&&m[1]) {
            o.gecko=numberfy(m[1]);
          }
        }
      }
    }
  }
}

Al igual que jQuery y Prototype, recurre a las expresiones regulares para detectar el navegador, con la diferencia de que esta implementación nos permite detectar alguna versión más de las disponibles.

El src de una imágen puede cargarse tu página

1 dic

+ 4

Nicholas C.Zakas publica un artículo que muestra que cada navegador interpreta los estándares web como quiere. En este caso nos pone un ejemplo:

<img src="" />

y el mismo en Javascript

var img = new Image();
img.src = "";

En los ejemplos vemos que creamos un tag <img /> (en Javascript un objeto Image()) al que no le indicamos la ruta de la imagen.

Estudiando el resultado en los diferentes navegadores, ha descubierto que partiendo de la URL http://www.ejemplo.com/bla/ejemplo.html se diferencian dos resultados:

  • Internet Explorer: Realiza una única petición al directorio en el que está alojada la página.
  • Firefox, Safari y Chrome: Realizan una petición a la misma página que hace la petición.
  • Opera: No hace nada.

El caso que nos preocupa sería el provocado por Firefox, Safari y Chrome, ya que al volver a cargar la página que está ejecutando la petición cargará otra nueva versión de la página que provocará el mismo problema al volver a ejecutar la petición de nuevo y así hasta que el servidor aguante. A mayor número de visitas mayor número de peticiones.

Este problema que parece muy concreto puede darse fácilmente con una construcción php tan simple como esta:

<img src="$imageUrl" >

Aunque Nicholas nos propone una solución en PHP que mediante htaccess redirigimos todas las imágenes por una página PHP que comprueba que el referrer sea diferente al de la página.

<?php
    //Works for IE only when using path URLs and not file URLs

    //get the referrer
    $referrer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';

    //current URL (assuming HTTP and default port)
    $url = "http://" . $_SERVER['HTTP_HOST']  . $_SERVER['REQUEST_URI'];

    //make sure they're not the same
    if ($referrer == $url){
        exit;
    }
?>

Esta solución, aunque no es muy apropiada ya que nos va a ejecutar este código por cada imagen que usemos en nuestra página, nos permite salir del paso mientras los navegadores se van actualizando, cosa que ya están haciendo.