Por que os botões de opção não podem ser "somente leitura"?

213

Gostaria de mostrar um botão de opção, ter seu valor enviado, mas, dependendo das circunstâncias, ele não é editável. Desativado não funciona, porque não envia o valor (ou não?) E esmaece o botão de opção. Somente leitura é realmente o que estou procurando, mas por algum motivo misterioso, não funciona.

Existe algum truque estranho que preciso fazer para que o read-only funcione conforme o esperado? Devo apenas fazê-lo em JavaScript?

Aliás, alguém sabe por que o somente leitura não funciona nos botões de opção, enquanto funciona em outras tags de entrada? Essa é uma dessas omissões incompreensíveis nas especificações HTML?

mcv
fonte
5
"Essa é uma dessas omissões incompreensíveis nas especificações HTML?" Pense nisso do ponto de vista do usuário. Por que exibir um botão no qual eles não podem clicar?
Paul D. Waite
67
Por que exibir um botão no qual eles não podem clicar? Porque quero que eles saibam que o botão está lá, mas não quero que eles possam clicar nele agora. Mas talvez mais tarde. É uma forma dinâmica, afinal. Por que um botão de opção seria diferente de qualquer outro campo de entrada?
Mcv 23/12/09
7
Aqui está a especificação: w3.org/TR/html401/interact/forms.html#h-17.12.2 "Os seguintes elementos suportam o atributo readonly: INPUT e TEXTAREA." O que está obviamente errado. Porém, aqui atrás , vemos um resumo mais preciso: w3.org/TR/WD-forms-970402#readonly "READONLY se aplica a elementos INPUT do tipo TEXT ou PASSWORD e ao elemento TEXTAREA". Parece que isso ocorreu entre as lacunas de recs e especificações.
GraphicDivine
Ainda mais curioso. De acordo com este documento antigo "Nas caixas de seleção, por exemplo, você pode ativá-las ou desativá-las (configurando o estado CHECKED), mas não altera o valor do campo". ( htmlcodetutorial.com/forms/_INPUT_DISABLED.html ) Isso é verdade? A configuração READONLY em uma caixa de seleção / rádio bloqueia o valor, mesmo que o usuário possa aparentemente alterá-lo?
GraphicDivine
verifique meu post [aqui] [1] dá uma solução simples limpo para a questão [1]: stackoverflow.com/a/15513256/1861389
driven4ward

Respostas:

149

Fingi apenas um botão de opção, desativando apenas os botões de opção desmarcados. Isso evita que o usuário selecione um valor diferente, e o valor marcado sempre será postado no envio.

Usando o jQuery para criar somente leitura:

$(':radio:not(:checked)').attr('disabled', true);

Essa abordagem também funcionou para tornar uma lista de seleção somente leitura, exceto que você precisará desativar cada opção não selecionada.

Megan
fonte
2
Graças @Megan, esta é uma grande solução
Michael La Voie
9
Uma variação disso para permitir que você use a readonlypropriedade, como o OP esperava que funcionasse:$(':radio[readonly]:not(:checked)').attr('disabled', true);
wodow
1
Entre as soluções abaixo, essa solução fornece o código mais limpo e funciona bem com o validador Jquery, já que não preciso ativar / desativar os campos, ou lidar com eventos de clique de desacoplamento e vinculá-los novamente ao enviar o formulário.
Kristianne Nerona
Funciona com precisão. Obrigado
Hassan Farooq
Inteligente! Usando .not (..), caso você já tenha um conjunto de campos de entrada selecionados: var myRadios = $ ('# specific-radios'); myRadios.not (': marcado'). prop ('desativado', verdadeiro); api.jquery.com/not
JoePC
206

Os botões de opção precisariam ser somente leitura se houver outras opções. Se você não tiver outras opções, um botão de opção marcado não poderá ser desmarcado. Se você tiver outras opções, poderá impedir que o usuário altere o valor simplesmente desativando as outras opções:

<input type="radio" name="foo" value="Y" checked>
<input type="radio" name="foo" value="N" disabled>

Fiddle: http://jsfiddle.net/qqVGu/

Sampson
fonte
3
O problema com sua primeira solução é que, se eu quiser ativar o botão de opção por javascript, de repente eu tenho dois campos com o mesmo nome, então preciso limpar um deles. Ou use o oculto de verdade e faça com que o botão de opção defina o valor do campo oculto. De qualquer maneira, é um pouco mais complicado do que eu gostaria que um botão de rádio tivesse. Sua segunda solução, embora não duvide que funcione, parece um truque realmente feio. Acho que a solução javascript é a única que atende aos meus critérios. Eu vou com isso.
Mcv 23/12/2009
7
Solução 1 por favor! É o único adequadamente acessível. E se você precisar criar um script, é apenas mais uma linha para definir a capacidade do campo oculto para o oposto da capacidade do rádio.
22990 bobince as
5
Acabei de notar que as soluções 2 e 3 mudaram de lugar na resposta de Jonathan, então agora os comentários não parecem fazer muito sentido.
mcv
1
Deseja notar que a solução Javascript não está funcionando, apenas desmarca o botão. Suponho que seja onclick="return false"para impedir mudanças.
21812
2
Quando defino o rádio "desativado", adiciono "style = cursor: default" para remover o "cursor desativado".
João Paulo
24

Este é o truque que você pode seguir.

<input type="radio" name="name" onclick="this.checked = false;" />
Sarfraz
fonte
4
Exatamente o que eu estava pensando, altho que seria melhor se você esclareceu que deve ser onClick="this.checked = <%=value%>"de alguma variedade :)
JustLoren
Ótimo saber disso. marcado pode ter valores verdadeiros ou falsos.
Sarfraz
Apenas um aviso de que isso não funcionará para aqueles que navegam com javascript não ativado por padrão.
tloach
3
Não é um problema para o meu caso. Já usamos toneladas de jQuery e Ajax.
Mcv 23/12/09
1
Digno de nota você pode apenas fazer onclick="return false;"para manter o valor do mesmo para o grupo
Zach
12

Eu tenho um formulário longo (mais de 250 campos) que posta em um banco de dados. É um pedido de emprego online. Quando um administrador examina um aplicativo que foi arquivado, o formulário é preenchido com dados do banco de dados. Os textos de entrada e as áreas de texto são substituídos pelo texto que eles enviaram, mas os rádios e as caixas de seleção são úteis para manter como elementos do formulário. Desativá-los os torna mais difíceis de ler. Definir a propriedade .checked como false onclick não funcionará porque eles podem ter sido verificados pelo usuário que preenche o aplicativo. De qualquer forma ...

onclick="return false;"

funciona como um encanto para 'desativar' rádios e caixas de seleção ipso facto.

humbolight
fonte
8

A melhor solução é definir o estado marcado ou não (do cliente ou servidor) e não permitir que o usuário o altere após as alas (ou seja, torne-o somente leitura) faça o seguinte:

<input type="radio" name="name" onclick="javascript: return false;" />
Vipresh
fonte
não! Nesse caso, o usuário pode editar o html no navegador, marcar a opção necessária como selecionada e postar o formulário.
error1009
2

Eu vim com uma maneira pesada de javascript para alcançar um estado somente leitura para caixas de seleção e botões de opção. É testado em relação às versões atuais do Firefox, Opera, Safari, Google Chrome, bem como às versões atuais e anteriores do IE (até o IE7).

Por que não simplesmente usar a propriedade desativada solicitada? Ao imprimir a página, os elementos de entrada desabilitados saem na cor cinza. O cliente para o qual isso foi implementado queria que todos os elementos saíssem da mesma cor.

Não tenho certeza se tenho permissão para postar o código fonte aqui, pois desenvolvi isso enquanto trabalhava para uma empresa, mas certamente posso compartilhar os conceitos.

Com eventos onmousedown, você pode ler o estado da seleção antes que a ação do clique o altere. Então, você armazena essas informações e restaura esses estados com um evento onclick.

<input id="r1" type="radio" name="group1" value="r1" onmousedown="storeSelectedRadiosForThisGroup(this.name);" onclick="setSelectedStateForEachElementOfThisGroup(this.name);" checked="checked">Option 1</input>
<input id="r2" type="radio" name="group1" value="r2" onmousedown="storeSelectedRadiosForThisGroup(this.name);" onclick="setSelectedStateForEachElementOfThisGroup(this.name);">Option 2</input>
<input id="r3" type="radio" name="group1" value="r3" onmousedown="storeSelectedRadiosForThisGroup(this.name);" onclick="setSelectedStateForEachElementOfThisGroup(this.name);">Option 3</input>

<input id="c1" type="checkbox" name="group2" value="c1" onmousedown="storeSelectedRadiosForThisGroup(this.name);" onclick="setSelectedStateForEachElementOfThisGroup(this.name);" checked="checked">Option 1</input>
<input id="c2" type="checkbox" name="group2" value="c2" onmousedown="storeSelectedRadiosForThisGroup(this.name);" onclick="setSelectedStateForEachElementOfThisGroup(this.name);">Option 2</input>
<input id="c3" type="checkbox" name="group2" value="c3" onmousedown="storeSelectedRadiosForThisGroup(this.name);" onclick="setSelectedStateForEachElementOfThisGroup(this.name);" checked="checked">Option 3</input>

A parte javascript disso funcionaria assim (novamente apenas os conceitos):

var selectionStore = new Object();  // keep the currently selected items' ids in a store

function storeSelectedRadiosForThisGroup(elementName) {
    // get all the elements for this group
    var radioOrSelectGroup = document.getElementsByName(elementName);

    // iterate over the group to find the selected values and store the selected ids in the selectionStore
    // ((radioOrSelectGroup[i].checked == true) tells you that)
    // remember checkbox groups can have multiple checked items, so you you might need an array for the ids
    ...
}

function setSelectedStateForEachElementOfThisGroup(elementName) {
    // iterate over the group and set the elements checked property to true/false, depending on whether their id is in the selectionStore
    ...

    // make sure you return false here
    return false;
}

Agora você pode ativar / desativar os botões de opção / caixas de seleção alterando as propriedades onclick e onmousedown dos elementos de entrada.

Tom
fonte
2

Maneira JavaScript - isso funcionou para mim.

<script>
$(document).ready(function() {
   $('#YourTableId').find('*').each(function () { $(this).attr("disabled", true); });
});
</script>

Razão:

  1. $('#YourTableId').find('*') -> isso retorna todas as tags.

  2. $('#YourTableId').find('*').each(function () { $(this).attr("disabled", true); }); itera sobre todos os objetos capturados e desativa as tags de entrada.

Análise (Depuração):

  1. form:radiobutton é considerado internamente como uma tag "entrada".

  2. Como na função acima (), se você tentar imprimir document.write(this.tagName);

  3. Onde quer que, nas tags, encontre botões de opção, ele retorna uma tag de entrada.

Portanto, a linha de código acima pode ser mais otimizada para tags de botão de opção, substituindo * por input: $('#YourTableId').find('input').each(function () { $(this).attr("disabled", true); });

user3702798
fonte
1

Uma opção bastante simples seria criar uma função javascript chamada no evento "onsubmit" do formulário para ativar o botão de opção de volta para que seu valor seja postado no restante do formulário.
Não parece ser uma omissão nas especificações HTML, mas uma opção de design (lógica, IMHO), um botão de opção não pode ser lido apenas como um botão, se você não quiser usá-lo, desative-o.

muda de inverno
fonte
1

Eu descobri que o uso onclick='this.checked = false;'funcionou até certo ponto. Um botão de opção que foi clicado não seria selecionado. No entanto, se houvesse um botão de rádio que foi seleccionado (por exemplo, um valor padrão), esse botão de rádio se tornaria desmarcada.

<!-- didn't completely work -->
<input type="radio" name="r1" id="r1" value="N" checked="checked" onclick='this.checked = false;'>N</input>
<input type="radio" name="r1" id="r1" value="Y" onclick='this.checked = false;'>Y</input>

Nesse cenário, deixar o valor padrão sozinho e desabilitar os outros botões de opção preserva o botão de opção já selecionado e evita a seleção.

<!-- preserves pre-selected value -->
<input type="radio" name="r1" id="r1" value="N" checked="checked">N</input>
<input type="radio" name="r1" id="r1" value="Y" disabled>Y</input>

Essa solução não é a maneira mais elegante de impedir que o valor padrão seja alterado, mas funcionará se o javascript estiver ativado ou não.

JW8
fonte
1

Para os botões de opção não selecionados, sinalize-os como desativados. Isso os impede de responder à entrada do usuário e limpar o botão de opção marcado. Por exemplo:

<input type="radio" name="var" checked="yes" value="Yes"></input>
<input type="radio" name="var" disabled="yes" value="No"></input>
dpolican
fonte
4
checked="yes"? Que especificação é essa? Use checked="checked"ou apenas o atributo checkedsem um valor. O mesmo para disabled.
Robin van Baalen
1

Tente o atributo disabled, mas acho que você não obterá o valor dos botões de opção. Ou defina imagens como:

<img src="itischecked.gif" alt="[x]" />radio button option

Cumprimentos.

Tim
fonte
1
oh, meu código html foi removido: img src = "itIsChecked.gif" alt = "[x]" OptionChecked
Tim
0

Estou usando um plug-in JS que estiliza elementos de entrada de caixa de seleção / rádio e usou o jQuery a seguir para estabelecer um 'estado somente leitura' onde o valor subjacente ainda é postado, mas o elemento de entrada parece inacessível ao usuário, e acredito que seja o motivo pretendido usaríamos um atributo de entrada somente leitura ...

if ($(node).prop('readonly')) {
    $(node).parent('div').addClass('disabled'); // just styling, appears greyed out
    $(node).on('click', function (e) {
        e.preventDefault();
    });
}
chopstik
fonte