Pergunta

Eu tenho o seguinte pedaço de jQuery:

$("#collapse-menu > li > a").click(function() {
    $(this).toggleClass("expanded").toggleClass("collapsed").find("+ ul").slideToggle("medium");
});

O que basicamente faz é expandir ou desmoronar um menu de "listas" aninhadas que contêm suspensos (exemplo simplificado):

<ul id="collapse-menu">
   <li><a class="expanded">Basic Details</a>
      <ul>
         <li>
            <select> .... </select>
         </li>
         <li>
            <select> .... </select>
         </li>

O código funciona absolutamente bem, exceto quando um grande valor é selecionado em qualquer uma das suspensas. Nesse ponto, quando clicado, o menu ainda se expandirá/colapsará corretamente, mas "flash" rapidamente enquanto faz isso, como se todo o elemento estivesse sendo redefinido de alguma forma. Os dados em si estão bem, mas é o piscar que é indesejado.

O estranho é que, se um pequeno valor for selecionado em um suspensão, não haverá piscar. Quando um grande valor é selecionado (digamos, acima de 30 em um suspensão de 18 a 99 anos), o piscar começa a acontecer.

Alguém pode me dizer por que isso está acontecendo? Ou se há algo certo no jQuery que está causando isso.

Obrigado.

ATUALIZAR:

Adicionando uma recompensa a isso. Tentei alguns plugins/soluções semelhantes na rede, mas todos parecem sofrer com esse problema "piscando" quando grandes valores de suspensão são selecionados por padrão.

Se ajudar, aqui está uma solução semelhante típica: http://www.i-marco.nl/weblog/jquery-acordion-menu/index_collapsed.html# ... mas sofre do mesmo problema quando os suspensos são adicionados dentro do acordeão.

Espero que alguém tenha uma solução limpa, em vez de precisar invadir isso de alguma forma.

Foi útil?

Solução

Da minha observação: a questão parece dependente do sistema operacional. As seleções são pintadas pelo sistema, pois são controles do sistema. Na minha máquina Linux, não tenho problemas com a animação piscando no http://jsbin.com/ixake exemplo. Espero que você tenha testado no Windows (r)

Parece que a seleção é "rolada" para o valor adequado toda vez que for repintado. E isso acontece muito enquanto anima.

A solução mais fácil seria substituir o sistema seleciona com as seleções baseadas em HTML para remover a dependência do sistema. Existem plugins jQuery discretos que farão isso por você.

Tentar isto ou escolher qualquer aqui Se o primeiro não fosse muito bom.

Depois disso, sua animação deve depender apenas do JS e do estilo.

Outras dicas

Eu acho que o problema é que toda vez que o elemento é redimensionado, os rolos suspensos para o elemento selecionado, o que causa o piscar.

A resposta seria salvar cada seleção no JavaScript (na mudança, digamos), então quando a animação começar a desmarcar o valor e depois restaurá -la quando a animação parar. Isso fornecerá o mesmo desempenho que você recebe quando tiver um pequeno valor selecionado, preservando a seleção do usuário.

Você também pode garantir que o formulário não possa ser enviado enquanto estiver em um estágio de transição; caso contrário, você receberá valores ruins voltando.

Pessoalmente, acho que o AutoComplete pode realmente ser o caminho a percorrer. No entanto, tive a idéia de que esconder a seleção há muito tempo, substituindo uma falsa curta, tornaria o slide mais suave. Parece funcionar melhor no navegador que testei (Firefox 3.0.18). O código provavelmente poderia ser limpo e há o bug que, às vezes, as seleções não correspondem aos tamanhos por padrão devido às barras de rolagem internas, mas que não devem ser muito difíceis de fingir.

$("#collapse-menu > li > a").click(function() {
    var was_expanded = $(this).hasClass('expanded');
    var uls = $(this).toggleClass("expanded").toggleClass("collapsed").find('+ ul');
    if (was_expanded) {
        $(this).parent().find('select').each(function() {
            var fake = $('<select class="fake"><option>' + $(this).val() + '</option></select>');
            $(this).parent().append(fake);
            $(this).hide();
        })
        uls.slideUp('medium', function() { });
    } else {
        $('.fake').remove();
        $('select').show();
        uls.slideDown('medium', function() { });
     }
});

O que você pode fazer é desativar as listas de seleção antes de animar o UL.

        $("#collapse-menu > li > a").click(function() {
            $(this)
                .toggleClass("expanded").toggleClass("collapsed")
                .find("+ ul").find("select").attr("disabled","disabled").end()
                .slideToggle("medium",function(){
                    $(this).find("select").each(function(){this.disabled=false;});
                });
        });

Experimente isso e relate de volta.

Você provavelmente desejará estilizar (CSS) as listas de seleção desativadas para parecer idênticas às não deficientes.


NOTAS

O acima tem um efeito colateral de não enviar os valores selecionados quando um formulário é enviado. Se isso for um problema para você, sugiro que você remova todas as opções da lista de seleção, exceto para a opção selecionada antes de animar e adicione -as de volta quando a animação estiver concluída. E se isso não funcionar para sua sugestão de Naugtur para usar listas de seleção no estilo HTML é provavelmente a melhor opção.

PS Não se preocupe em tentar usar o atributo readonly na lista de seleção ... ela não existe.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top