Bookmarklet: Navegar por internet sin hacer click

Esta vez traigo una curiosidad que se me ha ocurrido programar. Resulta que estoy harto de las ventanas popup que aparecen por todos lados en algunas webs, cada vez que haces click en cualquier cosa. Con esto vas a poder activar una especie de navegación sin clicks ¿Intrigado?

Hola, soy malnuer y empezaré diciendo que me parece muy bien que haya publicidad en internet, pero eso sí, siempre que no sea intrusiva. Esas musiquitas de navidad a todo volumen o anuncios a pantalla completa que te saltan a la cara cuando pulsas algo, o los videos que no te interesan y que no puedes saltarte… son cosas que empiezan a cruzar la frontera de lo aceptable (al menos para mí, que conste).

Los popups están también en esta categoría. Se trata de nuevas ventanas (o pestañas) que se abren espontaneamente en el navegador, y que cargan la web del producto que se quiere publicitar sin que tú lo hayas pedido. Esta despreciable práctica estaba muy extendida antiguamente, pero con el tiempo, los navegadores aprendieron a detectarlo y bloquearlo. Sin embargo, todavía quedaba un resquicio, una forma de engañar a los navegadores. Si el popup intenta abrirse justo a la vez que el usuario pulsa sobre un enlace, el navegador no tiene forma de saber si es un popup de publicidad o si se trata de algo que el usuario ha querido cargar voluntariamente ¿Cómo acabar entonces con los popups?

Si hacer click es el truco para colarte un popup, eliminar el click evitará el popup.

Esto, que suena a revelación budista, es fácil de conseguir con pocas líneas de código, que son las que voy a explicar a continuación. La intención será que el navegador siga un enlace cuando dejemos el ratón parado encima de un link durante un par de segundos, pero sin hacer click.

Primero necesitaremos identificar todos los enlaces de la página y después los recorreremos uno a uno con un bucle:

var all = document.getElementsByTagName("a");
for(var i=0,j=all.length;i<j;i++){
...
}

Dentro del bucle lo que haremos es asignar un evento onmouseover y otro onmouseout a cada enlace de la lista. Queremos que cuando nos pongamos encima de uno de estos enlaces, se ponga en marcha un contador de tiempo de un par de segundos y si llega a cumplirse el tiempo, navegaremos hacia el href. Por otro lado, si durante este tiempo nos quitamos de encima, se anulará el contador. Para controlar este contador necesitaremos una variable en la que guardar su «handler»:

var h = null;
var all = document.getElementsByTagName("a");
for(var i=0, j=all.length; i<j; i++){
  all[i].onmouseover = function(){
    var a = this;
    h = window.setTimeout(function(){ window.location = a.href; },2000);
  };
  all[i].onmouseout = function(){
    window.clearTimeout(h);
  };
}

He puesto en azul la asignación del evento onmouseover y en naranja el evento onmouseout para que se vea mejor. Por lo demás, creo que se entiende perfectamente. En todo caso, podría despistar el uso de la variable «a» en la parte azul del código. Si estás familiarizado con el concepto de closure, seguro que lo ves claro, pero si no, puedo decirte que si hubiese puesto: window.location = this.href; no hubiese funcionado bien, porque la palabra clave «this» no haría referencia al «this» de la función que nosotros queremos en realidad. Al crear la variable «a» estamos «dejando fijo» sobre quién queremos ejecutar el «.href» y así no hay problemas.

Además no hace falta pasar el valor de la variable «a» a la función que va a usarla, porque cuando defines una función en Javascript, ésta siempre se guarda en la memoria junto a su contexto (o ámbito) más inmediato, que en este caso sería la variable «a«. Si todo esto te parece muy raro, te recomiendo que busques información sobre contextos de Javascript y closures, o que preguntes en los comentarios.

Acabamos con la versión definitiva para Bookmarklet: (recuerda poner el «javascript:» al principio)

Navegación sin clicks:

(function(h){var all=document.getElementsByTagName("a");for(var i=0,j=all.length;i<j;i++){all[i].onmouseover=function(){var a=this;h=window.setTimeout(function(){window.location=a.href},2000);};all[i].onmouseout=function(){window.clearTimeout(h);};}})();

También puedes arrastrar esto a marcadores: [bookmarklet texto=»Navegar sin clicks»]KGZ1bmN0aW9uKGgpe3ZhciBhbGw9ZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ2EnKTtmb3IodmFyIGk9MCxqPWFsbC5sZW5ndGg7aTxqO2krKyl7YWxsW2ldLm9ubW91c2VvdmVyPWZ1bmN0aW9uKCl7dmFyIGE9dGhpcztoPXdpbmRvdy5zZXRUaW1lb3V0KGZ1bmN0aW9uKCl7d2luZG93LmxvY2F0aW9uPWEuaHJlZn0sMjAwMCk7fTthbGxbaV0ub25tb3VzZW91dD1mdW5jdGlvbigpe3dpbmRvdy5jbGVhclRpbWVvdXQoaCk7fTt9fSkoKTs=[/bookmarklet]

El inconveniente de usar esto, es que hay que activarlo de nuevo cada vez que cambiemos de página, por eso es más una curiosidad que algo realmente útil. Pero bueno, seguro que le encuentras algún uso. Y por supuesto, siempre puedes meterlo en una extensión de Chrome (por ejemplo) para que esté siempre activo.


¿Sabes qué? vamos a darle un último toque mejorado. Vamos a usar colores para marcar los enlaces de la página y que además vayan cambiando de tono mientras estás encima. No es que vaya a quedar mucho más bonito, pero sí nos dará información visual, que siempre viene bien.

El plan es que a todos los enlaces les pongamos un background rojo, y que cuando te pongas encima y te quedes ahí, vaya cambiando a amarillo. Si el color llega a amarillo intenso cargaremos el href del enlace, y si nos quitamos de encima, volveremos a ponerlo rojo.

Necesitaremos un par de variables más. Una para guardar la referencia al enlace que vamos a activar y otra para llevar un contador de tiempo. Ahora no podemos usar un setTimeout, tenemos que usar un setInterval porque queremos ir cambiando el color del background sucesivamente y poco a poco. Por último, como la función del setInterval será un poco más larga que antes, la pondremos aparte y la llamaremos loop. Manos a la obra:

var t = 0;
var a = null;
var h = null;
var all = document.getElementsByTagName("a");
for(var i=0,j=all.length;i<j;i++){
  all[i].style.background = "rgb(255,0,0)";
  all[i].onmouseover = function(){
    t = 0;
    a = this;
    h = window.setInterval(loop,20);
  };
  all[i].onmouseout = function(){
    a.style.background = "rgb(255,0,0)";
    window.clearInterval(h);
  };
}
function loop(){
  t+=5;
  if(t>255){
    window.location=a.href;
    window.clearInterval(h);
    a.style.background = "rgb(0,255,0)";
  }else{
    a.style.background = "rgb(255,"+t+",0)";
  }
}

He puesto en azul el onmouseover y en naranja el onmouseout igual que antes, y además he puesto en verde la función loop que se ejecutará todo el tiempo mientras estemos encima de un enlace.

Lo primero que encontramos, son las declaraciones de variables: t es el contador de tiempo, a es la referencia al enlace sobre el que tenemos el ratón y h es (igual que antes) el handler del setInterval. Al ejecutarse el Bookmarklet, todos los enlaces recibirán (por medio del bucle), los eventos onmouseover y onmouseout, y también se ganarán un bonito background rojo.

Cuando te pongas encima de un enlace, el temporizador se pondrá a cero, se guardará la referencia al enlace y se pondrá en marcha el loop, que se ejecutará cada 20 milisegundos.

Si te quitas de encima del enlace, se pondrá el background rojo de nuevo y se eliminará el interval gracias a que hemos guardado el handler.

Pero si no te quitas de encima y te quedas ahí el tiempo suficiente, lo que ocurrirá es que cada 20 milisegundos se incrementará en 5 el contador. Qué raro, ¿por qué no 1 en vez de 5? esto es porque vamos a usar el contador para la componente de color verde del background y necesitamos que llegue a 255 un poco más rápido. Después de incrementar, vemos si ya hemos pasado de 255, y si es así, pondremos la dirección del enlace en el navegador, eliminamos el interval, y ponemos un fondo verde al enlace. Si no hemos llegado todavía al amarillo, simplemente ponemos el nuevo tono que será cada vez más amarillo.

(function(t,a,h){var all=document.getElementsByTagName("a");for(var i=0,j=all.length;i<j;i++){all[i].style.background="rgb(255,0,0)";all[i].onmouseover=function(){t=0;a=this;h=window.setInterval(loop,20);};all[i].onmouseout=function(){a.style.background="rgb(255,0,0)";window.clearInterval(h);};}function loop(){t+=5;if(t>255){window.location=a.href;window.clearInterval(h);a.style.background="rgb(0,255,0)";}else{a.style.background="rgb(255,"+t+",0)";}}})();

Puedes arrastrar esto a marcadores: [bookmarklet texto=»Navegar sin clicks»]KGZ1bmN0aW9uKHQsYSxoKXt2YXIgYWxsPWRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdhJyk7Zm9yKHZhciBpPTAsaj1hbGwubGVuZ3RoO2k8ajtpKyspe2FsbFtpXS5zdHlsZS5iYWNrZ3JvdW5kPSdyZ2IoMjU1LDAsMCknO2FsbFtpXS5vbm1vdXNlb3Zlcj1mdW5jdGlvbigpe3Q9MDthPXRoaXM7aD13aW5kb3cuc2V0SW50ZXJ2YWwobG9vcCwyMCk7fTthbGxbaV0ub25tb3VzZW91dD1mdW5jdGlvbigpe2Euc3R5bGUuYmFja2dyb3VuZD0ncmdiKDI1NSwwLDApJzt3aW5kb3cuY2xlYXJJbnRlcnZhbChoKTt9O31mdW5jdGlvbiBsb29wKCl7dCs9NTtpZih0PjI1NSl7d2luZG93LmxvY2F0aW9uPWEuaHJlZjt3aW5kb3cuY2xlYXJJbnRlcnZhbChoKTthLnN0eWxlLmJhY2tncm91bmQ9J3JnYigwLDI1NSwwKSc7fWVsc2V7YS5zdHlsZS5iYWNrZ3JvdW5kPSdyZ2IoMjU1LCcrdCsnLDApJzt9fX0pKCk7[/bookmarklet]

Esa era la versión definitiva para que te construyas tu Bookmarklet. Por cierto, si no sabes qué es un Bookmarklet o cómo se configuran, puedes leerlo al final de este artículo: Bookmarklet – Cargar jQuery u otro archivo Javascript

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedIn