W jaki sposób możesz programowo nakazać HTML SELECT rozwijanie się (na przykład po najechaniu kursorem myszy)?


106

Jak programowo możesz nakazać selectrozwijaniu kodu HTML (na przykład po najechaniu myszą)?


6
Nie radziłbym wkręcać się w zachowanie domyślne <select>, ponieważ ludzie oczekują, że będzie się zachowywać w określony sposób, a Ty będziesz uniemożliwiać użytkownikom innych platform (takich jak urządzenia mobilne) korzystanie z Twojej witryny.
Brian Donovan

1
@BrianDonovan To nie tak, że nie możesz do tego dodać obsługi.
Morg.

@shasikanth: Twoje skrzypce nie działają ani w przeglądarce Firefox 37 nr w przeglądarce Chrome
rubo77

Ok, myślę, że wcześniej skrzypce działały. W każdym razie usunąłbym tutaj swój komentarz.
shasi kanth

@BrianDonovan W rzeczywistości telefon komórkowy jest dobrym przykładem zastosowania tego ... programowego generowania wyboru, a następnie automatycznego wyświetlania jego opcji.
Michael

Odpowiedzi:


16

Nie możesz tego zrobić za pomocą tagu wyboru HTML, ale możesz to zrobić za pomocą JavaScript i HTML. Istnieje wiele różnych formantów, które to robią - na przykład lista „sugestii” dołączona do wpisu SO „interesujący / ignorowany tag” lub wyszukiwanie adresów e-mail w Gmailu.

Istnieje wiele kontrolek JavaScript + HTML, które zapewniają tę możliwość - poszukaj opcji autouzupełniania dla pomysłów.

Zobacz ten link do kontroli autouzupełniania ... http://ajaxcontroltoolkit.codeplex.com/


6
to straszny wstyd - przeglądarki mobilne zapewniają listę przewijania dla konkretnego systemu operacyjnego i chcę, aby pojawiała się automatycznie.
Michael

120

Kiedyś było to faktycznie możliwe w przypadku HTML + Javascript, mimo że ludzie mówią, że tak nie jest, ale zostało to później wycofane i teraz nie działa.

Jednak działało to tylko w Chrome. Przeczytaj więcej, jeśli jesteś zainteresowany.


Zgodnie z projektem roboczym W3C dla HTML5, sekcja 3.2.5.1.7. Zawartość interaktywna :

Niektóre elementy w HTML mają zachowanie aktywacyjne, co oznacza, że ​​użytkownik może je aktywować. Powoduje to wyzwolenie sekwencji zdarzeń zależnych od mechanizmu [...] aktywacji, na przykład za pomocą klawiatury, poleceń głosowych lub kliknięć myszą .

Gdy użytkownik wyzwala element ze zdefiniowanym zachowaniem aktywacyjnym w sposób inny niż kliknięcie go, domyślną akcją zdarzenia interakcji musi być uruchomienie syntetycznych kroków aktywacji kliknięcia na elemencie.

<select>będąc treścią interaktywną wierzyłem, że możliwe jest programowe wyświetlanie jej <option>s. Po kilku godzinach zabawy odkryłem, że używanie document.createEvent()i .dispatchEvent()działa.

To powiedziawszy, czas na demo. Oto działające Fiddle.


HTML:

<select id="dropdown">
    <option value="Red">Red</option>
    <option value="Green">Green</option>
    <option value="Blue">Blue</option>
</select>
<br>
<button id="fire" type="button" onclick="runThis()">Show dropdown items</button>​

JavaScript:

// <select> element displays its options on mousedown, not click.
showDropdown = function (element) {
    var event;
    event = document.createEvent('MouseEvents');
    event.initMouseEvent('mousedown', true, true, window);
    element.dispatchEvent(event);
};

// This isn't magic.
window.runThis = function () { 
    var dropdown = document.getElementById('dropdown');
    showDropdown(dropdown);
};

Jeśli ktoś znajdzie sposób na zrobienie tego samego, ale nie w Chrome, możesz zmodyfikować to skrzypce . Wcześniejsze


2
Dziękuję Ci za to! Musiałem emulować zachowanie ALT + STRZAŁKA W DÓŁ IE właśnie w Chrome.
J Bryan Price,

3
Chciałbym móc dodać za to twoją nagrodę. Dziękuję bardzo.
Adam Tuttle,

7
Nie działa na: IE10, FF 24. Działa na: Chrome 30, Safari 6.0.5,Opera 16
hitautodestruct

2
@AdamTuttle To również nie działa na Androidzie 4.4.2
Mirko

42
Jest teraz przestarzała w Chrome 53+
Washington Guedes,

47

Odpowiedź Xaviera Ho obejmuje sposoby rozwiązania problemu w większości obecnie dostępnych przeglądarek. Jednak dobrą praktyką jest „nie wysyłanie / modyfikowanie” zdarzeń przez JavaScript . (Jak mousedownw tym przypadku)

Od wersji 53 i nowszych przeglądarka Google Chrome nie będzie wykonywać domyślnych czynności w przypadku niezaufanych zdarzeń . Takich jak zdarzenia utworzone lub zmodyfikowane przez skrypt lub wysłane za pomocą dispatchEventmetody. Ta zmiana dotyczy dostosowania do przeglądarek Firefox i IE, które, jak sądzę, już nie wykonują akcji.

Do celów testowych Fiddle podał, że odpowiedź Xaviera nie będzie działać w Chrome 53+. (Nie testuję tego FF i IE).

Linki w celach informacyjnych:

https://www.chromestatus.com/features/5718803933560832 https://www.chromestatus.com/features/6461137440735232

InitMouseEvent również jest przestarzałe


Czy można to zrobić za pomocą MouseEvents? developer.mozilla.org/en-US/docs/Web/API/MouseEvent
Shamal Perera

Nie sądzę. próbowałeś czegoś
Asim KT

28

To jest najbliższy, jaki mogłem uzyskać, zmienić rozmiar elementu onmouseover i przywrócić rozmiar onmouseout:

       <select onMouseOut="this.size=1;" onMouseOver="this.size=this.length;">
        <option>1</option>
        <option>2</option>
        <option>3</option>
        <option>4</option>
        <option>5</option>
      </select>


13
lub <SELECT onMouseOut = "this.size = 1;" onMouseOver = "this.size = this.length;"> ... </SELECT>
RealHowTo

1
Należy również dodać onchange = "this.size = 1", aby menu zwinięte po dokonaniu wyboru. Należy również skonfigurować reguły CSS elementu.
gm2008

Wydaje się, że działa. Szerokość zaznaczenia zmniejsza się, a następnie powoduje zdarzenie wyprowadzenia myszy, resetując zaznaczenie do jego oryginalnej szerokości. Powoduje to efekt napadu. Wydaje się, że ustawienie stałej szerokości rozwiązuje ten problem. Z więcej niż kilkoma pozycjami lista rozszerza się poza widok.
1,21 gigawata

16

Mam ten sam problem, a łatwiejszy sposób na jego rozwiązanie to HTML i CSS.

select{
  opacity: 0;
  position: absolute;
}
<select>
  <option>option 1</option>
  <option>option 2</option>
  <option>option 3</option>
</select>
<button>click</button>


2
Minęło dużo czasu, odkąd widziałem to podejście i jest to odniesienie, które miałem nadzieję znaleźć. Lepiej z dodatkowym CSS, aby dopasować rozmiar ukrytego wyboru do wyzwalacza (przycisk, img, div, itp.) ... 1) Zapewnia klikalny region wypełnienia wyzwalacza 2) Menu otwiera się bezpośrednio pod wyzwalaczem. Uwaga: może być również konieczne dodanie indeksu Z, aby zapewnić, że klikalny region jest najwyższym elementem w niektórych układach.
Mavelo,

jeśli jednak użytkownik przewinie stronę w dół, przycisk przesunie się odpowiednio, ale zaznaczenie pozostanie w tej samej pozycji; nie tak, jak oczekiwano. jakieś rozwiązanie na to?
David Portabella

Idealne rozwiązanie. Ale może lepiej zawiń przycisk i wybierz taki div jak ten <div style='position:relative'><select> <option>option 1</option> <option>option 2</option> <option>option 3</option> </select> <button>click</button></div>@DavidPortabella
Muhammet Can TONBUL

8

Myślę, że w Chrome nie jest to już możliwe.

Wygląda na to, że wersja 53 Chrome wyłącza tę funkcjonalność, jak stwierdził Asim K.

Zgodnie ze specyfikacją http://www.w3.org/TR/DOM-Level-3-Events/#trusted-events

Zaufane zdarzenia nie powinny uruchamiać domyślnej akcji (z wyjątkiem zdarzenia kliknięcia).

Jednak włączyli to w przeglądarce internetowej, ale nie testowałem tego.

Odkryliśmy, że niektóre wyświetlenia internetowe używają w nich funkcji szybkiego kliknięcia, a ze względu na ryzyko złamania zamierzamy zezwolić na przesuwanie myszy na wybranych elementach, nawet jeśli nie są zaufane.

W tej dyskusji pomysł, aby umożliwić programistom otwieranie listy rozwijanej programowo, zostaje porzucony.


7

Jeśli ktoś nadal tego szuka:

<select id="dropdown">
    <option value="Red">Red</option>
    <option value="Green">Green</option>
    <option value="Blue">Blue</option>
</select>
<br>
<button id="fire" type="button" >Show dropdown items</button>

JavaScript:

var is_visible=false; 

$(document).ready(function(){

    $('#fire').click(function (e) { 
    var element = document.getElementById('dropdown');


    if(is_visible){is_visible=false; return;}
    is_visible = true;

    var event;
    event = document.createEvent('MouseEvents');
    event.initMouseEvent('mousedown', true, true, window);
    element.dispatchEvent(event);

    /* can be added for i.e. compatiblity.
      optionsSelect.focus();
       var WshShell = new ActiveXObject("WScript.Shell");
       WshShell.SendKeys("%{DOWN}");
    */
    e.stopPropagation();
    return false;
});


$(document).click(function(){is_visible=false; });
});

Aktualizacja:

Jeden, dopóki nie ma idealnego rozwiązania tego problemu, ale możesz spróbować uniknąć tego scenariusza. Dlaczego chcesz to zrobić. Kilka miesięcy temu zastanawiałem się nad rozwiązaniem, które pozwoliłoby stworzyć wybraną wtyczkę dla urządzeń mobilnych

https://github.com/HemantNegi/jquery.sumoselect

Ostatecznie skończyło się na zamaskowaniu niestandardowego div (lub dowolnego innego elementu) przezroczystym elementem select, tak aby mógł bezpośrednio współdziałać z użytkownikiem.


1
Wtyczki takie jak github.com/HemantNegi/jquery.sumoselect to jedyne rozwiązanie dla różnych przeglądarek, które faktycznie wygląda lepiej niż domyślna kontrolka.
Justin

iniMouseEventwydaje się działać, ale dlaczego $(select).trigger('mousedown')nie działa?
coding_idiot

3

Oto najlepszy sposób, jaki znalazłem. UWAGA Działa tylko z IE w systemie Windows, a Twoja sieć prawdopodobnie musiałaby znajdować się w bezpiecznej strefie - ponieważ mamy dostęp do powłoki. Sztuczka polega na tym, że ALT-strzałka w dół jest klawiszem skrótu do otwierania listy rozwijanej wyboru.

<button id="optionsButton" style="position:absolute;top:10px;left:10px;height:22px;width:100px;z-index:10" onclick="doClick()">OPTIONS</button>
<select id="optionsSelect" style="position:absolute;top:10px;left:10px;height:20px;width:100px;z-index:9">
    <option>ABC</option>
    <option>DEF</option>
    <option>GHI</option>
    <option>JKL</option>
</select>
<script type="text/javascript">
   function doClick() {
       optionsSelect.focus();
       var WshShell = new ActiveXObject("WScript.Shell");
       WshShell.SendKeys("%{DOWN}");
   }
</script>

3
To nie będzie działać, chyba że robisz to .
Knu

1
@Knu Internet Explorer automatycznie dodaje identyfikatory elementów jako odniesienia do elementu w zakresie globalnym.
user2428118

@KlasMellbourn prawdopodobnie. Próbują teraz zwiększyć zgodność swoich przeglądarek. Użyj wspomnianego rozwiązania „rozmiaru”.
sproketboy

2

Przestań myśleć, że jedna rzecz jest niemożliwa, nic nie jest niemożliwe do zrobienia, kiedy chcesz.

Użyj tej rozszerzającej funkcji JS stworzonej przez faceta.

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

Uwzględnij ten kod JS i po prostu wywołaj przekazanie parametru jako wybranego identyfikatora, na przykład:

ExpandSelect(MySelect)

2
Żeby było jasne, że JS nie powoduje <SELECT>upadku a. Jak wyraźnie stwierdza się, że „przeglądarki nie pozwalają na rozwijanie <select> w czystym javascript, tę kontrolkę można rozwinąć tylko poprzez bezpośrednie kliknięcie myszą”. Więc jest to „niemożliwe”! Zamiast tego JS stwierdza: „Imitujemy rozszerzoną kontrolkę <select>, tworząc kolejną selekcję z wieloma opcjami wyświetlanymi jednocześnie ...” Co jest zupełnie inne i może, ale nie musi, być akceptowalne w Twoim przypadku użycia ...
JonBrave

1

Może się mylę, ale nie wierzę, że jest to możliwe przy domyślnym polu wyboru. Możesz zrobić coś z JS i CSS, co da pożądany rezultat, ale nie (o ile wiem) waniliowy SELECT.


0

Otwarcie opcji „HTML select” jest możliwe dzięki niektórym obejściom wspomnianym w tym pytaniu i podobnym. Jednak prostszym sposobem na zrobienie tego jest dodanie do projektu biblioteki wyboru, takiej jak „select2” lub „selected”. Na przykład, programowe otwarcie select2 byłoby tak proste, jak:

$('#target-select').select2('open');

-2

Nie jest to dokładnie to, o co prosiłeś, ale podoba mi się to rozwiązanie ze względu na jego prostotę. W większości przypadków, gdy chcę zainicjować listę rozwijaną, dzieje się tak, ponieważ sprawdzam, czy użytkownik faktycznie dokonał wyboru. Zmieniam rozmiar menu rozwijanego i ustawiam na nim ostrość, co ładnie podkreśla to, co pominęli:

$('#cboSomething')[0].size = 3;
$('#cboSomething')[0].focus();

Nie jestem pewien, dlaczego zostałeś przegłosowany, ponieważ nie jest to „najgorszy” sposób, aby to zrobić. Uniknąłbym tego po prostu dlatego, że zmienia układ otaczających elementów. Chociaż myślę, że rozwiązanie z @CMS jest łatwiejsze do zrozumienia dzięki zdarzeniom skupienia / rozmycia w sterowaniu.
Mavelo,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.