Estou usando o jQuery para criar botões de opção personalizados e estou com um problema. Ao clicar no rótulo associado ao rádio, os eventos de clique disparam duas vezes, se eu clicar apenas no próprio rádio, ele está funcionando bem (bem, na verdade não é o rádio que estou clicando, mas o div que envolve toda a entrada e o rótulo). Aqui está o código:
O HTML:
<div id="box">
<asp:RadioButtonList ID="RadioButtonList1" runat="server">
<asp:ListItem>RADIO1</asp:ListItem>
<asp:ListItem>RADIO2</asp:ListItem>
<asp:ListItem>RADIO3</asp:ListItem>
</asp:RadioButtonList>
</div>
jQuery:
<script type="text/javascript">
$(function () {
$('#box').find('input:radio').each(function (i) {
var input = $(this);
// get the associated label using the input's id
var label = $('label[for=' + input.attr('id') + ']');
// wrap the input + label in a div
$('<div class="custom-radio"></div>').insertBefore(input).append(label, input);
var wrapperDiv = input.parent();
// find all inputs in this set using the shared name attribute
var allInputs = $('input[name=' + input.attr('name') + ']');
// necessary for browsers that don't support the :hover pseudo class on labels
label.hover(
function () {
$(this).addClass('hover');
}, function () {
$(this).removeClass('hover checkedHover');
});
//bind custom event, trigger it, bind click,focus,blur events
wrapperDiv.bind('updateState', function () {
if ($(this)[0].children[1].checked) {
allInputs.each(function () {
var curDiv = $('div > label[for=' + $(this).attr('id') + ']').parent();
curDiv.removeClass('custom-radio-checked');
curDiv.addClass('custom-radio');
});
$(this).toggleClass('custom-radio custom-radio-checked');
}
else {
$(this).removeClass('custom-radio-checked checkedHover checkedFocus');
}
})
.trigger('updateState')
.click(function () { console.log('click'); })
.focus(function () {
label.addClass('focus');
}).blur(function () {
label.removeClass('focus checkedFocus');
});
});
});
</script>
Existe alguma solução para esse comportamento?
jQuery('input').prop('checked', true);
return false;
é equivalente a `evt.stopPropagation (); evt.preventDefault (); ( em jQuery )Tentei adicionar a solução acima adicionando:
mas não funcionou. No entanto, adicionando este:
resolveu o problema! :)
fonte
evt.stopPropagation(); evt.preventDefault();
didn; 'tVincule o evento de clique à entrada em vez do rótulo. Quando o rótulo é clicado - o evento ainda ocorrerá porque, como Dustin mencionou, um clique no rótulo aciona um clique na entrada. Isso permitirá que o rótulo mantenha sua funcionalidade normal.
Ao invés de
fonte
change
mesmo ao botão de opção, pois o texto de um rótulo é clicável - eles nem sempre clicam no próprio botão de opção.label > input
configuração Bootstrapesque , esta é A resposta, não uma resposta. Adicionarevt.stopPropagation()
ouevt.preventDefault()
ao seu código, embora eficaz, é um hack que deve ser evitado quando a solução adequada é muito mais limpa e eficiente.Se estiver tentando usar um contêiner externo como um elemento de clique, você também pode deixar os eventos borbulharem naturalmente e testar o elemento esperado em seu manipulador de cliques. Este cenário é útil se você estiver tentando definir o estilo de uma zona de clique exclusiva para um formulário.
fonte
if (e.target == e.currentTarget) {}
Para corrigir isso da maneira mais fácil, remova o atributo "for" do rótulo. Um clique no rótulo também acionará um clique no elemento associado. (que no seu caso está disparando o evento de clique duas vezes.)
Boa sorte
fonte
Eu costumo usar esta sintaxe
ao invés de
fonte
A melhor resposta está escondida nos comentários:
Este violino ilustra que todas as outras soluções -
stopPropagation
,stopImmediatePropagation
,preventDefault
,return false
- ou nada muda ou destruir a funcionalidade caixa / radio). Também ilustra que este é um problema de JavaScript básico, não um problema de jQuery.EDIT: Outra solução de trabalho que acabei de encontrar em outro segmento é vincular o
onclick
à entrada em vez do rótulo. Violino atualizado .fonte
Eu tentei adicionando solução.
mas não funcionou.
Adicionando
resolveu o problema! :)
fonte
O problema com e.preventDefault (); isso impede que o clique no rótulo verifique o botão de opção.
Uma solução melhor seria simplesmente adicionar uma verificação rápida "está marcada" como:
fonte
Meu problema é um pouco diferente, pois
evt.stopPropagation();evt.preventDefault();
não funciona pra mim, eu só adicionoreturn false;
no final, aí funciona.fonte
No meu caso, o problema era que eu tinha o evento click em uma função e a função era executada duas vezes .... cada execução da função cria um novo evento click. - facepalm -
após mover o evento click para fora da função, tudo funcionou conforme o esperado! :)
fonte
Tente colocar sua tag de entrada fora do elemento acionador, porque a tag de rótulo emula o clique, então você sempre terá mais de uma chamada.
fonte
Eu tive o mesmo problema porque aninhei meu rádio dentro do rótulo como este com o manipulador anexado ao radio_div. Remover o rótulo aninhado corrigiu o problema.
fonte
O rótulo aciona o rádio / caixa de seleção a ser marcada.
Evita principalmente que o rótulo acione esse comportamento.
fonte
O clique no rótulo com um atributo for = "some-id" aciona um novo clique, mas apenas se o destino existir e for uma entrada. I foi não capaz de resolvê-lo perfeitamente com e.preventDefault () ou coisas assim, então eu fiz assim:
Por exemplo, se você tem essa estrutura e deseja um evento clicando em .alguma classe
O que funcionou foi:
fonte