Posso abrir uma lista suspensa usando jQuery

85

Para esta lista suspensa em HTML:

<select id="countries">
<option value="1">Country</option>
</select>

Eu gostaria de abrir a lista (o mesmo que clicar com o botão esquerdo nela). Isso é possível usando JavaScript (ou mais especificamente jQuery)?

Jon Tackabury
fonte
4
Alguém pode explicar por que isso é tão impossível?
SpaceBeers de

Respostas:

18

Você pode simular facilmente um clique em um elemento , mas um clique em um <select>não abrirá a lista suspensa.

Usar várias seleções pode ser problemático. Talvez você deva considerar botões de opção dentro de um elemento de contêiner, que pode expandir e contrair conforme necessário.

ieure
fonte
70

Eu estava tentando encontrar a mesma coisa e fiquei desapontado. Acabei mudando o tamanho do atributo para a caixa de seleção para que ela pareça abrir

$('#countries').attr('size',6);

e então quando você terminar

$('#countries').attr('size',1);
CommentLuv
fonte
12
adicionar o sizeatributo ao menu suspenso, na verdade, converte o menu suspenso em caixa de listagem ... então ele se expande ..
Mayank Pathak
Ótima solução. Você apenas tem que lidar com o fato de que a caixa de listagem ocupa mais espaço na página (em vez de se expandir sobre o conteúdo como uma lista suspensa) e, assim, empurra o conteúdo para baixo.
zkent
Para aqueles que podem apenas imaginar o que parece, a aparência é uma caixa de seleção múltipla após usar esta abordagem (mas não multisselecionável) que eu pessoalmente acho mais estável do que abrir o menu suspenso.
Siwei
Tecnicamente, isso funciona, mas 1) agora você tem uma barra de rolagem feia na lateral e 2) o z-index é fixado no select original, então também não funciona como um pop-up pull-down.
BoB3K de
Obrigado por isso ... Passei 2 horas tentando vários popovers etc para alertar os usuários que eles têm que escolher algo. Nada estava funcionando bem ... este é um lembrete sutil, mas firme. E funciona (ao contrário de outras soluções fragmentadas).
11 de
15

Já me deparei com o mesmo problema e tenho uma solução. Uma função chamada ExpandSelect () que emula o clique do mouse no elemento "selecionar", o faz criando um outro <select>elemento que está absolutamente posicionado e tem várias opções visíveis ao mesmo tempo definindo o sizeatributo. Testado em todos os principais navegadores: Chrome, Opera, Firefox, Internet Explorer. Explicação de como funciona, junto com o código aqui:

Editar (o link foi quebrado) .

Eu criei um projeto no Google Code, vá para o código lá:

http://code.google.com/p/expandselect/

Capturas de tela

Há uma pequena diferença na GUI ao emular o clique, mas isso não importa, veja você mesmo:

Ao clicar com o mouse:

MouseClicking
(fonte: googlecode.com )

Ao emular clique:

EmulatingClicking
(fonte: googlecode.com )

Mais screenshots no site do projeto, link acima.

Czarek Tomczak
fonte
2
Você pode postar um jsfiddle para isso?
Jay Sullivan
9

Isso é aprimorado a partir das respostas logo acima e usa o comprimento / número de opções para se conformar com quantas opções realmente existem.

Espero que isso ajude alguém a obter os resultados de que precisam!

    function openDropdown(elementId) {
        function down() {
            var pos = $(this).offset(); // remember position
            var len = $(this).find("option").length;
                if(len > 20) {
                    len = 20;
                }

            $(this).css("position", "absolute");
            $(this).css("zIndex", 9999);
            $(this).offset(pos);   // reset position
            $(this).attr("size", len); // open dropdown
            $(this).unbind("focus", down);
            $(this).focus();
        }
        function up() {
            $(this).css("position", "static");
            $(this).attr("size", "1");  // close dropdown
            $(this).unbind("change", up);
            $(this).focus();
        }
        $("#" + elementId).focus(down).blur(up).focus();
    }
Chris K
fonte
9

Isso deve abranger:

 var event;
 event = document.createEvent('MouseEvents');
 event.initMouseEvent('mousedown', true, true, window);
 countries.dispatchEvent(event); //we use countries as it's referred to by ID - but this could be any JS element var

Isso pode ser vinculado, por exemplo, a um evento de pressionamento de tecla, então, quando o elemento tem o foco, o usuário pode digitar e ele se expandirá automaticamente ...

--Contexto--

  modal.find("select").not("[readonly]").on("keypress", function(e) {

     if (e.keyCode == 13) {
         e.preventDefault();
         return false;
     }
     var event;
     event = document.createEvent('MouseEvents');
     event.initMouseEvent('mousedown', true, true, window);
     this.dispatchEvent(event);
 });
Stuart.Sklinar
fonte
funcionou para mim! todas as outras respostas sugeriram que não como acionar um select, mas você encontrou um, há alguma desvantagem nessa abordagem?
kittyminky
Sim - interfere nos eventos de tabulação (eu acho!), Depende das suas necessidades - mas funcionou como esperado - mas não atendeu às nossas outras necessidades.
Stuart.Sklinar
Funcionou para mim. Se estiver chamando de um manipulador de eventos diferente, lembre-se de obter o elemento dom -$('#select_element').get(0).dispatchEvent(event);
BoB3K
isso não funciona para mim. rodando no Chrome 56.0.2924 no OSX
ekkis
1
isso não funciona para mim. Mas parecia promissor.
user3335999
5

Uma maneira simples e fácil.

function down(what) {
  pos = $(what).offset();  // remember position
  $(what).css("position","absolute");
  $(what).offset(pos);   // reset position
  $(what).attr("size","10"); // open dropdown
}

function up(what) {
$(what).css("position","static");
$(what).attr("size","1");  // close dropdown
}

Agora você pode chamar seu DropDown assim

<select onfocus="down(this)" onblur="up(this)">

Funciona perfeitamente para mim.

Talvez seja melhor, porque você não tem problemas com a posição dos outros elementos na página.

function down(was) {
a = $(was).clone().attr('id','down_man').attr('disabled',true).insertAfter(was);
$(was).css("position","absolute").attr("size","10");
}

function up(was) {
$('#down_man').remove();
$(was).css("position","static");
$(was).attr("size","1");
}

Altere o ID para um valor fixo mybe não é inteligente, mas espero que você veja o idee.

Sr. perfeito
fonte
4

Não é possível que o javascript "clique" em um elemento (você pode acionar o onclickevento anexado , mas não pode literalmente clicar nele)

Para visualizar todos os itens da lista, transforme a lista em uma multiplelista e aumente seu tamanho, da seguinte forma:

<select id="countries" multiple="multiple" size="10">
<option value="1">Country</option>
</select>
Andreas Grech
fonte
Adiciona uma barra de rolagem após 4 itens no IE6, 7 e 8b2 e Opera 9.62. Adiciona uma barra de rolagem após 10 itens no Safari para Windows e Google Chrome.
Grant Wagner
2

Não, você não pode.

Você pode alterar o tamanho para torná-lo maior ... semelhante à ideia de Dreas, mas é o tamanho que você precisa alterar.

<select id="countries" size="6">
  <option value="1">Country 1</option>
  <option value="2">Country 2</option>
  <option value="3">Country 3</option>
  <option value="4">Country 4</option>
  <option value="5">Country 5</option>
  <option value="6">Country 6</option>
</select>
Scunliffe
fonte
2

Tentei usar a resposta do mrperfect e tive alguns problemas. Com algumas pequenas mudanças, consegui fazê-lo funcionar para mim. Eu apenas mudei para que fosse feito apenas uma vez. Depois de sair do menu suspenso, ele voltaria ao método normal de menus suspensos.

function down() {
    var pos = $(this).offset(); // remember position
    $(this).css("position", "absolute");
    $(this).offset(pos);   // reset position
    $(this).attr("size", "15"); // open dropdown
    $(this).unbind("focus", down);
}
function up() {
    $(this).css("position", "static");
    $(this).attr("size", "1");  // close dropdown
    $(this).unbind("change", up);
}
function openDropdown(elementId) {
    $('#' + elementId).focus(down).blur(up).focus();
}
colinbashbash
fonte
2

Uma coisa que isso não responde é o que acontece quando você clica em uma das opções na lista de seleção após ter feito seu size = n e feito seu posicionamento absoluto.

Como o evento de desfoque torna seu tamanho = 1 e o altera de volta para sua aparência, você também deve ter algo assim

$("option").click(function(){
    $(this).parent().blur();
});

Além disso, se você estiver tendo problemas com a lista de seleção de posição absoluta exibida atrás de outros elementos, basta colocar um

z-index: 100;

ou algo parecido no estilo do select.

vipergtsrz
fonte
2

Super simples:

var state = false;
$("a").click(function () {
    state = !state;
    $("select").prop("size", state ? $("option").length : 1);
});
Yckart
fonte
1
isso não é o mesmo que abri-lo. quando uma caixa de listagem está na parte inferior da página, se eu abrir, ela abre para cima. se eu mudar o tamanho, ele "abre" para baixo, abaixo de onde posso clicar. nada bom
ekkis
@ekkis O comportamento explicado pode variar em diferentes dispositivos e navegadores. Testei minha solução proposta com Firefox, Google Chrome e Opera no desktop e Safari no celular, onde funciona conforme o esperado. O salto de rolagem pode ser facilmente corrigido salvando / restaurando o deslocamento de rolagem ao abrir / fechar ou talvez usando scrollIntoViewno <select>.
yckart
1

Como já foi dito, você não pode abrir programaticamente um <select>usando JavaScript.

No entanto, você pode escrever seu próprio <select>gerenciando toda a aparência e sensação você mesmo. Algo parecido com o que você vê para os termos de pesquisa de preenchimento automático no Google ou Yahoo! ou a caixa Pesquisar localização na The Weather Network .

Encontrei um para jQuery aqui . Não tenho ideia se atenderia às suas necessidades, mas mesmo que não atenda totalmente às suas necessidades, deve ser possível modificá-lo para que seja aberto como resultado de alguma outra ação ou evento. Este realmente parece mais promissor.

Grant Wagner
fonte
0

acabei de adicionar

select = $('#' + id);
length = $('#' + id + ' > option').length;
if (length > 20)
    length = 20;
select.attr('size', length);
select.css('position', 'absolute');
select.focus();

e adicionar ao select

onchange="$(this).removeAttr('size');"
onblur="$(this).removeAttr('size');"

para fazer a mesma aparência do clássico (sobrepor o resto do html)

Emmanuel
fonte
-1

Talvez tarde, mas foi assim que resolvi: http://jsfiddle.net/KqsK2/18/

$(document).ready(function() {
  fixSelect(document.getElementsByTagName("select"));
                      });                       

   function fixSelect(selectList)
            {
            for (var i = 0; i != selectList.length; i++)
              {

                 setActions(selectList[i]);
              }
            }


   function setActions(select)
            {
               $(select).click(function() {
                   if (select.getElementsByTagName("option").length == 1)
                        {
                          active(select);
                        }
                      });
                $(select).focus(function() {
                       active(select);
                       });
                $(select).blur(function() {
                       inaktiv(select);
                       });
                $(select).keypress(function(e) {
                      if (e.which == 13) {

                      inaktiv(select);
                          }
                       });
                  var optionList = select.getElementsByTagName("option");

                  for (var i = 0; i != optionList.length; i++)
                           {
                                setActionOnOption(optionList[i], select);
                           }
      }

  function setActionOnOption(option, select)
      {
                    $(option).click(function() {
                                inaktiv(select);
                        });
      }

  function active(select)
      {
          var temp = $('<select/>');
              $('<option />', {value: 1,text:$(select).find(':selected').text()}).appendTo(temp);
               $(temp).insertBefore($(select));

              $(select).attr('size', select.getElementsByTagName('option').length);
              $(select).css('position', 'absolute');
              $(select).css('margin-top', '-6px');
              $(select).css({boxShadow: '2px 3px 4px #888888'});



                        }

        function inaktiv(select)
                   {
                 if($(select).parent().children('select').length!=1)
                     {
                                             select.parentNode.removeChild($(select).parent().children('select').get(0));
                                }
                $(select).attr('size', 1);
                $(select).css('position', 'static');
                $(select).css({boxShadow: ''});
                $(select).css('margin-top', '0px');

                  }
Johan Nordli
fonte