BoP #11: Przycisk „wróć na górę”

Dzisiaj w większym stopniu skupimy się na JavaScript.

 

Co chcemy dzisiaj osiągnąć? Musimy zmienić położenie odnośnika „na górę”, który ze stopki powędruje w prawym dolny róg ekranu w formie koła z ikoną strzałki w górę. Następnie sprawimy aby pojawiał podczas przewijania strony a po kliknięciu w ten odnośnik przenosiło nas na sam początek strony.

 

CSS

Zaczniemy od zmiany położenia i wyglądu, dlatego możemy nawet usunąć odnośnik, który znajduje się w tej chwili

a następnie zaraz po zamknięciu tagu <footer> tworzymy nowy:

„&#8679;” to kod odpowiedzialny za wyświetlenie strzałki (widoczna na screenie lub pod podanym linkiem)

https://codepen.io/morawcik/pen/YQjxVa

 

Teraz potrzebujemy nadać odpowiednie style.

Zaczniemy od umiejscowienia w prawym dolnym rogu.

Ustawiamy „fixed” dlatego aby odnośnik pojawiał się zawsze 20px od prawej i 20px od dolnej krawędzi bez względu a ilość treści czy jak dużo strony zostanie przewiniętej – zawsze będzie w tym samym miejscu.

https://codepen.io/morawcik/pen/dRjzgK

 

Dodamy sobie teraz odpowiednie tło i sprawimy by całość miała kształt koła.

Najpierw dodajemy tło. następnie za pomocą border-radius i padding nadajemy kształt koła.

https://codepen.io/morawcik/pen/awjyMV

 

Na koniec dodamy trochę cienie oraz zmienimy kolor strzałki na biały i usuniemy podkreślenie. Cień zrobimy tak samo jak w przypadku tagów.

i jeszcze zmiany dotyczące strzałki

https://codepen.io/morawcik/pen/rwrGNz

 

Jako, że odnośnik ma się pojawiać dopiero przy przewijaniu strony to musimy go ukryć na początek. Potrzebujemy dodać „display: none;” do „#back-top”

 

Eventy

Jeśli coś będzie niezrozumiałe to nie bójcie się pytać a już niedługo ruszymy z kursem JS 😉

Musimy zacząć od wyłapania momentu kiedy strona jest przewijana. Do takich rzeczy (nie tylko do przewijania ale też np. do wychwycenia kliknięcia w jakiś element, naciśnięcia klawisza, zmiany jakiegoś elementu itd) służą eventy. Dzięki nim możemy wychwycić moment, w którym „coś się stało” z jakimś elementem na stronie pod wpływem interakcji użytkownika lub nawet kodu JavaScript. W naszym przypadku będzie to event „scroll” a naszym elementem będzie cała strona czyli „document”.

Wyłapanie eventu możemy zrobić za pomocą:

gdzie

  • element to wybrany element, dla którego wyłapujemy event
  • type to rodzaj eventu (np. scroll)
  • listener to funkcja, która zostanie wywołana po wyłapaniu eventu

 

W części dotyczącej responsywnego menu poznaliśmy inny sposób wyłapywania eventu i oba są poprawne. W ramach zadania domowego (po przeczytaniu tego wpisu) spróbujcie zamienić tamten zapis eventu na ten poznany dzisiaj i na odwrót 😉

 

Zaczniemy od przypisania elementu pod „element”. W tym przypadku będzie to po prostu:

Podmienimy sobie jeszcze type i listener

Oczywiście „scroll” to nasz event a „toggleBackTop” to nazwa funkcji, która będzie odpowiedzialna za obsługę naszego odnośnika.

 

Funkcje

Czym jest funkcja? Jest to zbiór różnych „czynności” zgrupowanych w jednym miejscu. Weźmy za przykład coś z naszego życia – gotowanie obiadu. Funkcją mogłoby być wtedy „zróbObiad” a w funkcji mielibyśmy takie czynności jak: wybranie potrawy, kupienie produktów, ugotowanie obiadu. Taką funkcję możemy uruchomić (wywołać) z dowolnego miejsca.

Jednym ze sposobów tworzenia funkcji jest:

O pozostałych sposobach napiszę więcej w kursie.

Zaczynamy od słowa „function”, które informuje przeglądarkę, że tworzymy funkcję. Następnie mamy „nazwa”, które jest nazwą funkcja – np. „zróbObiad” czy nasze „toggleBackTop”. Dalej mamy nawias, w którym znajdują się argumenty, które przekazujemy do funkcji. Co to znaczy? Wróćmy do naszego obiadu – chcemy wywołać funkcję i przekazać, że chcemy na obiad np. rosół wtedy wywołujemy funkcję za pomocą:

a deklaracja funkcji będzie wyglądać tak:

Jeśli nie chcemy aby do funkcji był przekazywany argument (np. potrwa na obiad ma być wybierana wewnątrz funkcji) to nawiasy zostawiamy puste „zróbObiad()”.

 

Na końcu mamy klamry otwierającą i zamykającą – wewnątrz nich znajduje się kod naszej funkcji.

 

Nasza funkcja będzie wyglądać tak:

Cały nowy kod:

 

Instrukcja warunkowa if…else

Po pierwsze musimy rozpoznawać jak bardzo jest przewinięta nasza strona. Do tego posłuży nam:

 

Następnie musimy wykryć czy strona jest przewinięta odpowiednio – w naszym przypadku jeśli będzie to przynajmniej 100px to wtedy pokazujemy odnośnik a jeśli mniej to ukrywamy. Jak to zrobić? Do tego posłuży nam instrukcja warunkowa if…else, która ma taki zapis:

Kod zaczynający się od // to komentarz – nie jest wykonywany

Działa to tak, że jeśli podany warunek zostanie spełniony to wykona się kod zawarty zaraz za if

Jeśli warunek nie zostanie spełniony to wykona się kod po else

 

Przystosowując do naszych potrzeb będzie to:

Co „po ludzku” oznacza: jeśli strona jest przewinięta przynajmniej o 100px to wykonaj pierwszy kod, w przeciwnym razem wykonaj drugi

 

Manipulacja CSS’em

Aby móc odwołać się do jakiegoś elementu na stronie możemy skorzystać z różnych funkcji jak np. użyte przy menu „document.getElementsByClassName” czy „document.querySelector”. Czym się różnią? W pierwszej funkcji możemy podać tylko klasę natomiast w drugiej możemy podać pełną ścieżkę do elementu łącząc klasy, id, atrybuty czy pseduelementy – tak samo jak robimy to w CSS. Drugą różnicą jest to, że getElementsByClassName zawsze zwraca tablicę elementów nawet jeśli znajdzie tylko jeden element o podanej klasie a querySelector w przypadku znalezienia tylko jednego elementu zwraca od razu ten element.

 

Div w którym jest nasz odnośnik ma ustawione id „back-top” w CSS możemy się do niego odwołać za pomocą „#back-top” i tak samo możemy to zrobić korzystając z querySelector:

Teraz aby pokazać nasz odnośnik wystarczy zmienić mu styl:

„style” odwołuje się do wszystkich styli naszego elementu, „display” odwołuje się do  właściwości „display” a „= ‚block'” służy do przypisania tej wartości do właściwości „display” co w CSS przekłada się na „display: block”

 

Żeby ukryć element wystarczy podmienić wartość dla „display” na „none”:

 

Nasza funkcja wygląda teraz tak:

https://codepen.io/morawcik/pen/RgBLWO

Animacja

A co jeśli chcemy aby pokazywanie się i ukrywanie odnośnika było animowane a nie zwykłe pokaż/ukryj? Musimy zacząć od zamienienia dla #back-top

na

 

I teraz wystarczy w JS podmienić zmianę właściwości (wraz z wartościami) „display” na „opacity”:

na

https://codepen.io/morawcik/pen/xrJWwo

 

Przewijanie strony do góry

Ostatnim krokiem jest sprawienie aby po kliknięciu w przycisk strona przewijała się do początku. Oczywiście teraz po kliknięciu zostaniemy przeniesieni do początku strony ale jest to przeskok – w jednej chwili jesteśmy gdzieś na dole a po kliknięciu od razu na początku. Naszym celem jest sprawienie aby przewijanie było płynne.

 

Najpierw musimy wyłapać sobie kliknięcie w odnośnik:

 

Następnie tworzymy funkcję „scrollTop”:

Argument „event” który przekazujemy do funkcji to obiekt, który zawiera dużo informacji dotyczących danego eventu (u nas kliknięcia), które nieraz są bardzo pomocne. Możemy z tego dowiedzieć się, na którym elemencie został wywołany event, poznać jego położenie na stronie itd. Nas interesuje tylko funkcja „preventDefault”, która (w prostych słowach) wyłącza podstawowe działanie elementu. Np. dla odnośnika jest to przejście pod adres, który znajduje się w atrybucie „href” – jeśli użyjemy „preventDefault” to osobo która kliknie w taki odnośnik nie zostanie przeniesiona pod adres z tego odnośnika.

Nasz odnośnik ma ustawiony atrybut „href” na „#”, więc nie zmienilibyśmy strony ale po kliknięciu bylibyśmy przenoszeni od razu na początek strony a tego nie chcemy – chcemy zrobić animację.

 

Następnie w funkcji „scrollTop” dodajemy:

„var scrollInterval” tworzy nam zmienną (czyli takie „pudełko” w którym coś przechowujemy – np. jakąś wartość czy nawet całą funkcję) do której przypisujemy funkcję „setInterval”. Czym jest ta funkcja? Jest to funkcja, która wykonuje się w kółko bez końca lub do momentu jej przerwania i ma taki zapis:

„czas” to czas w milisekundach, który określa co ile wykonuje się podana funkcja (u nas jest to 15 milisekund).

„nazwaFunkcji” to po prostu funkcja, która wykonuje się co określony czas. Zamiast tworzyć nową funkcję możemy zrobić tak jak powyżej – utworzyć anonimową funkcję czyli taką, która wykona się tylko tutaj i nigdzie indziej nie możemy się do niej odwołać.

 

Pozostało tylko przewinąć stronę do samego początku. Po pierwsze musimy sprawdzić czy jesteśmy już na początku czy jeszcze nie:

W if’ie sprawdzamy czy pozycja przewijania (w pionie) jest różna od „0” (zero) czy nie. Jeśli nie jesteśmy na początku to musimy przewinąć stronę. Możemy to zrobić za pomocą:

„scrollBy” to funkcja wywoływana na oknie przeglądarki (window), która służy do przewijania. Pierwszy parametr określa o ile przewijamy w poziomie a drugi w pionie. Jako, że chcemy przewinąć tylko do góry to pierwszy parametr jest ustawiony na „0” (zero) – nie przewijamy w poziomie, a drugi na „-50” – przewijamy o 50px do góry. Jeśli chcemy zwiększyć lub zmniejszyć szybkość przewijania wystarczy zmienić „-50” na inną wartość.

 

W tej chwili nasza anonimowa funkcja będzie się wykonywać ciągle ale przewijanie będzie tylko do momentu aż strona nie będzie przewinięta do samego początku. Na koniec musimy „wyłączyć” wykonywanie się tej funkcji jeśli już dotarliśmy na początek. Aby „wyłączyć” działanie funkcji „setInterval” musimy użyć:

Funkcja ta „czyści” ustawiony interwał, który znajduje się w zmiennej „scrollInterval” – jeślibyśmy nie przypisali interwału do zmiennej to nie moglibyśmy go później wyczyścić i musiałby wykonywać się bez przerwy co uniemożliwiłoby przewijanie strony w dół (przy każdej próbie wracalibyśmy na górę).

https://codepen.io/morawcik/pen/XgBEVL

 

I gotowe!

Macie pomysł na swój wygląd odnośnika albo macie jakieś pytanie? Piszcie śmiało 🙂


Post 11 z 13 z serii Blog od podstaw
  • Dobrym nawykiem jest pisanie kodu po angielsku (nazwy funkcji itp.), ale polskie znaki (ąę…) to już przesada 😉

    • Zgadzam się w 100% – podany kod to tylko zobrazowanie przykładu

  • Dorian Bajorek

    Fajna odskocznia od Jquery

    • Polecam czysty JS – czasem nie warto ładować całej biblioteki do prostego skryptu.

  • Warto poprawić ten ‚przycisk’ ze strony dostępności. Proponowałbym takie rozwiązanie: https://jsfiddle.net/abd8uyux/

    • Warto ale nie wiem czy na początku w podstawach chcę iść w takie szczegóły. Przemyślę jeszcze sprawę i o ile się zdecyduję to w przyszłości poświęcę cały wpis na „takie sprawy” 🙂

      • Myślę, że zalicza się to do podstaw. Warto takie rzeczy wpajać od początku 🙂

  • Jaro Jaro

    Wylaczylismy event.preventDefault ale nie zastapilismy to inna funkcja, wiec w jaki sposob ma sie przewijac strona po clicku na top?

    • Cały kod zawarty w setInterval odpowiada za „płynne” przewijanie.

      • Jaro Jaro

        rozumiem, ale ktora funkcja wywoluje wlasnie setinverval? Bo ja rozumiem to w ten sposob ze musi byc nasluchiwacz ktory po clicku na nasza strzalke wlasnie wywola setInterval. Z tego co widze w kodzie to tylko wylaczylismy domyslna funkcje przez preventDefault, ale nie rozumiem w jaki sposob to sie laczy ze soba.

        Dodam tylko ze zrobilem wlasnie krok po kroku tak jak napisales to i u mnie na stronie to nie dziala, wklejam kod:

        document.addEventListener(‚scroll’, toggleBackTop);

        function toggleBackTop () {
        if (window.scrollY >= 100) {
        document.querySelector(‚#back-top’).style.opacity = „1”;
        } else {
        document.querySelector(‚#back-top’).style.opacity = „0”;
        }
        }

        document.querySelector(‚#back-top’).addEventListener(‚click’, scrollTop);

        function scrollTop(event) {
        event.preventDefault();
        }

        function Top() {
        window.scrollY = 0;
        }

        var scrollInterval = setInterval(function() {
        if (window.scrollY != 0) {
        window.scrollBy(0, -50);
        }
        else {
        clearInterval(scrollInterval);
        }
        }, 45);

        • setInterval ma być w funkcji scrollTop (całość widać na załączonym przykładzie z codepen.io).
          Dodałem info do artykułu, bo faktycznie nie było to odpowiednio napisane. Przepraszam za kłopot, postaram się aby w przyszłości nie było już takich niejasności 🙂

          • Jaro Jaro

            a no tak, przeciez to oczywiste;p dzieki ze tak szybko odpisales. Robisz dobra robote, powodzenia.

          • No właśnie nie wiem czy takie oczywiste – tzn. dla mnie tak, bo wiem gdzie to napisałem ale dla kogoś kto to czytał już nie koniecznie.
            Dzięki! 🙂