Nie działa onclick za pierwszym razem

Nie działa onclick za pierwszym razem
K7
  • Rejestracja: dni
  • Ostatnio: dni
0

Dlaczego onclick nie działa za pierwszym razem

Kopiuj
<style>
.projectmenu {
	position: absolute;
	z-index: 4;
	background: rgb(248, 248, 248, 1);
	width: 100%;
	max-height: 500px;
	overflow: auto;
	left: 0px;
	top: 3em;
	display: none;
	border: 1px solid black;
}
</style>
Kopiuj
function show_hide_korespondencja(id)
{            
	//console.log("show_hide_korespondencja");
	var x = document.getElementById(id);
  	if (x.style.display === "none") 
  	{
  		$('.projectmenu').hide();
    	x.style.display = "block";
  	} else {
    	x.style.display = "none";
  	}		  
    return false;     
}
Kopiuj
<button class="btn ripple btn-primary" data-bs-toggle="dropdown" onclick="show_hide_korespondencja('projekty'); ">
Projekty <i class="icon ion-ios-arrow-down tx-11 mg-l-3"></i>
</button>
<div id="projekty">

I teraz problem
Jeżeli będę stylizował
div id="projekty" przez

Kopiuj
style="position: absolute; z-index: 4; background: rgb(248, 248, 248, 1);
width: 100%; max-height: 500px; overflow: auto; left: 0px; top: 3em; display: none; border: 1px solid black;"

on click działa za pierwszym razem i jest ok

Jeżeli będę stylizował
div id="projekty" przez przez
class="projectmenu"
On click działa dopiero za drugim razem i potem jest ok.

Dlaczego tak się dzieje i jak temu zapobiegać?
Wolałbym drugą opcję

Scripterix
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 3
3

Dzieje się tak, bo sprawdzasz inline style, a nie rzeczywisty (skomputowany) styl elementu.

Kiedy ustawiasz display:none w atrybucie style, x.style.display === "none" jest prawdą już za pierwszym kliknięciem.

Kiedy ustawiasz display:none przez klasę .projectmenu, to x.style.display jest pusty ("") — bo display:none nie jest ustawiony inline, tylko pochodzi z CSS. Pierwsze kliknięcie wpada w gałąź else i dopiero ustawia inline none; drugie kliknięcie dopiero działa, jak oczekujesz.

Szybka naprawa (zachowujesz CSS-ową klasę)

Użyj skomputowanego stylu albo klas:
Wersja A – getComputedStyle

Kopiuj
<script>
function show_hide_korespondencja(id) {
  const el = document.getElementById(id);
  const isHidden = window.getComputedStyle(el).display === 'none';

  // schowaj inne menu (jak w Twoim kodzie)
  document.querySelectorAll('.projectmenu').forEach(d => d.style.display = 'none');

  el.style.display = isHidden ? 'block' : 'none';
  return false;
}
</script>

Wersja B – toggle klasą (czystsza):

Kopiuj
.projectmenu { display: none; }
.projectmenu.is-open { display: block; }
Kopiuj
<script>
function show_hide_korespondencja(id) {
  // schowaj inne
  document.querySelectorAll('.projectmenu.is-open')
    .forEach(d => d.classList.remove('is-open'));

  // przełącz wskazane
  document.getElementById(id).classList.toggle('is-open');
  return false;
}
</script>

Dodatkowe uwagi (ważne)

Masz na przycisku data-bs-toggle="dropdown". To uruchamia mechanikę Bootstrapowego dropdownu, która też manipuluje widocznością i może się „gryźć” z Twoją funkcją. Jeśli nie używasz natywnego .dropdown-menu, rozważ usunięcie data-bs-toggle="dropdown" albo użyj jednej metody (albo Bootstrap, albo własny JS).

Nie mieszaj jQuery i czystego JS dla tego samego problemu, chyba że w pełni świadomie (u Ciebie $('.projectmenu').hide() + el.style.display = ...). Lepiej spójnie jedną techniką.

Jeśli koniecznie chcesz zostać przy x.style.display === "none", to ustaw początkowo inline style="display:none" na #projekty. Ale to obejście — lepiej użyć A lub B powyżej.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.