Klik w czystym CSS, Vanilla JS, jQuery, AngularJS i Vue.js, cz.1


Zdarzenie Click jest chyba najczęściej wykonywanym zdarzeniem na stronach internetowych. Klikamy w zdjęcia, odnośniki, ikony czy tekst. Możemy je obsłużyć na kilka różnych sposobów, pokażę Wam te najpopularniejsze. Czysty CSS, czysty JS i dwa frameworki JavaScript: jQuery i AngularJS. Posłużę się przykładem menu, które pojawia się dopiero po kliknięciu w ikonę hamburgera.


Czysty CSS

W czystym CSSie uda nam się obsłużyć kliknięcie, czyli pokazać treść dopiero gdy użytkownik kliknie na elemencie strony. Możemy to zrobić na 2 wygodne sposoby używając inputów: checkbox i radio. Dzięki inputowi radio możemy używając tylko HTML + CSS zrobić funkcjonalne Accordion (czyli rozsuwane panele), ale w tym przykładzie użyję checkbox.

Struktura HTML:

<input type="checkbox" id="open-Menu" name="open-menu">
<div class="container">
<label for="open-Menu">
<i class="fa fa-bars" aria-hidden="true"></i>
</label>
<ul class="menu">
...
</ul>
</div>

Początek jest chyba jasny:) Umieszczamy checkbox o ID=”open-menu” (pamiętajcie że ID są unikalne i na stronie nie mogą znaleźć się dwa ID o takiej samej nazwie).

Zaraz za checkboxem umieszczamy DIV, dlaczego? Dzięki temu używając selektora ‘+’ możemy dowolnie manipulować jego zawartością w zależności od stanu checkboxa ( checked/unchecked).

Label dodany zaraz na początku DIVa, jest przypisany do naszego checkboxa i ma za zadanie obsługiwać go graficznie(ładniej wyglądać niż standardowy ) i funkcjonalnie (kliknięcie w label powoduje zaznaczenie/odznaczenie checkboxa).

UL o klasie ‘menu’ to nasza treść, która będzie się pojawiała po kliknięciu w label.

CSS:

Ukrywamy elementy, które mają się pojawić dopiero po kliknięciu:

.container ul li {
@extend .basic;
@extend .flex;
transform: translateY(-100%);
@include transition(.3);
display: flex;
opacity: 0;
list-style: none;
}

Dzięki ‘transform: translateY(-100%);’ przesuwam elementy o 100% wysokości w góre, wystarczy aby je schować. Dodatkowo używając ‘opacity: 0;’ ukrywam ich widoczność i gdy będą się pojawiały, uzyskamy efekt FadeIn.

Jednak gdy użytkownik kliknie muszą one wjechać na stronę, robimy to odwracając opisane wyżej parametry, dodatkowo stawiając warunek, że dzieje się to tylko wtedy gdy checkbox jest zaznaczony (:checked):

input[type="checkbox"] {
display: none;
}
input[type="checkbox"]:checked + .container .menu li {
transform: translateY(100%);
opacity: 1;
}
input[type="checkbox"]:checked + .container label {
font-size: 20px;
}

W przypadku CSS musimy zwrócić uwagę na 2 rzeczy:

  1. Ukrycie inputa — wystarczy display:none. Jego zadanie przejmie utworzony wcześniej label.
  2. Stan checkboxa — dzieki użyciu input[type=”checkbox”]:checked + .container możemy definiować wygląd i zachowanie elementów znajdujących się w DIV o klasie ‘container’, w momencie kliku (zaznaczenia) checkboxa. Jeżeli chcemy definiować wygląd przed kliknięciem możemy użyć — input[type=”checkbox”] + .container. Musimy pamiętać, że selektor + oznacza kolejny element, tzn. w kodzie klasa container znajduje się bezpośrednio za inputem checkbox.

DEMO:

https://jsfiddle.net/piotr_feder/d9t321y7/

https://jsfiddle.net/piotr_feder/d9t321y7/


Vanilla JS

W czystym Java Scripcie obsłużyć kliknięcie jest trochę łatwiej, przynajmniej moim zdaniem.

Pierwsza różnica jest taka, że zmieniamy lekko strukturę HTMLa: usuwamy inputa i label.

<div class=”container”>
<span class=”open-menu”>
<i class=”fa fa-bars” aria-hidden=”true”></i>
</span>
<ul class=”menu”>

</ul>
</div>

Dodanie klasy show do CSS, dzięki której pojawią się pozycje w menu. W moim przypadku dodaje ją do UL z klasą menu, a w CSS mam zdefiniowane:

.container .show > li {
transform: translateY(100%);
opacity: 1;
}

Czyli: gdy gdzieś w elemencie o klasie ‘container’ pojawi się element o klasie ‘show’ i ten element będzie miał dziecko którym jest element li, to pokazujemy menu:)

Kolejną różnicą jest jak się pewnie domyślacie kawałek kodu JavaScript:)

const btn = document.querySelector(‘.open-menu’);
const menu = document.querySelector(‘.menu’);
btn.addEventListener(‘click’, function() {
if (menu.classList.contains(‘show’)) {
menu.classList.remove(‘show’);
} else {
menu.classList.add(‘show’);
}
})

Omówmy go krok po kroku:

const btn = document.querySelector(‘.open-menu’);
const menu = document.querySelector(‘.menu’);

Const służy do tworzenia zmiennych tylko do odczytu (nie zamierzamy zmieniać zawartości zmiennych) i używamy zamiast wysłużonego var. Zatem ‘const btn’ tworzy nam zmienną btn, w której przechowujemy button w który musimy kliknąć, aby otworzyć menu.

Pobieramy go poprzez ‘document.querySelector(‘.open-menu’)’, element ‘document’ pomaga nam pobrać dowolną wartość drzewa DOM, a metoda ‘querySelector’ zwróci pierwszy element wskazany w nawiasach, czyli w naszym przypadku DIVa o klasie .open-menu.

W taki sam sposób pobieramy element odnoszący się do menu i zapisujemy go w zmiennej menu.

Ponieważ chcemy, aby po kliku w button (czyli naszą zmienną btn) wydarzyła się jakaś akcja, musimy ją przypisać do buttona. Metoda addEventListener pozwala nam właśnie to zrobić:

btn.addEventListener('click', function() {
... wykonywany kod ...
}

Dzięki tej metodzie możemy do dowolnego elementu, przypisać jakąś akcje/zdarzenie, po wykonaniu której, zostanie uruchomiony pożądany kod:

if (menu.classList.contains('show')) {
menu.classList.remove('show');
} else {
menu.classList.add('show');
}

W omawianym przypadku jest to instrukcja if, która sprawdzi czy element ze zmiennej menu posiada już klasę show. Jeżeli tak to usunie (classList.remove) ją (klik zamykający menu), jeżeli show nie jest dodane do elementu menu to musimy je dodać (classList.add) (klik otwierający menu).

Dzięki metodzie classList możemy w łatwy sposób: 
- sprawdzić czy zawiera już naszą klasę: menu.classList.contains(‘show’) , 
- jeżeli nie zawiera możemy ją dodać: menu.classList.add(‘show’),
-
a jeżeli już ta klasa jest, możemy ją usunąć: menu.classList.remove(‘show’);

DEMO:

https://jsfiddle.net/piotr_feder/9Lysotot/


W tej części dowiedzieliście się jak obsłużyć zdarzenie klik w czystym CSS i czystym JavaScripcie. W części drugiej opiszę jak zrobić to samo w bibliotece jQuery i frameworkach: AngularJS i Vue.js.