Czy mogę otworzyć listę rozwijaną za pomocą jQuery

85

Dla tej listy rozwijanej w HTML:

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

Chciałbym otworzyć listę (to samo, co kliknięcie lewym przyciskiem myszy). Czy jest to możliwe przy użyciu JavaScript (a dokładniej jQuery)?

Jon Tackabury
źródło

Odpowiedzi:

18

Możesz łatwo zasymulować kliknięcie elementu , ale kliknięcie <select>nie spowoduje otwarcia menu.

Używanie wielokrotnych wyborów może być problematyczne. Być może powinieneś rozważyć przyciski opcji wewnątrz elementu kontenera, które możesz rozszerzać i zmniejszać w razie potrzeby.

ieure
źródło
70

Próbowałem znaleźć to samo i zawiodłem się. Skończyło się na zmianie rozmiaru atrybutu dla pola wyboru, aby wyglądało na otwarte

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

a kiedy skończysz

$('#countries').attr('size',1);
CommentLuv
źródło
12
dodanie sizeatrybutu do listy rozwijanej faktycznie konwertuje listę rozwijaną na Listbox, a zatem rozszerza się ..
Mayank Pathak
Świetne rozwiązanie. Musisz tylko poradzić sobie z faktem, że pole listy zajmuje więcej miejsca na stronie (zamiast rozszerzać zawartość jak lista rozwijana), a tym samym przesuwa zawartość w dół.
zkent
Dla tych, którzy mogą sobie tylko wyobrazić, jak to wygląda, wygląd jest polem wielokrotnego wyboru po zastosowaniu tego podejścia (ale nie wielokrotnego wyboru), które osobiście uważam za bardziej stabilne niż otwieranie menu.
Siwei
To technicznie działa, ale 1) masz teraz brzydki pasek przewijania z boku i 2) indeks Z jest ustalony na oryginalnym zaznaczeniu, więc nie działa też jak rozwijane okienko.
BoB3K
Dziękuję za to ... Spędziłem 2 godziny próbując różnych popoverów itp., Aby ostrzec użytkowników, że muszą coś wybrać. Nic nie działało dobrze ... to subtelne, ale stanowcze przypomnienie. I działa (w przeciwieństwie do innych łuszczących się rozwiązań).
11teenth
15

Natknąłem się na ten sam problem i mam rozwiązanie. Funkcja o nazwie ExpandSelect (), która emuluje kliknięcie myszą na elemencie „select”, robi to poprzez utworzenie innego <select>elementu, który jest absolutnie pozycjonowany i ma wiele opcji widocznych jednocześnie poprzez ustawienie sizeatrybutu. Przetestowane we wszystkich głównych przeglądarkach: Chrome, Opera, Firefox, Internet Explorer. Wyjaśnienie, jak to działa, wraz z kodem tutaj:

Edytuj (link został uszkodzony) .

Stworzyłem projekt w Google Code, przejdź do kodu tam:

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

Zrzuty ekranu

Istnieje niewielka różnica w graficznym interfejsie użytkownika podczas emulacji kliknięcia, ale to nie ma znaczenia, przekonaj się sam:

Po kliknięciu myszą:

MouseClicking
(źródło: googlecode.com )

Podczas emulacji kliknięcia:

EmulationClicking
(źródło: googlecode.com )

Więcej zrzutów ekranu na stronie projektu, link powyżej.

Czarek Tomczak
źródło
2
Czy możesz opublikować w tym celu jsfiddle?
Jay Sullivan
9

Jest to oparte na odpowiedziach powyżej i wykorzystuje długość / liczbę opcji, aby dostosować się do liczby faktycznie dostępnych opcji.

Mam nadzieję, że pomoże to komuś uzyskać potrzebne wyniki!

    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
źródło
9

Powinno to obejmować:

 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

Może to być powiązane na przykład ze zdarzeniem naciśnięcia klawisza, więc gdy element ma fokus, użytkownik może wpisać, a rozwinie się on automatycznie ...

--Kontekst--

  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
źródło
pracował dla mnie! każda inna odpowiedź sugerowała, że ​​nie ma sposobu, aby uruchomić selekcję, a znalazłeś taką, czy są jakieś wady tego podejścia?
kittyminky
Tak - przeszkadza w zakładaniu zdarzeń (myślę!), To zależy od twoich potrzeb - ale zadziałało zgodnie z oczekiwaniami - ale nie pasowało do naszych innych potrzeb.
Stuart.Sklinar
Pracował dla mnie. Jeśli dzwonisz z innego programu obsługi zdarzeń, pamiętaj, aby wyjąć element dom -$('#select_element').get(0).dispatchEvent(event);
BoB3K
to nie działa dla mnie. działa w Chrome 56.0.2924 na OSX
ekkis
1
to nie działa dla mnie. Wyglądało to obiecująco.
user3335999
5

Prosty, łatwy sposób.

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
}

Teraz możesz zadzwonić do DropDown w ten sposób

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

U mnie działa idealnie.

Może lepiej, bo nie masz problemów z pozycją pozostałych elementów na stronie.

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");
}

Zmień identyfikator na stałą wartość mybe nie jest mądry, ale mam nadzieję, że widzisz ideę.

Pan Perfekcyjny
źródło
4

Nie jest możliwe, aby javascript "kliknął" na elemencie (możesz wywołać dołączone onclickzdarzenie, ale nie możesz go dosłownie kliknąć)

Aby wyświetlić wszystkie pozycje na liście, utwórz listę jako multiplelistę i zwiększ jej rozmiar, na przykład:

<select id="countries" multiple="multiple" size="10">
<option value="1">Country</option>
</select>
Andreas Grech
źródło
Dodaje pasek przewijania po 4 elementach w IE6, 7 i 8b2 oraz Opera 9.62. Dodaje pasek przewijania po 10 elementach w Safari dla Windows i Google Chrome.
Grant Wagner,
2

Nie, nie możesz.

Możesz zmienić rozmiar, aby był większy ... podobny do pomysłu Dreas, ale jest to rozmiar, który musisz zmienić.

<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
źródło
2

Próbowałem użyć odpowiedzi mrperfect i miałem kilka błędów. Po kilku drobnych zmianach udało mi się to uruchomić. Po prostu zmieniłem to tak, żeby robił to tylko raz. Po wyjściu z listy rozwijanej nastąpi powrót do zwykłej metody rozwijania menu.

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
źródło
2

Jedyną rzeczą, na którą to nie odpowiada, jest to, co się stanie, gdy klikniesz jedną z opcji na liście wyboru po dokonaniu rozmiaru = n i ustawieniu pozycji absolutnej.

Ponieważ zdarzenie rozmycia sprawia, że ​​rozmiar = 1 i zmienia go z powrotem na wygląd, powinieneś również mieć coś takiego

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

Ponadto, jeśli masz problemy z bezwzględnie pozycjonowaną listą wyboru wyświetlaną za innymi elementami, po prostu umieść

z-index: 100;

lub coś takiego w stylu zaznaczenia.

vipergtsrz
źródło
2

Super proste:

var state = false;
$("a").click(function () {
    state = !state;
    $("select").prop("size", state ? $("option").length : 1);
});
yckart
źródło
1
to nie to samo, co otwieranie. kiedy pole listy znajduje się na dole strony, jeśli je otworzę, otwiera się do góry. jeśli zmienię jego rozmiar, „otwiera się” w dół, poniżej miejsca, w którym mogę kliknąć. no good
ekkis
@ekkis Wyjaśnione zachowanie może się różnić na różnych urządzeniach i przeglądarkach. Przetestowałem proponowane przeze mnie rozwiązanie w przeglądarkach Firefox, Google Chrome i Opera na komputerze stacjonarnym oraz Safari na urządzeniach mobilnych, gdzie działa zgodnie z oczekiwaniami. Zwój-skok mógłby łatwo ustalony przez zapisywanie / przywracanie zwój-offset na otwieranie / zamykanie lub być może przy użyciu scrollIntoViewsprawie <select>.
yckart
1

Jak już wspomniano, nie można programowo otworzyć pliku <select>przy użyciu JavaScript.

Możesz jednak napisać własne <select>zarządzanie całym wyglądem i samopoczuciem. Coś jak to, co widzisz w autouzupełnianiu wyszukiwanych haseł w Google lub Yahoo! lub pole Wyszukaj lokalizację w The Weather Network .

Znalazłem jeden dla jQuery tutaj . Nie mam pojęcia, czy spełniłaby Twoje potrzeby, ale nawet jeśli nie do końca odpowiada Twoim potrzebom, powinna dać się zmodyfikować, aby otworzyła się w wyniku innej akcji lub zdarzenia. Ten faktycznie wygląda bardziej obiecująco.

Grant Wagner
źródło
0

właśnie dodałem

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

i dodaj do zaznaczenia

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

aby wyglądał tak samo jak klasyczny (nakładaj na resztę HTML)

Emmanuel
źródło
-1

Może późno, ale tak to rozwiązałem: 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
źródło