javascript - que - ¿Cómo detectar un evento de deselección del botón de radio?
obtener id $(this) jquery (8)
¿Hay una manera fácil de adjuntar un evento de "deselección" en un botón de radio? Parece que el evento de cambio solo se dispara cuando se selecciona el botón.
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
}
});
¿Cómo es esto para ti?
$(''input'').change(function() {
if ($(''#one'').is('':checked'')) {
alert(''checked'');
} else {
alert(''not checked'');
}
});
¿Por qué no crea simplemente un evento personalizado como, digamos, deselect
y deje que se active en todos los miembros del grupo de radio en el que se hizo clic, excepto el elemento en el que se hizo clic? Es más fácil hacer uso de la API de gestión 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));
})
Los eventos de deselección solo se activarán entre los miembros del mismo grupo de radio (elementos que tienen el mismo atributo de name
).
EDITAR: para tener en cuenta todas las ubicaciones posibles de la etiqueta de etiqueta adjunta (envolver el elemento de radio o estar conectado a través de un selector de identificación) quizás sea mejor usar el evento onchange
para activar los manejadores. Gracias a Faust por señalarlo.
$(''input[type="radio"]'').on(''change'', function(){
// ...
}
Creo que es necesario agregar la función de cambio en el nivel de entrada, en lugar de en cada botón de opción.
Prueba esto:
$("input[name=''a'']").change(function() {
$("input[name=''a'']").each(function(){
if(this.checked) {
// do something when selected
} else {
// do something when deselected
}
});
});
Creo que esto podría estar ocurriendo porque el evento de focus
se dispara antes del evento de change
, por lo que la próxima radio en la que haga clic se enfocará antes de que la radio marcada anterior active un evento de cambio. No me cites en esto aunque ...
Podrías hacerlo así:
var isChecked = function(id) { alert(id + '': '' + $(''#'' + id).is('':checked'')) }
$(''input[name="a"]'').change(function(){ isChecked(''one'') })
Demostración: http://jsfiddle.net/elclanrs/cD5ww/
Descubrí que la forma más sencilla de hacer esto sin poner un nuevo marco para crear un evento no deselected
, es hacer que el cambio de cualquier botón de radio active un evento de update
en todos los botones de radio de su grupo y luego defina 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á incluso si el botón de opción no se seleccionó previamente. Si todo lo que está haciendo es mostrar, esconder o deshabilitar elementos de la interfaz de usuario, no debería importar mucho.
Para usar tu 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.
}
});
Encontré una solución para mi caso específico que podría ayudar. Esto funciona cuando el evento "deseleccionar" se puede aplicar a todos los botones de opción que no están seleccionados.
Quería:
- agregar una clase al elemento cuando se seleccionó el botón de radio , y
- eliminar esa clase cuando el botón fue "deseleccionado" .
Encontré esta pregunta porque tuve 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 mucho más fácil, porque puedo intentar eliminar la clase de todos los botones de radio simplemente con jQuery, y luego agregar la clase al seleccionado:
$(''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, no tuve que encontrar una manera de activar el evento "deseleccionar".
Por lo tanto, si en su caso puede aplicar el evento a todos los botones de radio que no están seleccionados , y no solo al que ha sido "deseleccionado", ¡puede usar esta medida!
Puede crear un evento de "deselección" personalizado de forma relativamente sencilla, pero como ya descubrió, el evento de cambio estándar solo se activa con el botón de opción recién marcado, no con el que se marcó anteriormente y que no se ha marcado.
Si te gustaría poder decir algo como:
$("#one").on("deselect", function() {
alert("Radio button one was just deselected");
});
Luego ejecute algo como la siguiente función desde el controlador de documentos listos (o coloque el código directamente en el controlador de documentos listos):
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 poner un controlador de clic en todas las radios de la página (esto no impide que agregue sus propios controladores de eventos de clic a las mismas radios) que verificará si hubo una radio seleccionada previamente en el mismo grupo (es decir, con el mismo nombre) y si es así, active un evento de "deselección" en esa radio. Luego guarda la que acaba de hacer clic como la actual. El evento "deseleccionar" no se activa si hace clic en la radio ya marcada o si no hubo una marcada previamente. El .filter().each()
bit al final es para anotar qué radios ya están seleccionados. (Si necesita atender a más de un formulario en la misma página que tiene grupos de radio independientes con el mismo nombre, actualice la función anterior correspondiente).
Usted puede desencadenar el evento ''cambio'' usted mismo. Es un poco difícil evitar que los botones de radio desencadenen infinitamente eventos de ''cambio'' entre sí, 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.