Bug de IE – radiobutton olvidadizos al ser movidos entre el DOM

Esta semana tuve que invertir (perder) mi tiempo intentando entender y solucionar un comportamiento extraño de IE que resultó ser un bug que aparentemente existe en todas las versiones de este navegador y que fue solucionado según dicen en la versión 8 beta2.

A grandes razgos el problema sucede cuando se tiene una lista de radiobuttons (no sucede con otros componentes incluyendo el text o los checkboxes) y esta es trasladada entre el árbol DOM de la página, como por ejemplo cuando se mueve el formulario de un div a otro.  Cuando esto sucede, a IE se le olvida mágicamente cual era el radio seleccionado.

Para no volver a perder el tiempo con este error de IE hice una pequeña implementación de un formulario que reproduce las condiciones del error y le indica al usuario si el navegador utilizado padece o no del bug.

Inicialmente se tiene un formulario dentro del div seccion1 y otro div seccion2 vacío.

<div id='seccion1'>
    <form id='formulario' action='#' onSubmit='return procesarEnvio()'>

        <input type='radio' id='uno'    name='grupo' value='1' />
        <label for="uno">Primera opción.</label><br />
        <input type='radio' id='dos'    name='grupo' value='2' />
        <label for="dos">Segunda opción.</label><br />
        <input type='radio' id='tres'   name='grupo' value='3' />
        <label for="tres">Tercera opción.</label><br />
        <input type='radio' id='cuatro' name='grupo' value='4' />
        <label for="cuatro">Cuarta opción.</label><br />
        <input type='radio' id='cinco'  name='grupo' value='5' />
        <label for="cinco">Quinta opción.</label><br />

        <br />

        <input type='submit' value='Enviar' />

    </form>
</div>

<div id='seccion2'>
</div>

Cuando el usuario envía el formulario se obtiene el radio seleccionado.

        var seleccion1 = obtSeleccionValor('seccion1', 'formulario', 'grupo');

        alert("[1] El 'radiobutton' seleccionado es: " + seleccion1);

No hay problemas.  Para reproducir las condiciones del bug, se mueve, para este ejemplo con la ayuda de Prototype, al formulario de la seccion1 a la seccion2.

        var formulario = $$('#seccion1 #formulario').first();

        $('seccion2').insert(formulario);

Se vuelve a consultar cual es el radio seleccionado.

        var seleccion2 = obtSeleccionValor('seccion2', 'formulario', 'grupo');

        alert("[2] El 'radiobutton' seleccionado es: " + seleccion2);

Si seleccion1 == seleccion2 significa que se está utilizando un buen navegador, de lo contrario significa que se está utilizando un navegador ampliamente conocido por desconocer estándares y ser la pesadilla de los desarrolladores.

Desafortunadamente no encontré una solución elegante para este problema diferente de almacenar temporalmente cual es el radio seleccionado antes de realizar su movimiento en el DOM y actualizar su valor posteriormente.

Esto es práctico de hacer con Prototype.

        var formulario = $$('#' + secc + ' #' + form).first();

        var seleccion = formulario.getInputs('radio', grp).find(
            function(re)
            {
                return re.checked;
            });

Esta sección de código obtiene los radios del formulario form que se encuentran contenidos en el div secc, que pertenecen al grupo grp y que se encuentran seleccionados.  seleccion será undefined si ninguno de los radios se encuentra actualmente seleccionado.

        var seleccion = formulario.getInputs('radio', grp);

        if(seleccion[sel] != undefined)
              seleccion[sel].checked = true;

Esta sección corrige el valor seleccionado (sel) entre los radios (seleccion).  Dependiendo de la información contenida en los value y referenciada por sel, podrá ser una mejor opción recorrer la seleccion y realizar las comparaciones necesarias para activar (checked) al radio adecuado.

Utilice la aplicación demostración para verificar la presencia del bug en su navegador y para revisar con mayor precisión su código fuente.

Enlace: BugIERadioMovDom 0.1.

Leave a Reply

Your email address will not be published. Required fields are marked *