Arreglando Safari

19
Diciembre
2006

Vamos a dejarlo claro: IE sucks (IE7 sucks menos pero sigue sucks), Firefox sucks, Opera sucks, Safari sucks y Lynx sucks (estos tíos siguen sin implementar las imágenes). Después de dejar claro que todos los navegadores fallan por una cosa u otra vamos a intentar arreglar un poco uno de ellos. Hoy le toca a Safari, el navegador por defecto de Mac OS X, derivado de KHTML, aunque creo que Konqueror sí enfoca a los controles.

El problema esta vez es que Safari no hace ni caso al atributo for de los elementos label de la página. Según la documentación del W3C el atributo for (traduzco) “asocia explicitamente la label [etiqueta] que se está definiendo con otro control. Cuando está presente, el valor del atributo debe ser el mismo que el valor del atributo id de algún otro control en el mismo documento”, y además “cuando un elemento label recibe el foco, transpasará el foco a su control asociado”. Firefox hace eso, Opera hace eso, incluso IE consigue hacer eso, pero Safari se lo pasa por… donde los bytes no ven el sol. Ejemplo:

Por suerte se puede arreglar con un poco de Javascript, que simulará el comportamiento de los otros tres navegadores en Safari (siempre que el usuario tenga Javascript activado, claro).

function fixSafariLabels(labels)
{
  if (navigator.userAgent.toLowerCase().indexOf(’applewebkit’) == -1) return;
  labels = labels || document.getElementsByTagName(’label’);
  
  for (var index = 0; index < labels.length; index++) {
    if (labels[index].hasAttribute(’for’)) {
      var id = labels[index].getAttribute(’for’);
      var field = document.getElementById(id);
      
      if (!field) continue;
      
      Event.observe(labels[index], ‘click’,
        function(evt) {
          var id, field;
          id = this.getAttribute(’for’);
          if (field = document.getElementById(id)) {
            field.focus();
          }
        }
      );
      
      var type;
      if (field.hasAttribute(’type’) &&
        (type = field.getAttribute(’type’).toLowerCase()) &&
        (type == ‘checkbox’ || type == ‘radio’)) {
        Event.observe(labels[index], ‘click’,
          function(evt) {
            var id, field;
            id = this.getAttribute(’for’);
            if (field = document.getElementById(id)) {
              field.click();
            }
          }
        )
      }
    }
  }
}

La función en realidad es muy sencilla. Acepta un argumento labels que será un array de etiquetas que queramos arreglar, pero si no lo proporcionamos intentará arreglar todas las etiquetas del documento (la opción del argumento viene bien cuando creamos etiquetas dinámicamente en la página). Con todas las etiquetas indicadas comprueba si especifican un atributo for y si la referencia es válida y ese caso añade la función que pasa el foco de la etiqueta al control en el evento click. La segunda parte de la función intenta imitar el comportamiento que tienen IE, Firefox y Opera cuando las etiquetas están asociadas a un checkbox o a un radio button, que no sólo le transpasan el foco, sino que realizan un “click” sobre él.

La función es (juraría) JavaScript puro excepto por los Event.observe() para “instalar” los nuevos gestores, que es parte de Prototype, pero es una función sin la que no puedo vivir. Para aplicar la función a todos los controles de una página lo más cómodo es añadirla al evento load del documento. Por ejemplo:

Event.observe(window, 'load', function(evt) { fixSafariLabels(); });

No se puede utilizar directamente la función como tercer argumento y se necesita una función anónima auxiliar porque si no recibiríamos como parámetro el evento generado y la función no realizaría lo que se supone debería hacer.


4 comentarios a “Arreglando Safari”

  1. Gravatar Gandalfj dice:

    ¡Si es que el mejor navegador es el de la PSP!

    (broma….)

  2. Gravatar Daniel dice:

    Pues aunque no lo imagines el navegador de la PSP (y el de la PS3, al parecer) no está nada mal: se llama NetFront y soporta una buena ristra de tecnologías web (seguro que alguna de ellas mejor que el innombrable).

    Existe una versión para Linux, si no me equivoco, aunque personalmente diseñar teniendo en cuenta a los cuatro gatos que tienen una PSP me parece excesivo ¿no?

  3. Gravatar Gandalfj dice:

    ¡Meowwwwwwwwwwwwwwwwwwwwwww!

    En cuanto a lo de diseñar para cuatro gatos, hombre, fijate el Windows XP, que no lo usa nadie, y siguen sacando updates y tal ;)

  4. Gravatar Daniel dice:

    Lo escribí mal. Corrijo: “los cuatro gatos que utilizan un PSP para navegar”.

Deja un comentario

Puedes enterarte de las respuestas a tus comentarios de esta entrada mediante myComments.

XHTML: Puedes utilizar las siguientes etiquetas: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Tu servidor sin límites: 20GB de espacio, 1TB de transferencia, 1 dominio gratuito. Por 1.5€ al mes utilizando el código "RUIDOBLANCO" en DreamHost. Más información.