Conseguir que jQuery reconozca .change () en IE

131

Estoy usando jQuery para ocultar y mostrar elementos cuando se altera / hace clic en un grupo de botones de radio. Funciona bien en navegadores como Firefox, pero en IE 6 y 7, la acción solo ocurre cuando el usuario hace clic en otro lugar de la página.

Para elaborar, cuando carga la página, todo se ve bien. En Firefox, si hace clic en un botón de opción, se oculta una fila de la tabla y la otra se muestra inmediatamente. Sin embargo, en IE 6 y 7, hace clic en el botón de opción y no pasará nada hasta que haga clic en algún lugar de la página. Solo entonces IE vuelve a dibujar la página, ocultando y mostrando los elementos relevantes.

Aquí está el jQuery que estoy usando:

$(document).ready(function () {
  $(".hiddenOnLoad").hide();

  $("#viewByOrg").change(function () {
    $(".visibleOnLoad").show();
    $(".hiddenOnLoad").hide();
  });

  $("#viewByProduct").change(function () {
    $(".visibleOnLoad").hide();
    $(".hiddenOnLoad").show();
  });
});

Aquí está la parte del XHTML que afecta. Toda la página se valida como XHTML 1.0 Strict.

<tr>
  <td>View by:</td>
  <td>
    <p>
      <input type="radio" name="viewBy" id="viewByOrg" value="organisation"
      checked="checked" />Organisation</p>
    <p>
      <input type="radio" name="viewBy" id="viewByProduct" value="product" />Product</p>
  </td>
</tr>
<tr class="visibleOnLoad">
  <td>Organisation:</td>
  <td>
    <select name="organisation" id="organisation" multiple="multiple" size="10">
      <option value="1">Option 1</option>
      <option value="2">Option 2</option>
    </select>
  </td>
</tr>
<tr class="hiddenOnLoad">
  <td>Product:</td>
  <td>
    <select name="product" id="product" multiple="multiple" size="10">
      <option value="1">Option 1</option>
      <option value="2">Option 2</option>
    </select>
  </td>
</tr>

Si alguien tiene alguna idea de por qué sucede esto y cómo solucionarlo, ¡sería muy apreciado!

Philip Morton
fuente

Respuestas:

96

Intenta usar en .clicklugar de .change.

Paolo Bergantino
fuente
3
@samjudson, en mis pruebas esto no es correcto y el clic de jquery se dispara cuando selecciono el siguiente botón de radio con las teclas de flecha. (vista, ie7)
svandragt
1
@ Pacifika: No es para mí en IE7. Al menos lo hace bien. "hacer clic" es un evento totalmente diferente de "cambio" y hay al menos algunos casos (si no todos) donde es un sustituto inapropiado.
Bobby Jack
3
@samjudson: los eventos de clic en los botones de opción y las casillas de verificación también se activan al seleccionarlos con el teclado. Funciona en todos los navegadores
Philippe Leybaert
44
Estoy corregido, ¡ese parece ser el caso, por muy contradictorio que sea!
Bobby Jack
2
Esta parece ser la respuesta más popular a esta pregunta en particular, ¡pero no es completamente correcta! clickdifiere de changeque su controlador de eventos también se llamará al hacer clic en la opción ya seleccionada, mientras changeque no. Esta respuesta tiene un ejemplo de cómo usar jQuery .datapara comparar los valores antiguos y nuevos.
Laoujin
54

El problema con el uso del clickevento en lugar de changees que obtienes el evento si se selecciona la misma casilla de radio (es decir, no ha cambiado realmente). Esto se puede filtrar si verifica que el nuevo valor sea diferente al anterior. Esto me parece un poco molesto.

Si usa el changeevento, puede notar que reconocerá el cambio después de hacer clic en cualquier otro elemento en IE. Si llama blur()al clickevento, hará que el changeevento se active (solo si las cajas de radio realmente han cambiado).

Así es como lo estoy haciendo:

// This is the hack for IE
if ($.browser.msie) {
  $("#viewByOrg").click(function() {
    this.blur();
    this.focus();
  });
}

$("#viewByOrg").change(function() {
  // Do stuff here
});

Ahora puede usar el evento change como normal.

Editar: se agregó una llamada a focus () para evitar problemas de accesibilidad (vea el comentario de Bobby a continuación).

Mark A. Nicolosi
fuente
2
Es un truco muy malvado, porque evita que los usuarios naveguen con el teclado, porque el foco desaparece después de seleccionar un botón de radio.
Philippe Leybaert el
55
Esto es genial, pero causa problemas de accesibilidad del teclado. Una vez que se desencadena el evento blur (), el botón de radio ya no está enfocado, por lo que moverse entre los botones de radio con el teclado se vuelve extremadamente incómodo. Mi solución actual es agregar una llamada a "this.focus ();" inmediatamente después de la declaración blur ().
Bobby Jack
1
Creo que es la peor solución presentada, debido a los problemas de accesibilidad.
Philippe Leybaert el
11
Pero el problema de accesibilidad se puede resolver con una llamada a focus (). Es al menos tan bueno como usar click () para todo.
Bobby Jack
Gracias Bobby, lo agregaré a la respuesta.
Mark A. Nicolosi
33

¿Has probado el evento onpropertychange de IE? No sé si hace la diferencia, pero probablemente valga la pena intentarlo. IE no activa el evento de cambio cuando los valores se actualizan a través del código JS, pero tal vez onpropertychange funcionaría en este caso.

$("#viewByOrg").bind($.browser.msie? 'propertychange': 'change', function(e) {
  e.preventDefault(); // Your code here 
}); 
Kevin
fuente
"hacer clic" no parecía funcionar, pero "cambio de propiedad" sí. ¡Gracias!
James Kingsbery el
Intenté esto en IE8 no funciona. No viene dentro de la función.
ARUN
14

Esto también debería funcionar:

$(document).ready(function(){
   $(".hiddenOnLoad").hide();
   $("#viewByOrg, #viewByProduct").bind(($.browser.msie ? "click" : "change"), function () {
                        $(".visibleOnLoad").show();
                        $(".hiddenOnLoad").hide();
                    });
});

Gracias Pier. Esto fue muy útil.


fuente
Esta es, al menos, una respuesta mucho mejor que la actual aceptada / mejor votada. 'Solo' rompe la accesibilidad del teclado en IE, en lugar de todos los buenos navegadores también.
Bobby Jack
... aunque, ¿no es solo una copia de la respuesta de Pier?
Bobby Jack
De acuerdo, es una versión ligeramente menos legible de Pier's pero con ambos selectores vinculados en una sola llamada.
Tristan Warner-Smith
Reemplace clickcon click keyup keypresspara agregar soporte de teclado.
aloisdg se muda a codidact.com el
6

En IE debes usar el evento click, en otros navegadores onchange. Tu función podría convertirse

$(document).ready(function(){
   $(".hiddenOnLoad").hide();
   var evt = $.browser.msie ? "click" : "change";
   $("#viewByOrg").bind(evt, function () {
                        $(".visibleOnLoad").show();
                        $(".hiddenOnLoad").hide();
                    });

   $("#viewByProduct").bind(evt, function () {
                        $(".visibleOnLoad").hide();
                        $(".hiddenOnLoad").show();
                    });     
});
Pier Luigi
fuente
Reemplace clickcon click keyup keypresspara agregar soporte de teclado.
aloisdg se muda a codidact.com el
6

agregue este complemento

jQuery.fn.radioChange = function(newFn){
    this.bind(jQuery.browser.msie? "click" : "change", newFn);
}

luego

$(function(){
    $("radioBtnSelector").radioChange(function(){
        //do stuff
    });
});
dovidweisz
fuente
4

Tuve el mismo problema con el texto de entrada.

Cambié:

$("#myinput").change(function() { "alert('I changed')" });

a

$("#myinput").attr("onChange", "alert('I changed')");

¡y todo está funcionando bien para mí!

fabrice
fuente
2

Esta es una manera simple de decirle a IE que active el evento de cambio cuando se hace clic en el elemento:

if($.browser.msie) {
    $("#viewByOrg").click(function() {
        $(this).change();
    });
}

Puede ampliar esto a algo más genérico para trabajar con más elementos de formulario:

if($.browser.msie) {
    $("input, select").click(function() {
        $(this).change();
    });
    $("input, textarea").keyup(function() {
        $(this).change();
    });
}
Pablo
fuente
1

Estoy bastante seguro de que este es un problema conocido con IE. Agregar un controlador para el onclickevento debería solucionar el problema:

$(document).ready(function(){

    $(".hiddenOnLoad").hide();

    $("#viewByOrg").change(function () {
        $(".visibleOnLoad").show();
        $(".hiddenOnLoad").hide();
    });

    $("#viewByOrg").click(function () {
        $(".visibleOnLoad").show();
        $(".hiddenOnLoad").hide();
    });

    $("#viewByProduct").change(function () {
        $(".visibleOnLoad").hide();
        $(".hiddenOnLoad").show();
    });     

    $("#viewByProduct").click(function () {
        $(".visibleOnLoad").hide();
        $(".hiddenOnLoad").show();
    });     
});
Chris Zwiryk
fuente
1

En IE, fuerce la radio y las casillas de verificación para activar un evento de "cambio":

if($.browser.msie && $.browser.version < 8)
  $('input[type=radio],[type=checkbox]').live('click', function(){
    $(this).trigger('change');
  });
Jeoff Wilks
fuente
1

a partir de jquery 1.6 esto ya no es un problema ... aunque no estoy seguro de cuándo se solucionó ... Gracias a Dios por ello

Baz1nga
fuente
1

el truco con el clic funciona ... pero si desea obtener el estado correcto de la radio o la casilla de verificación, puede usar esto:

(function($) {
    $('input[type=checkbox], input[type=radio]').live('click', function() {
       var $this = $(this);
       setTimeout(function() {
          $this.trigger('changeIE'); 
       }, 10) 
    });
})(jQuery);

$(selector).bind($.browser.msie && $.browser.version <= 8 ? 'changeIE' : 'change', function() {
  // do whatever you want
})
no te detengas
fuente
0

El uso de clic en lugar de cambio hace que el comportamiento sea diferente. Prefiero emular el comportamiento del evento de cambio usando un temporizador (setTimout).

algo como (advertencia - código del bloc de notas):

if ($.browser.msie) {
  var interval = 50;
  var changeHack = 'change-hac';
  var select = $("#viewByOrg");
  select.data(changeHack) = select.val();
  var checkVal=function() {
    var oldVal = select.data(changeHack);
    var newVal = select.val();
    if (oldVal !== newVal) {
      select.data(changeHack, newVal);
      select.trigger('change')
    }
    setTimeout(changeHack, interval);
  }
  setTimeout(changeHack, interval);
}

$("#viewByOrg").change(function() {
  // Do stuff here
});
Ken Egozi
fuente
whoah ... un poco pesado, no?
orip
0

prueba esto, me funciona

$("#viewByOrg")
        .attr('onChange', $.browser.msie ? "$(this).data('onChange').apply(this)" : "")
        .change( function(){if(!$.browser.msie)$(this).data('onChange').apply(this)} )
        .data('onChange',function(){alert('put your codes here')});
LluviaChen
fuente
0

Esto puede ayudar a alguien: en lugar de comenzar con la identificación del formulario, oriente la identificación seleccionada y envíe el formulario en el cambio, de esta manera:

<form id='filterIt' action='' method='post'>
  <select id='val' name='val'>
    <option value='1'>One</option>
    <option value='2'>Two</option>
    <option value='6'>Six</option>
  </select>
  <input type="submit" value="go" />
</form>

y el jQuery:

$('#val').change(function(){
  $('#filterIt').submit();
});

(Obviamente, el botón Enviar es opcional, en caso de que JavaScript esté deshabilitado)

Jongosi
fuente
0

Intenta lo siguiente:

.bind($.browser.msie ? 'click' : 'change', function(event) {
Bilal Jalil
fuente
0

Evite usar .focus () o .select () antes de la función .change () de jquery para IE, entonces funciona bien, lo estoy usando en mi sitio.

Gracias

musulmán
fuente
0
//global
var prev_value = ""; 

$(document).ready(function () {

 if (jQuery.browser.msie && $.browser.version < 8)
      $('input:not(:submit):not(:button):not(:hidden), select, textarea').bind("focus", function () { 
         prev_value = $(this).val();

       }).bind("blur", function () { 
         if($(this).val() != prev_value)
         has_changes = true;
       });
}
Kiev
fuente
0

Intente usar cada uno en lugar de cambiar / hacer clic , que funciona bien incluso la primera vez en IE, así como en otros navegadores

No funciona por primera vez

$("#checkboxid").**change**(function () {

});

Trabajando bien incluso la primera vez

$("#checkboxid").**each**(function () {

});
Dayanand Rupanavar
fuente