Diferença entre find ('option [selected]') e find ('option'). filter ('[selecionado]')

9

cenário:

Eu tenho duas expressões jQuery:

/* A */ $('select').find('option[selected]');
/* B */ $('select').find('option').filter('[selected]');

qual significa (vamos supor que exista apenas um select no documento, para simplificar):

  • A : obtenha o select e, em seguida, localize todos os option descendentes que tenham um atributo denominado selected .
  • B : obtenha o select , localize todos os option descendentes e, em seguida, filtre por quem tiver um atributo denominado selected .

Comportamento esperado:

Um e B deve fornecer o mesmo resultado.

Comportamento real:

Depois que o usuário alterou a seleção na lista suspensa,

  • Um retorna o padrão selecionado option .
  • B retorna o novo selecionado option .

Pergunta:

Então, por que eles são diferentes? Meu entendimento sobre os seletores CSS está errado?

Demonstração ao vivo:

A demonstração ao vivo é aqui aqui .

Código-fonte:

HTML :

<select>
 <option value='p'>p</option> 
 <option value='q' selected>q</option>
 <option value='r'>r</option> 
 <option value='s'>s</option> 
</select>


<input type='button' value='click me!'/> <br/> 
 ResultA : <span id='ResultA'>
    here
</span> <br/> 
 ResultB : <span id='ResultB'>
    here
</span> <br/> 

Javascript :

function SetResult(ResultObj, ElementObj) {
    ResultObj.text("length=" + ElementObj.length + " " + "val()=" + ElementObj.val());
}

$(function() {
    $('input[type=button]').click(function() {
        var SelectObj = $('select');
        SetResult($("#ResultA"), SelectObj.find('option[selected]'));
        SetResult($("#ResultB"), SelectObj.find('option').filter('[selected]'));
    });
});

Resultado do teste:

+---------------------------+--------------+---------------------+---------+-----+
|          Browser          | Environment  |       jQuery        |    A    |  B  |
+---------------------------+--------------+---------------------+---------+-----+
| Chrome 22.0.1229.94m      | Win7         | 1.8.2, 1.7.2, 1.6.4 | default | new |
| Chrome 23.0.1271.64 m     | Win7         | 1.8.2, 1.7.2, 1.6.4 | default | new |
| Firefox 15.0.1            | Win7         | 1.8.2, 1.7.2, 1.6.4 | default | new |
| Firefox 16.0.2            | Win7         | 1.8.2, 1.7.2, 1.6.4 | default | new |
| IE 6                      | WinXP        | 1.8.2, 1.7.2, 1.6.4 | *new*   | new |
| IE 9                      | Win7         | 1.8.2, 1.7.2, 1.6.4 | default | new |
| Opera 12.02               | Win7         | 1.8.2, 1.7.2, 1.6.4 | default | new |
| Opera 12.10               | Win7         | 1.8.2, 1.7.2, 1.6.4 | default | new |
| Safari 5.1.7 (7534.57.2)  | Win7         | 1.8.2, 1.7.2, 1.6.4 | default | new |
+---------------------------+--------------+---------------------+---------+-----+
| Chrome 22.0.1229.94       | MacOS 10.7.5 | 1.8.2, 1.7.2, 1.6.4 | default | new |
| Chrome 23.0.1271.64       | MacOS 10.7.5 | 1.8.2, 1.7.2, 1.6.4 | default | new |
| Firefox 13.0              | MacOS 10.7.5 | 1.8.2, 1.7.2, 1.6.4 | default | new |
| Firefox 14.0.1            | MacOS 10.7.5 | 1.8.2, 1.7.2, 1.6.4 | default | new |
| Firefox 16.0.2            | MacOS 10.7.5 | 1.8.2, 1.7.2, 1.6.4 | default | new |
| Opera 12.01               | MacOS 10.7.5 | 1.8.2, 1.7.2, 1.6.4 | default | new |
| Opera 12.10               | MacOS 10.7.5 | 1.8.2, 1.7.2, 1.6.4 | default | new |
| Safari 6.0.1 (7536.26.14) | MacOS 10.7.5 | 1.8.2, 1.7.2, 1.6.4 | default | new |
+---------------------------+--------------+---------------------+---------+-----+
| Chrome 21.0.1180.82       | iOS 4.3.5    | 1.8.2, 1.7.2, 1.6.4 | default | new |
| Opera 7.0.5               | iOS 4.3.5    | 1.8.2               | default | new |
| Safari                    | iOS 4.3.5    | 1.8.2, 1.7.2, 1.6.4 | default | new |
+---------------------------+--------------+---------------------+---------+-----+
  • padrão significa que retorna o padrão selecionado option .
  • novo significa que ele retorna o novo selecionado option .

Como você pode ver, todos os navegadores, exceto o IE6, apresentam resultados diferentes.

    
por Pang 30.10.2012 в 12:10
fonte

5 respostas

1

O que as expressões devem retornar?

[selected] corresponde a todos os elementos que possuem um atributo selected , com qualquer valor (referências: W3C , jQuery ).

Por que os resultados são inconsistentes?

Eu enviei um relatório de bug para o jQuery aqui . Está marcada como uma cópia de outro relatório de erros que está agora corrigido .

Alguma solução?

Para obter a seleção atual :

Use o seletor :selected (demonstração ao vivo aqui ):

$('select').find('option').filter(':selected'); /* Supposedly faster */
or
$('select').find('option:selected');            /* Supposedly slower */

Observe que a segunda expressão é supostamente mais lenta , de acordo com o doc .

  

Como :selected é uma extensão jQuery e não faz parte da especificação CSS, as consultas que usam :selected não podem aproveitar o aumento de desempenho fornecido pelo método DOM querySelectorAll() nativo.

Para obter a seleção padrão :

Para jQuery 1.9 + , use qualquer uma das expressões como na pergunta, por exemplo

/* A */ $('select').find('option[selected]');
/* B */ $('select').find('option').filter('[selected]');

Para jQuery 1.6 + , use a propriedade defaultSelected (demonstração ao vivo aqui , referências: w3schools , Mozilla , MSDN , MSDN ):

$('select').find('option').filter(function() {
    return $(this).prop('defaultSelected');
});
    
por Pang 07.11.2012 / 03:39
fonte
3

O mecanismo Sizzle verifica a propriedade selected de um elemento (que contém o valor atual ) em vez do atributo que contém o valor original (padrão).

Veja o link

O que eu ainda não descobri é por que seu segundo seletor aparentemente invoca Sizzle, mas o primeiro não parece.

Em qualquer caso, a propriedade é o que você deve verificar em vez do atributo, portanto, você deve usar o pseudo-seletor :selected e não [selected]

    
por Alnitak 30.10.2012 / 12:37
fonte
1

quando você escreve option[selected] , ele pesquisa o atributo selected / property em vez disso, você deve usar option:selected se você tiver a propriedade readonly e o código option[readonly] , ela retornará s

$ ('[atributo]') seleciona elementos que possuem o atributo especificado, com qualquer valor.
Para mais informações: Possui o Seletor de Atributos [name]

Rabo

<select>
 <option value='p'>p</option> 
 <option value='q' selected>q</option>
 <option value='r'>r</option> 
 <option value='s' readonly>s</option> 
</select>  
    
por Pragnesh Chauhan 30.10.2012 / 12:20
fonte
0

Isso depende de como o DOM é construído pelo navegador. usando option[selected] jQuery procura por um elemento de opção com o atributo selecionado que, em alguns casos, não é aplicado

Você deve usar

SelectObj.children(':selected')
    
por Matei Mihai 30.10.2012 / 12:19
fonte
0

Sua implementação está errada, não é

find('option[selected]')

Deveria ser,

SelectObj.find('option:selected')

Aqui está o violino editado:

link

e referência:

link

    
por Never Back Down 30.10.2012 / 12:22
fonte