Chcę, aby zaznaczony element zawierał jedną domyślną opcję, która po wybraniu wyświetla wyskakujące okienko. Stworzyłem więc HTMLOptionElement i dodałem zdarzenie do detektora zdarzeń onclick, ale zdarzenie nie jest wyzwalane po kliknięciu opcji.

Oto mój kod:

const selectDefaultOption = new Option(".. show popup ...");
selectDefaultOption.addEventListener("mouseup", () => {
    // ... show pop up
});
document.querySelector("#select").appendChild(selectDefaultOption);

Czy robię coś źle? A może nie da się osiągnąć tego, do czego się staram?

Wnioski i rozwiązanie

Po kilku próbach doszedłem do wniosku, że nie ma zgrabnego rozwiązania, aby po prostu wywołać zdarzenie dołączone do wybranej opcji.

Udało mi się jednak osiągnąć wykonanie akcji, gdy wybrana jest konkretna opcja (choć nie jest to tak eleganckie, jak początkowo zamierzałem).

Rozwiązanie:

const selectElement = document.querySelector("#select");

const placeholderOption = new Option("<< select option >>", "<< select option >>", true, true);
placeholderOption.style.display = "none"; // this option is never display in the selection and serves only as a placeholder
selectElement.add(placeholderOption, null);

const onclickOption = new Option("onclick option", "onclick option")
onclickOption.onclick = () => alert("onlick option clicked!");
selectElement.add(onclickOption, null);

let previousSelectedValue;
selectElement.onmouseenter = event => {
  previousSelectedValue = event.target.value;
  event.target.value = placeholderOption.value;
  event.target.onmouseleave = event => {
    event.target.value = previousSelectedValue;
  };
} 
selectElement.oninput = event => {    
  event.target.onmouseleave = undefined; // reset the onmouseleave so it doesn't change current value
  const selectedOption = event.target.selectedOptions[0];
  if (selectedOption.onclick){
    selectedOption.onclick(selectedOption.event); 
    event.target.value = previousSelectedValue; // you may assign placeholderOption.value
  }
};
<select id="select">
    <option>option#1</option>
    <option>option#2</option>
</select>
1
Olafvolafka 26 styczeń 2022, 21:22
Zaktualizowałem swój kod i teraz działa we wszystkich przeglądarkach. stackoverflow.com/a/70875801/14807111
 – 
Maik Lowrey
27 styczeń 2022, 16:23

3 odpowiedzi

Najlepsza odpowiedź

Najpierw dodaję eventListener do wybranego kontenera. Jako wyzwalacz skupiłem się. Następnie używam Twojego kodu, aby utworzyć nowy element opcji. Do tego elementu przypisuję nowy eventListener, który wyzwala alert().

Aktualizacja dla wszystkich przeglądarek

Przypisanie EventListener do tagów opcji w utworzonym elemencie zakończy się niepowodzeniem w większości przeglądarek. Dlatego dobrze jest powiązać EventListerner z Select Tag. Następnie możesz sprawdzić, które to jest pole za pomocą pola wartości.

const s = document.getElementById('select');
let isLoaded = false;

s.addEventListener('focus', () => {  
  if (! isLoaded) {
    const selectDefaultOption = new Option(".. show popup ...");    
    selectDefaultOption.setAttribute('value', "popup");
    s.appendChild(selectDefaultOption);
  }
  isLoaded = true;
});

function callPopUp(event) {
  let s = document.getElementById('select');
  if (s.value === 'popup') {
    alert('PopUp')
  }
}
select {
  width: 200px;
  background: gray;
  padding:10px;
}
<select id="select" onclick='callPopUp(event)'>
  <option value="123">123</option>  
  <option value="456">456</option>  
</select>

Uwaga

Wraz z @Olafvolafka dowiedzieliśmy się, że w większości przeglądarek (Chrome, Opera) nie jest możliwe pomyślne powiązanie zdarzenia z tagiem/elementem opcji. Żadne zdarzenie nie zostało wywołane. Tylko w Firefoksie zostało wyzwolone zdarzenie. Dlatego musimy pracować z obejściem. Stan 01/2022.

2
Maik Lowrey 28 styczeń 2022, 16:51
Twoje rozwiązanie działa (choć ma pewne wady), ale Twoja odpowiedź nie odpowiada na moje początkowe pytanie, a mianowicie: Czy możliwe jest wywołanie zdarzenia po kliknięciu opcji?
 – 
Olafvolafka
28 styczeń 2022, 15:34
Nie tylko w Firefoksie byłoby to możliwe. Zobacz moją pierwszą odpowiedź i rozmowę z czatu.
 – 
Maik Lowrey
28 styczeń 2022, 16:02
1
Ja wiem. Właśnie zwracałem uwagę, że brakuje tej informacji w Twojej odpowiedzi ;) Jeśli zaktualizujesz swoją odpowiedź tak, aby w pełni odpowiadała na moje pytanie, zaakceptuję ją.
 – 
Olafvolafka
28 styczeń 2022, 16:30
1
Zaktualizowałem swoją odpowiedź (dodaj notatkę). To był trudny orzech do zgryzienia! Merci i Wiwaty
 – 
Maik Lowrey
28 styczeń 2022, 16:52

Należy umieścić detektor na elemencie select i sprawdzić wartość (zamiast umieszczać detektor bezpośrednio na elemencie opcji)

document.querySelector('select').addEventListener('change', e => {
  if (e.target.value === '2') console.log('The special option was chosen');
})
<select>
  <option value='1'>1</option>
  <option value='2'>Special</option>
  <option value='3'>3</option>
</select>
0
Kinglish 26 styczeń 2022, 21:31
To nie jest dokładnie to, co staram się osiągnąć. Działa to tylko po zmianie wybranej opcji. Moim celem jest wykonanie jakiejś akcji po wybraniu domyślnej opcji, nawet jeśli już została wybrana.
 – 
Olafvolafka
26 styczeń 2022, 23:13

Twój kod działa. z mouseup

Zdarzenie mouseup jest uruchamiane na elemencie, gdy przycisk urządzenia wskazującego (takiego jak mysz lub gładzik) zostanie zwolniony, gdy wskaźnik znajduje się w nim.

https://developer.mozilla.org/en-US/docs/Web/API/Element/mouseup_event

const selectDefaultOption = new Option(".. show popup ...");

selectDefaultOption.addEventListener("mouseup", () => {
    alert()
});
document.querySelector("#select").appendChild(selectDefaultOption);
option {
  width: 200px;
  background: gray;
}
<div id="select">
  <option>123</option>
</select>
0
Maik Lowrey 26 styczeń 2022, 21:32