• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Pokaż/ukryj menu (lista pionowa)

Object Storage Arubacloud
0 głosów
902 wizyt
pytanie zadane 10 września 2016 w JavaScript przez Adecristo Początkujący (460 p.)

Witam. Mam problem z pokazaniem/ukryciem menu.

Otóż mam taką listę:

<ol>
	<li class="glowna"><a href="#" class="element-w-menu" onClick="pokazUkryj();">Statystyka</a></li>
		<ul id="lista">
			<li><a href="" class="element-w-menu-a">Średnia ważona</a></li>
		</ul>
	<li class="glowna" onClick="pokazUkryj();"><a href="#" class="element-w-menu">Kombinatoryka</a></li>
		<ul id="lista">
			<li><a href="" class="element-w-menu-a">Reguła mnożenia<</li>
		</ul>
</ol>

Oraz napisałem do tego taki skrypcik: 

<script type="text/javascript">
	
	function pokazUkryj()
	{
		var ul = document.getElementById('lista');
		
		if(ul.style.display=="none"){
			ul.style.display = "block";
		}
		else{
			ul.style.display = "none";
		}
	}
</script>

Na pierwszym elemencie w menu (statystyka) działa świetnie. Niestety na drugim elemencie (kombinatoryka) rozwija się podmenu ze statystyki.

Okej, w dokumencie może być tylko jedno ID - rozumiem czemu to nie działa i dlaczego tak się dzieje. Póki co tworzę proste strony i szlifuje bardziej html/css. Js dosłownie tylko liznąłem, dlatego nie potrafię znaleść rozwiązania. Nadanie każdemu elementowi z listy ID i skopiowanie skryptu tyle razy ile elementów - jest to jakieś wyjście, jednakże bardzo nieoptymalne. Czy istnieje jakaś funkcja w JS która pozwoli mi na ukrycie/pokazanie podmenu?

1 odpowiedź

+3 głosów
odpowiedź 10 września 2016 przez niezalogowany
wybrane 10 września 2016 przez Adecristo
 
Najlepsza

Na początku stwórz poprawną strukturę HTML:

<ol>
    <li class="glowna">
        <a href="#" class="element-w-menu" onClick="pokazUkryj();">Statystyka</a>
        <ul>
            <li><a href="" class="element-w-menu-a">Średnia ważona</a></li>
        </ul>
    </li>
    <li class="glowna" onClick="pokazUkryj();">
        <a href="#" class="element-w-menu">Kombinatoryka</a>
        <ul>
            <li><a href="" class="element-w-menu-a">Reguła mnożenia<</li>
        </ul>
    </li>
</ol>

Usuń JS z HTMLa - nie mieszaj języków, ponieważ robi się bałagan:

<ol>
    <li class="glowna">
        <a href="#" class="element-w-menu">Statystyka</a>
        <ul>
            <li><a href="" class="element-w-menu-a">Średnia ważona</a></li>
        </ul>
    </li>
    <li class="glowna">
        <a href="#" class="element-w-menu">Kombinatoryka</a>
        <ul>
            <li><a href="" class="element-w-menu-a">Reguła mnożenia<</li>
        </ul>
    </li>
</ol>

Zamiast definiować style w JS, do ukrywania elementów, posłuży nam specjalna klasa, którą stworzymy w CSS ( jak wyżej, nie mieszamy języków )

.hide {
  display: none !important;
}

Dalej zostaje tylko implementacja w JS:

var menuLinks = document.getElementsByClassName('element-w-menu');
// zaznacz odpowiednie linki

for( var i = 0; i < menuLinks.length; i++ ) {
  // wykonaj pętlę tyle razy, ile jest linków
  
  menuLinks[ i ].addEventListener('click', function() {
    // do każdego linku dodaj nasłuchiwanie zdadzenia - click
    
    // obiekt this, wskazuje na kliknięty element
    
    var submenu = this.nextElementSibling; 
    // pobierz element za nim -> ul
   
    submenu.classList.toggle('hide'); 
    // zmień w nim klasę hide - tzn jeśli jej nie ma,
    // to ją dodaj, jeśli jest, to ją usuń
  });
}

 

komentarz 10 września 2016 przez Adecristo Początkujący (460 p.)
Dziękuję za jasne wytłumaczenie :)
komentarz 10 września 2016 przez ScriptyChris Mędrzec (190,190 p.)

@niezalogowany, Twój kod JSa można zapisać nieco krócej czyściej / bardziej optymalnie :)

var parent = document.querySelector( 'ol' );
parent.addEventListener( 'click', function( ev ) {
  var t = ev.target;
  
  if ( t.classList.contains( 'element-w-menu' ) )
    t.nextElementSibling.classList.toggle( 'hide' );
} );

CSS można wyrzucić !important.

komentarz 10 września 2016 przez niezalogowany
edycja 10 września 2016
Tak, EventDelegation jest znacznie bardziej schludnym rozwiązaniem. Uznałem jednak, że nie ma co mieszać początkującemu w głowie. ( A może lepiej własnie przedstawić taką metodę? )

!important się przyda -> co jeśli nadpiszę sobie atrybut Display? na przykład selektorem o większej specyficzności? .hide to .hide -> nie jakieś debugowanie później nie wiadomo czego.
komentarz 10 września 2016 przez niezalogowany

Hahaha.. Krzycho92, co ja własnie napisałem : ))) przepraszam, roztargniony jestem. 

Już poprawiam

komentarz 10 września 2016 przez ScriptyChris Mędrzec (190,190 p.)

Bez pętli się nie obejdzie -> chyba, że zastosujemy Event Delegation

Tak też i zrobiłem.

jeszcze jest ES6 : )

Nom. Dla zmiennej menuLinks można nawet dać const, bo przecież jej nie modyfikujesz tylko odpalasz na niej pętlę :)

!important się przyda -> co jeśli nadpiszę sobie atrybut Display?

Dać selektor .obecna-klasa.hide i tam zapisać display: none

[edit]

Edytowałeś swój post zanim ja zdążyłem napisać ten ;)

komentarz 10 września 2016 przez niezalogowany

Dać selektor .obecna-klasa.hide i tam zapisać display: none?

Nie chcę, żeby poprawne ukrywanie elementów, było uzależnione od tego, czy jest odpowiednio do tego zadania stworzony CSS.

Druga sprawa.. pracując w grupie.. już z pewnością nikt się nie będzie nad tym zastanawiał.

komentarz 10 września 2016 przez Adecristo Początkujący (460 p.)
Okej, a jak zrobić, żeby po załadowaniu strony od razu menu było schowane? Jakaś kolejna pętla?
komentarz 10 września 2016 przez niezalogowany
dodaj klasy .hide do elementów, które chcesz, aby były schowane : )
komentarz 10 września 2016 przez ScriptyChris Mędrzec (190,190 p.)

Nie chcę, żeby poprawne ukrywanie elementów, było uzależnione od tego, czy jest odpowiednio do tego zadania stworzony CSS.

Ale w tym przypadku kod nie będzie elastyczny, bo !important już nie nadpiszesz.

Druga sprawa.. pracując w grupie.. już z pewnością nikt się nie będzie nad tym zastanawiał.

To akurat jest wredne. Na praktykach miałem przerabiać projekt, który był stylowany (i w ogóle tworzony) z 10 lat temu. Zawierał mnóstwo zagnieżdżonych <table> służących jako struktura strony, pomieszane polskie nazwy klas z angielskimi, mieszanie styli inline z CSSowymi, no i oczywiście gdzieniegdzie !important, który skutecznie utrudniał mi znalezienie przyczyny dlaczego moja zmiana nie odnosi skutku. Dopiero, po przejrzeniu dokładnie styli i elementów, które były nad tym moim docelowym - dostrzegałem !important. Ale ile razy napisałem bardzo specyficzną ścieżkę CSS, żeby coś wydłubać - bo nie miałem dostępu do HTMLa (jakieś Java Richface to produkowały - nie znam się na backendzie) - to już nie liczyłem. Nie mogłem po prostu nadać danemu elementowi klasy (nie miałem dostępu do "produkowanego" HTMLa) i go sobie ostylować. Musiałem CSSem specjalnie go szukać i nie zawsze się to udawało. Dopiero, gdy powiedziałem opiekunowi, że trudno mi będzie zmieniać style bez dodawania własnych klas do danego elementu HTML - dali mi dostęp do niego.

Dlatego, podczas pracy w grupie nad dużym projektem, na prawdę lepiej jeśli każdy dba o kod, bo podczas zmiany czegoś okazuje się, że zmiana nie przynosi efektu przez takie przykładowe !important.

komentarz 10 września 2016 przez niezalogowany

Oczywiście, nie używamy* !important w CSSsie, tutaj nawet nie mamy o czym dyskutować.

* -> potrzebujemy ukryć element JavaScriptem -> mamy dwie opcję

  1. el.style.display = 'none' -> de facto dodanie CSSa inline
  2. el.classList.toggle('klasa-z-important-none')

w przypadku drugim, nie musimy się męczyć z żadnymi ifami ( if el.style.display === 'none' ) el.style.display = 'nienon' else coś tam bla bla, nie mieszamy JSa z CSSem... chociaż tutaj to już argument trochę na siłę : )

Ogólnie własnie o to chodzi, żeby JS był ważniejszy od CSSa, Nie ma po co nadpisywać .hide

 

Podobne pytania

0 głosów
1 odpowiedź 258 wizyt
pytanie zadane 15 grudnia 2018 w JavaScript przez KRZYSZT0FSLENDER Nowicjusz (120 p.)
0 głosów
1 odpowiedź 648 wizyt
0 głosów
6 odpowiedzi 2,968 wizyt
pytanie zadane 16 marca 2016 w JavaScript przez n0s1gnal Użytkownik (700 p.)

92,555 zapytań

141,402 odpowiedzi

319,553 komentarzy

61,939 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...