2012-06-23 16 views
37

¿Hay una manera fácil de adjuntar un evento "anular selección" en un botón de opción? Parece que el evento de cambio solo se dispara cuando se selecciona el botón.¿Cómo detectar el botón de radio? ¿Deseleccionar evento?

HTML

<input type="radio" id="one" name="a" /> 
<input type="radio" id="two" name="a" /> 

JavaScript

$('#one').change(function() { 
    if(this.checked) { 
     // do something when selected 
    } else { // THIS WILL NEVER HAPPEN 
     // do something when deselected 
    } 
});​ 

jsFiddle

+0

¿Por qué el voto a favor? – tskuzzy

+0

usuario no puede anular la selección de una radio ... ¿qué quieres hacer? – charlietfl

+17

El usuario puede anular la selección de una radio pero seleccionando otro botón de opción. – tskuzzy

Respuesta

22

¿Por qué no sólo tiene que crear un evento personalizado como, digamos, deselect y dejar que se desencadenan en todos los miembros del grupo de radio que se conecta a excepción del propio elemento que se ha hecho clic? Es mucho más fácil utilizar la API de manejo de eventos que jQuery proporciona de esa manera.

HTML

<!-- First group of radio buttons --> 
<label for="btn_red">Red:</label><input id="btn_red" type="radio" name="radio_btn" /> 
<label for="btn_blue">Blue:</label><input id="btn_blue" type="radio" name="radio_btn" /> 
<label for="btn_yellow">Yellow:</label><input id="btn_yellow" type="radio" name="radio_btn" /> 
<label for="btn_pink">Pink:</label><input id="btn_pink" type="radio" name="radio_btn" /> 
<hr /> 
<!-- Second group of radio buttons --> 
<label for="btn_red_group2">Red 2:</label><input id="btn_red_group2" type="radio" name="radio_btn_group2" /> 
<label for="btn_blue_group2">Blue 2:</label><input id="btn_blue_group2" type="radio" name="radio_btn_group2" /> 
<label for="btn_yellow_group2">Yellow 2:</label><input id="btn_yellow_group2" type="radio" name="radio_btn_group2" /> 
<label for="btn_pink_group2">Pink 2:</label><input id="btn_pink_group2" type="radio" name="radio_btn_group2" /> 

jQuery

// Attaching click event handlers to all radio buttons... 
$('input[type="radio"]').bind('click', function(){ 
    // Processing only those that match the name attribute of the currently clicked button... 
    $('input[name="' + $(this).attr('name') + '"]').not($(this)).trigger('deselect'); // Every member of the current radio group except the clicked one... 
}); 

$('input[type="radio"]').bind('deselect', function(){ 
    console.log($(this)); 
}) 

eventos La desactivación activará sólo entre los miembros del mismo grupo de radio (elementos que tienen el mismo atributo name).

jsFiddle solution

EDIT: Con el fin de tener en cuenta todas las posibles colocaciones de la etiqueta etiqueta adjunta (que envuelven el elemento de radio o están unidos a través de un selector de id) es tal vez mejor utilizar onchange evento para desencadenar los controladores. Gracias a Faust para señalar eso.

$('input[type="radio"]').on('change', function(){ 
    // ... 
} 
+0

+1. Buena solución, excepto que no indica qué radio se seleccionó previamente. – nnnnnn

+2

Me estaba enfocando en el problema principal aquí que proporciona una solución para un evento de deselección personalizado, pero por supuesto OP puede modificarlo a su gusto. – brezanac

+0

Sería mejor vincularse para cambiar el evento en lugar de hacer clic. –

-1

los cómo esto para ti?

http://jsfiddle.net/WZND9/6/

$('input').change(function() { 
    if ($('#one').is(':checked')) { 
     alert('checked'); 
    } else { 
     alert('not checked'); 
    } 
}); 
0

creo que esto podría estar ocurriendo porque el evento focus desencadena antes del evento change lo que el siguiente de radio que debe seleccionar se centró antes de la radio comprobado anterior desencadena un evento de cambio. No me hagáis esto, sin embargo ...

Se podía hacerlo de esta manera:

var isChecked = function(id) { alert(id + ': ' + $('#' + id).is(':checked')) } 
$('input[name="a"]').change(function(){ isChecked('one') }) 

Demostración:http://jsfiddle.net/elclanrs/cD5ww/

14

Usted puede crear una costumbre "anular la selección de" acontecimiento relativamente sin dolor, pero como ya has descubierto, el evento de cambio estándar solo se activa en el botón de opción recién verificado, no en el botón previamente marcado que se acaba de marcar.

Si desea ser capaz de decir algo como:

$("#one").on("deselect", function() { 
    alert("Radio button one was just deselected"); 
}); 

A continuación, ejecute algo parecido a la siguiente función de su documento manejador de listas (o poner el código directamente en su documento manejador de listas):

function setupDeselectEvent() { 
    var selected = {}; 
    $('input[type="radio"]').on('click', function() { 
     if (this.name in selected && this != selected[this.name]) 
      $(selected[this.name]).trigger("deselect"); 
     selected[this.name] = this; 
    }).filter(':checked').each(function() { 
     selected[this.name] = this; 
    }); 
} 

demostración de trabajo:http://jsfiddle.net/s7f9s/2

Lo que esto hace es pone un clic controlador en todas las radios de la página (esto no le impide agregar sus propios manejadores de eventos de clic a las mismas radios) que verificará si hubo una radio previamente seleccionada en el mismo grupo (es decir, con el mismo nombre) y si así que active un evento "deseleccionar" en que radio. Luego guarda el que acaba de hacer clic como el actual. El evento "deseleccionar" no se activa si hace clic en la radio ya verificada o si no hubo una marcada previamente. El bit .filter().each() al final es tomar nota de qué radios son ya seleccionado. (Si necesita atender más de un formulario en la misma página teniendo grupos de radio independientes con el mismo nombre, actualice la función de arriba).

+1

+1 Nadie reconoció su esfuerzo y por eso lo haré ahora. – brezanac

+0

+1 ¡Gracias! ¡Esta es la solución perfecta para mí! Solo tuve que cambiar las llamadas a la función 'encendido' para 'enlazar' porque estaba usando una versión anterior de jQuery. –

+0

Sería mejor vincularse para cambiar el evento en lugar de hacer clic. –

0

Creo que necesita agregar la función de cambio en el nivel de entrada, en lugar que en cada botón de radio.

Prueba esto:

$("input[name='a']").change(function() { 
    $("input[name='a']").each(function(){ 
    if(this.checked) { 
     // do something when selected 
    } else { 
     // do something when deselected 
    } 
    }); 
});​ 
4

He encontrado que la forma más sencilla de hacer esto sin poner en un nuevo marco para crear un evento deselected, es hacer el cambio de cualquier botón de radio desencadenar un evento update en todos de los botones de opción en su grupo y luego definen el comportamiento que desea en el evento de actualización.

El inconveniente es que el código en la rama de deselección se ejecutará aunque el botón de opción no se haya seleccionado previamente. Si todo lo que hace es simple mostrar, ocultar o deshabilitar los elementos de la interfaz de usuario, eso no debería importar mucho.

Para utilizar su ejemplo:

buttons = $('input[name="a"]'); 
buttons.change(function() { 
    buttons.trigger('update:groupA'); 

}).bind('update:groupA', function(){ 
    if(this.checked) { 
     //Do your checked things 
    } else { 
     //Do your unchecked things. Gets called whenever any other button is selected, so don't toggle or do heavy computation in here. 
    } 
});​ 
0

Usted puede activar el evento 'cambio' a sí mismo. Es un poco difícil de evitar los botones de opción de disparo infinitamente evento 'cambio' el uno del otro, pero se puede hacer así:

$('input[type="radio"]').each(function() { 
    var name = $(this).attr('name'); 
    var that = this; 
    $('input[name="'+name+'"][type="radio"]').not(that) 
     .on('change', function(e, alreadyTriggered) { 
      if(!alreadyTriggered || alreadyTriggered.indexOf(this) == -1) { 
       if(!alreadyTriggered) { 
        alreadyTriggered = [that]; 
       } 
       alreadyTriggered.push(this); 
       $(that).trigger('change', [alreadyTriggered]); 
      } 
    }); 
}); 

Aquí está la demo del código anterior en el trabajo.

0

Encontré una solución para mi caso específico que podría ayudar. Esto funciona cuando el evento "deselect" se puede aplicar a todos los botones de opción que no están seleccionados.

yo quería:

  1. agregar una clase al elemento cuando se selecciona el botón de radio , y
  2. eliminar esa clase cuando el botón se "desactivada".

me pasó a encontrar a esta pregunta, porque tenía el mismo problema:

$('input:radio').on('change', function() { 
    if($(this).is(':checked')) { 
     $(this).addClass('my-class-for-selected-buttons') 
    } else { // THIS WILL NEVER HAPPEN 
     $(this).removeClass('my-class-for-selected-buttons') 
    } 
});​ 

Pero, en mi caso, la solución fue bastante más fácil, porque puedo tratar de eliminar la clase de todo los botones de radio bastante simplemente con jQuery, y luego añadir la clase a la seleccionada:

$('input:radio').on('change', function() { 
    $('input:radio').removeClass('my-class-for-selected-buttons') // Here! 

    if($(this).is(':checked')) { 
     $(this).addClass('my-class-for-selected-buttons') 
    } 
});​ 

con este simple cambio, que no necesitaba encontrar una manera de activar el evento "Deseleccionar".

Por lo tanto, si en su caso puede aplicar el evento a todos los botones de opción que no están seleccionados, y no solo al que acaba de ser "deseleccionado", puede usar esta medida.

Cuestiones relacionadas