od Podstaw
10 godz. 55 min · JavaScript · Full-stack i Programowanie
Piotr PalarzWeb DeveloperJeśli poznałeś już wymienione wyżej technologie, to zapewne zdajesz sobie sprawę z ich ograniczeń. Za pomocą języka HTML tworzymy bowiem strukturę dokumentu, dodajemy treść tekstową, obrazy czy wideo. Aby jednak strona internetowa wyglądała perfekcyjnie, korzystamy z arkuszy stylów CSS, które pozwalają nam opisać wygląd wszystkich elementów HTML, ustawić wielkość tekstu czy dodać tło strony. No właśnie, ale gdzie tutaj interakcyjność?Zapewne już wiesz, że język CSS oferuje tzw. pseudoklasy, które pozwalają nam np. przypisać zmianę koloru elementu po najechaniu na niego kursorem myszy. I to tak naprawdę wszystko, na co możemy zareagować. A co gdybyśmy chcieli po wciśnięciu jakiegoś przycisku wysunąć ukryty panel, sprawdzić poprawność wypełnianego właśnie formularza lub pobrać dane z serwera i wyświetlić je na stronie bez przeładowywania witryny? Dobra wiadomość jest taka, że to wszystko jest możliwe z użyciem języka JavaScript, który “rozumie” każda przeglądarka internetowa.Choć język JavaScript powstał jako język skryptowy na potrzeby stron internetowych, to już dawno temu “wyszedł” z przeglądarek internetowych i może być używany tak naprawdę gdziekolwiek. W kursie, który masz przed sobą, poznasz język JavaScript jako niezależny język programowania, a dopiero później dowiesz się, jak wykorzystywać go do wzbogacania stron internetowych. Dzięki postawieniu grubej linii pomiędzy samym językiem, a Obiektowym Modelem Dokumentu dostępnym w przeglądarkach internetowych, będziesz nie tylko bardzo dobrze rozumiał sam język, ale w przyszłości wykorzystasz go do innych zastosowań.Na początku omówimy ciekawą historię języka JavaScript, a chwilę później rozpoczniemy poznawanie najważniejszych jego konstrukcji. I tak dowiesz się czym są zmienne, jakie typy danych dostępne są w tym języku, czym są liczne operatory, instrukcje warunkowe, pętle, tablice, obiekty i funkcje. Wszystkie te zagadnienia są bardzo podobne w innych językach programowania, dlatego kurs ten jest również świetnym wstępem do programowania w ogóle. Każda z przedstawianych konstrukcji języka jest bardzo dokładnie tłumaczona z myślą osobach początkujących. Nie zmienia to jednak faktu, że nawet osoby znające już podstawy języka JavaScript znajdą tutaj coś dla siebie, gdyż na każdym etapie przedstawiane są również liczne ciekawostki odnośnie danej konstrukcji.Kiedy zrozumiesz już jak działa język JavaScript, przejdziemy do drugiej połowy kursu, gdzie dokładnie omówimy Obiektowy Model Dokumentu, dostępny w przeglądarkach internetowych. Zobaczysz jak przeglądarka tworzy z kodu HTML drzewo dokumentu, jak reprezentowane są poszczególne jego węzły, a także jak język JavaScript potrafi z tym “wewnętrznym światem” współpracować. Dowiesz się jak wyszukiwać na stronie interesujących nas elementów HTML, a także jak tworzyć nowe elementy, przypisywać im treść i wstawiać je na stronę. Popracujemy również z atrybutami elementów, ich klasami i wreszcie ze stylami CSS, abyśmy mogli wpływać dynamicznie na wygląd naszej strony.Zobaczysz również, jak możemy w dowolnym momencie odczytać współrzędne położenia elementu na stronie, a także jego wysokość czy szerokość. Tę wiedzę wykorzystamy później w praktycznym przykładzie.Jeden z rozdziałów kursu poświęcony został zdarzeniom, a więc możliwości reagowania na zachowania użytkownika. Dzięki temu zobaczysz, jak możemy przypisać np. zdarzenie kliknięcia do wybranego elementu, a kiedy zostanie on kliknięty, wykona się przygotowany przez nas kod. Poznasz kilka różnych sposobów na przypisywanie oraz usuwanie zdarzeń, a także dowiesz się czym jest tzw. “bubbling” oraz “capturing” czy jak zablokować domyślną akcję przeglądarki.Przy pisaniu jakiegokolwiek kodu, zawsze pojawiają się błędy, dlatego i tutaj Twoje wątpliwości nie pozostaną bez odpowiedzi. Poznasz wszystkie typu błędów, które mogą się pojawić podczas wykonywania naszego kodu, a także wiele sposobów ich wykrycia i wyeliminowania.W kursie nie brakuje oczywiście praktycznych przykładów, które celowo zostały ułożone tak, aby wykorzystać w nich jak najwięcej zdobytej wcześniej wiedzy. Nie zostaniesz więc sam z poczuciem, że co prawda rozumiesz jak działa dana konstrukcja, ale nie masz pomysłu, kiedy z niej skorzystać. Na początek wykonamy praktyczny projekt losowania liczb z wybranego przedziału tak, aby nie mogły się powtórzyć. Już przy tym projekcie poznasz wiele ciekawych technik i sztuczek.Następnie przejdziemy do nieco bardziej zaawansowanego przykładu i napiszemy skrypt, który pozwoli nam sortować dane w tabeli po wybranych kolumnach, kiedy któraś z nich zostanie kliknięta. Zobaczysz jak sortować dane zarówno malejąco jak i rosnąco, a także jak zmieniać kolejność elementów HTML na stronie.W kolejnym projekcie zajmiemy się walidacją danych wpisywanych do formularza, by ten nie mógł zostać wysłany do serwera tak długo, jak zawiera jakiekolwiek błędy. Zobaczysz tutaj zdarzenia związane z polami formularza, a także sposoby na pobieranie z nich wartości i sprawdzanie czy są one poprawne. Zadbamy także o wrażenia użytkownika i wyświetlimy na stronie stosowne błędy, a także podświetlimy źle uzupełnione pola na czerwono.W przedostatnim projekcie wstawimy na stronę przycisk, który będzie się pojawiał po przewinięciu strony w dół, a znikał po odwrotnej akcji. Co jednak ciekawe, po jego kliknięciu, strona zostanie automatycznie, płynnie przewinięta do samej góry.W ostatnim projekcie stworzymy bardzo efektowny dymek z podpowiedzią, który będzie się pojawiał nad elementem po najechaniu na niego kursorem myszy. Wykorzystamy tutaj mnóstwo ciekawych technik. Dowiesz się również jak swój kod przygotować w taki sposób, abyś mógł go udostępnić innym osobom, by w łatwy sposób skorzystały z przygotowanego Tooltipa na swoich stronach.Kurs kończy się sekcją Tips & Tricks, w której znajdziesz 10 krótkich lekcji. W każdej z nich została omówiona jedna sztuczka. Każda z nich pozwoli Ci jeszcze lepiej zrozumieć język JavaScript, ale przede wszystkim zaoszczędzić czas i kilka linijek często niepotrzebnego kodu.Podsumowując, kurs ten jest nie tylko wprowadzeniem do samego języka JavaScript, ale także do Obiektowego Modelu Dokumentu. Dzięki wyraźnemu rozdzieleniu tych dwóch zagadnień, będziesz mógł w przyszłości wykorzystać język JavaScript także do innych zastosowań, poza przeglądarką internetową.
Kurs ten jest dla wszystkich osób, które znają już podstawy HTML i CSS i chciałyby przejść poziom wyżej i dodać do swoich stron dynamiczności. Żadna wcześniejsza wiedza z zakresu JavaScript czy programowania nie jest wymagana, gdyż wszystkie konstrukcje są starannie tłumaczone. Materiał ten będzie również świetnym odświeżeniem i usystematyzowaniem wiedzy dla osób, które już z tym językiem miały do czynienia. Po przerobieniu tego kursu będziesz gotowy, by poznawać język JavaScript dalej, z kursem JavaScript w Praktyce, który powstał jako dopełnienie tego kursu i porusza nieco bardziej zaawansowane tematy, na które tutaj zabrakło już czasu.
Ostatnim projektem, który wspólnie w tym kursie stworzymy,
mam nadziejęm że pracujesz razem ze mną,
Jest tooltip, czyli taki dymek z podpowiedzią, który będzie się pojawiał nad pewnymi elementami.
Ja na razie w kodzie HTML umieściłem tutaj, jak widzisz tekst, jakieś zdjęcie i tutaj np.
Element strong,
zauważ, że po najechaniu Jeżeli chwilę poczekam pojawia się tytuł.
Z tego powodu, że w HTMLu możemy przypisywać atrybut title do wszystkiego praktycznie i on się w przeglądarce
pojawia.
Do obrazka również przypisałem, czy do tego paragrafu.
Konkretnie tutaj do linku.
Czyli jeżeli nad obrazkiem chwile poczekam to pojawi się tutaj taki oto dymek taki tooltip, ale jest to
domyślna akcja przeglądarki i z JavaScript'em to ma niewiele wspólnego.
Dlatego będziemy chcieli stworzyć swój własny tooltip, który będzie się wyświetlał nad elementem, na który
najedziemy.
Natomiast, o co chodzi.
Chodzi nam właśnie, o to aby pobrać sobie wszystkie elementy, które mają atrybut title i aby w tym domku
było wyświetlone to, co jest tutaj, więc będziemy mogli je bez problemu znaleźć, przy okazji w tej lekcji,
pokażę ci jak możemy tutaj w tej funkcji anonimowej, która się sama wywołuje, ukryć pewne funkcje, a pewne
funkcjonalności udostępnić na zewnątrz, zaraz dokładnie pokaże ci jak to zrobić.
Otóż będę chciał utworzyć tutaj na początku funkcję init, bo ładnie to wszystko podzielimy i będzie to
taka funkcja, która będzie wykonywana na początku.
Chciałbym żeby do niej były przekazane elementy, które chcemy objąć tym tooltip'em
Wspomniałem ci, że będą to wszystkie elementy z atrybutem title, ale powiedzmy, że piszemy własny plugin,
który udostępnimy komuś i chcemy, aby ten ktoś mógł zdecydować, na których elementach wyświetlimy ten dymek,
na których nie, więc będziemy chcieli przyjąć elems, czyli te elementy
i tutaj coś z tym będziemy chcieli zrobić.
Ale domyślasz się, że ta funkcja init nie będzie widoczna na zewnątrz, nigdzie.
Czyli gdybyśmy tutaj w kodzie pod scripts chcieli się odwołać do init, to nie będzie to dla nas dostępne.
Dlatego właśnie oprócz tego, że tutaj będzie jeszcze więcej funkcji.
Na samym końcu odwołamy się do window, który jest tutaj dostępny ten obiekt i nasz plugin nazwiemy tooltip,
w ten sposób, czyli t00ltip i napiszemy lub init.
Co to oznacza?
Że stąd jakby wyeksportowaliśmy na zewnątrz, czyli do window tooltip referencje do init.
Dzięki temu będziemy mogli tutaj wpisać sobie script, w taki liniowy sposób albo oczywiście w jakimś innym
pliku i będziemy tutaj mogli napisać t00ltip,
w ten sposób i będziemy mogli tutaj podać te elementy,
no i jak widzisz my tutaj możemy dowolnie sobie nasze funkcje nazywać tu będzie więcej funkcji z których
imit może korzystać, ale one na zewnątrz nie będą widoczne. Na zewnątrz
chcemy jedynie, aby po odwołaniu się do tooltip tak naprawdę odwołać się do init i tutaj pewne rzeczy przekazać,
czyli teraz jeżeli się odwołam do tooltip i coś podam to to coś będzie przekazane
tak naprawdę tutaj, bo tutaj tylko jest jakby proxy na tę funkcję, którą tutaj widać, czyli wszystkie elementy, które
mają tytuł chcielibyśmy podać.
Jak wspomniałem jeżeli komuś taki skrypt udostępnimy, to on będzie mógł wywołać tooltip,
po wczytaniu oczywiście tego skryptu i wybrać, które elementy mają być objęte tym tooltipem.
Dlatego tutaj wpiszemy document.querySelectorAll i następnie chcemy pobrać wszystkie elementy, które
mają atrybut title.
Tak możemy to zrobić tym selectorem CSS3, czyli tutaj, co ktoś poda, to to zostanie przekazane.
Wiesz, że będzie to ten obiekt tablicopodobny NodeList. On zostanie przekazany do tego tooltip, czyli
tak naprawdę do funkcji init, a imit będzie dostępne pod elems.
Czyli jeżeli tutaj sobie zrobimy console.log, zobaczmy, to wszystkie elementy, które mają title, czyli właśnie ten
strong tutaj img oraz link zostały nam zwrócone, a metoda init nie istnieje,
w tym oto miejscu i o to nam chodziło.
Myślę, że załapałeś na czym rzecz polega.
Bardzo przydatna sprawa, bo teraz możemy tutaj stworzyć jeszcze więcej funkcji z których init będzie korzystać
i teraz będziemy chcieli zrobić rzecz następującą.
Otóż taki dymek będzie się pojawiał po najechaniu na konkretny element.
Więc mamy kilka zdarzeń, jeżeli chodzi o najechanie na element w obiektowym modelu dokumentu my skorzystamy
z mouseenter i mouseleave, mouseenter jest wtedy kiedy najedziemy na jakiś element, a mouseleave kiedy opuścimy
ten element. Możemy na takie zdarzenia zareagować, skoro mamy tutaj elementy, to możemy wykonać pętle i
do każdego z nich przypisać pewne zdarzenia.
Natomiast nie chcę tego robić w funkcji init, zrobimy to w osobnej funkcji, którą nazwałem assignedEvent,
więc tutaj ją wywołamy, czyli przypisz zdarzenia.
Jak widzisz ktoś nam tutaj przekazał do naszego tooltip, wszystkie elementy, które go interesują a my
przekazujemy je dalej.
Teraz do funkcji assignEvents, więc którą teraz utworze, ona też przyjmuje elementy.
Pamiętaj, że te wszystkie nazwy, które są tutaj są dowolne. Jeżeli tu przekazuje
elems tu sobie mogę nazwać, ja chcę, już to tłumaczyłem.
Ale gdybyś czasem zapomniał i mamy do tego dostęp to nie musi się nazywać tak samo, jak to dla wygody
tak nazywam i tutaj będziemy chcieli wykonać pętle i przypisać zdarzenia do wszystkich tych elementów.
Ta funkcja, chciałbym żeby przyjmowała jeszcze kilka parametrów tzn.
tutaj chcę napisać assignEvents, czyli przypisz zdarzenia do wszystkich elementów, które tutaj przekażę.
Chcę, żeby to zdarzenie to było mouseenter, tak jak ci wspomniałem, ono tak wygląda i następnie chcę, aby
była wykonana funkcja showTooltip, którą za moment będziemy tworzyć i teraz jak to działa normalnie musielibyśmy
się odwołać do jakiegoś elementu, następnie addEventListener mouseenter.
I taka funkcja, ale ja stworzyłem sobie funkcję pomocniczą assignEvents i w niej właśnie się do tego
odwołam.
Skoro tutaj podałem jeszcze dwa parametry, to ona powinna je tutaj przyjmować,
czyli nazwiemy tutaj type oraz powiedzmy event.
Może to być w ten sposób i teraz będziemy chcieli po wszystkich tych elementach, które tutaj przekażemy
przeiterować i każdemu z nich dodać
addEventListener mouseenter, czyli type
i na to, żeby się wykonała funkcja która się będzie nazywać showTooltip, tutaj
ją przekażemy.
Czyli tutaj wykonamy po prostu pętlę. Ja wkleję gotowy kod, na pewno już na tym etapie rozumiesz o
co chodzi, iterujemy po wszystkich elementach.
Każdemu z nich poprzez addEventListener
przypisujemy type, czyli to, tutaj zostanie podstawione.
Następnie to co przekażemy tutaj i tutaj ostatni parametr false.
Dzięki temu każdy z elementów, który został przekazany tutaj, a w konsekwencji tutaj, otrzyma na zdarzenie
mouseenter
funkcję showTooltip, więc warto ją teraz utworzyć, aby nie było błędu, ona może być na razie pusta.
W ten sposób, ta funkcja, jest przypisywana, jak widzisz, poprzez addEventListener, właśnie w tym miejscu,
bo dokładnie referencja do niej jest przekazana tutaj, a stąd tutaj.
A to oznacza, że ona może przyjmować ewent i będziemy chcieli coś z tego eventu wyświetlić.
Na razie zróbmy sobie console.log, najechanie myszą, ok, sprawdźmy, czy nam to działa.
Czyli jeżeli najadę sobie na ten element, który miał title.
Jak widzisz, najechanie myszą działa, na obrazek, jeśli najadę również w konsoli i na ten link również.
Czyli do każdego z tych elementów przypisaliśmy zdarzenie mouseenter.
Teraz chce przypisać do każdego z tych elementów zdarzenie mouselift, ono wygląda w następujący sposób.
Z tego powodu, że chcę wyświetlić tooltip, kiedy najedziemy na taki element, a kiedy z niego zaskoczymy to
chcę, aby ten tooltip został schowany.
Dlatego, będziemy chcieli stworzyć nową funkcję, którą nazwiemy removeTooltip i znowu ją tutaj utworze, abyśmy nie mieli
błędu, że ją tutaj podstawiamy i tutaj możemy napisać powiedzmy,
opuszczenie myszy,
czyli chodzi o to, że z elementu zjechaliśmy. Najeżdżamy na element, najechanie myszą, zjeżdżamy, opuszczenie
myszy.
Wszystko działa, na razie, jak należy i przypisaliśmy sobie za pomocą pomocniczej funkcji.
Zdarzenia, możesz z niej korzystać możesz ją również przerobić, w łatwy sposób możemy przypisać zdarzenia
do wielu elementów.
Skoro mamy już funkcję showTooltip, to będziemy chcieli w niej pobrać sobie title elementu na które najechaliśmy.
Już wiesz, że poprzez e.target możemy się odwołać do elementu, na który najechaliśmy myszą, tak samo jak z kliknięciem
i będziemy mogli pobrać jego atrybut title, czyli możemy tutaj napisać text równa się e.target i następnie
getAttribute, title. Wyświetlmy go sobie w konsoli,
czyli text, a więc po najechaniu myszą na jakiś element, powinniśmy w konsoli zobaczyć jego title.
Tak też się dzieje, jeżeli chwilkę poczekam w przeglądarce, jak widzisz, mamy
Dowiedz się więcej.
I to też w konsoli się wyświetliła.
Jeżeli jadę na obrazek to fotografia z pierwszego miejsca, powiedzmy taki jest title przypisany dokładnie
tutaj w kodzie HTML, czyli na razie wszystko działa jak należy.
I teraz, co będziemy chcieli zrobić.
Otóż stworzymy jeszcze jedną funkcję, która się będzie nazywała createTooltip, a więc twórz Tooltip i będziemy
chcieli ją tutaj wywołać, przekazując jej właśnie ten tytuł.
Zróbmy to w ten sposób, czyli wywołamy taką funkcję i przekażemy jej po prostu tekst. Utwórzmy ją jeszcze
wyżej.
Wszystko będzie ładnie podzielone i tak jak ci wspominałem, te funkcje na zewnątrz nie są widoczne, a
na zewnątrz tylko wyeksportowaliśmy
twłaśnie zapis, czyli Tooltip. Napiszemy createTooltip. Ona będzie przyjmować właśnie jakiś tekst, który
tutaj przekazujemy, więc możemy tutaj tę zmienną nazwać tekst i będziemy chcieli utworzyć nowy element,
który nam się będzie na stronie pojawiał.
Ja od razu mogę ci powiedzieć, że będzie to element div który wcześniej ostylowałem.
Więc tworzymy zmienną Tooltip i document.createElement div.
Będę chciał mu przypisać od razu dwie klasy.
Wierzę, że możemy to zrobić poprzez classListApp.
Albo np. poprzez className.
I tutaj musimy podać string, więc Tooltip, to jest pierwsza klasa, a druga to będzie hidden, aby był on ukryty.
Chociaż na razie, nie musimy go ukrywać.
Może zróbmy tutaj tylko Tooltip, bo chcę Ci pokazać jak on będzie wyglądał i teraz będę chciał do niego
również wstawić tekst, który został przekazany.
Więc możemy to zrobić poprzez Tooltip,
textContent albo np. poprzez appendChild, chcę ci przypomnieć, że również możemy tutaj stworzyć nowy
obiekt tekstowy.
Pamiętasz, że mieliśmy taką metodę i jej możemy przekazać tekst. Ona nam zwróci nowy obiekt tekstowy, który
poprzez appendChild możemy tutaj dodać. Prościej byłoby to zrobić poprzez kropka textContent i przypisać
równa się text,
ale zróbmy to w ten sposób, czyli tutaj, po najechaniu na jakiś element, bierzemy jego title i wywołujemy
funkcję createTooltip, przekazując ten właśnie title dalej i ten title zostanie ustawiony dla takiego elementu
div, któremu nadaliśmy również klasę Tooltip.
No i wstawmy sobie
to teraz do document.body.appendChild, żebym mógł pokazać na czym to polega.
Ok, czyli teraz po najechaniu na jakiś element powinniśmy mieć w document.body wstawione taki Tooltip.
Uwaga.
Mamy błędy createTooltip is not defined, błąd w linijce 28, zerknijmy, napisałem
createTooltip, tutaj jest błąd, OK, literówka. Raz jeszcze.
Po najechaniu powinien nam zostać wstawiony tutaj ten Tooltip i dokładnie tak się stało.
Dlaczego on
wygląda w ten sposób?
Ano właśnie dlatego, że w stylach CSS to zdefiniowałem.
Jak to zrobić możesz sobie zajrzeć do styli.
Nie ma to z JavaScript'em nic wspólnego,
czyli div, który ma klasę Toolkit i środku ma tekst będzie wyglądał w taki oto sposób, jak tutaj widzisz.
Jeżeli jesteś ciekaw jak działa to after i jak dodałem tutaj taką strzałeczkę, to na blogu eduweb.pl
możesz znaleźć artykuł, w którym opisuje, jak takie pseudo klasy działają w CSS, czyli before i after.
Zachęcam cie do przejrzenia tego artykułu.
Mamy już Tooltip, który został na stronę wstawiony i teraz pozostało nam zrobić jedną rzecz, mianowicie ten
Tooltip wyświetlić w tym miejscu, gdzie jechaliśmy na konkretny element.
Przy okazji możesz zobaczyć, że kiedy ja najeżdżam na te elementy, tych typów jest tutaj pełno wstawianych,
dlatego chciałbym od razu usunąć taki Tooltip, w momencie, kiedy z takiego elementu zjeżdżamy.
No i teraz mógłbyś się zastanawiać, jak to zrobić.
Stworzyliśmy taki Tooltip, wstawiliśmy go na stronę i teraz jak go usunąć, stworzyliśmy funkcję removeTooltip i
moglibyśmy w niej wyszukać element poprzez document.querySelector z klasą Tooltip, który znajduje się na
stronie, my go tutaj wstawiliśmy i go usunąć.
Ale łatwiej to będzie zrobić inaczej.
Mianowicie na samej górze otworzymy zmienną, którą nazwę globalTooltip i ona na początku będzie mieć wartość
null, natomiast w momencie, kiedy taki Tooltip utworzymy, tutaj wstawiamy go do body, przypiszmy go sobie do
globalTooltip,
w ten sposób, czyli teraz będziemy mieli ten element wstawiony do body, ale również jego referencja będzie tutaj i
dzięki temu, będzie on dostępny w funkcji removeToolkit.
Czyli w tej funkcji będziemy go chcieli usunąć, a więc odwołamy się do globalTooltip, żeby usunąć taki element wiesz,
że musimy odwołać się do jego parentNode,
removeChild i znowu podamy globalTooltip.
No i teraz nam to powinno zadziałać, sprawdzimy raz jeszcze.
Najeżdżam na jakiś element, Tooltip powinien zostać dodany.
Jak widzisz, jest.
Ale kiedy ja z tego elementu zjeżdżam, on szybko nam znika, bo jest ze strony usuwany. Próbuje zaskalować i
zaskoczyłem z elementu. Element znika i widzimy, że tutaj go nie ma.
Czyli jest wszystko OK.
Pozostało nam go w pozycjonować w odpowiednim miejscu i teraz jak możemy to zrobić.
Pokazywałem ci jak odczytać położenie na naszej stronie konkretnego elementu poprzez np.
getBoundingClientRect
i zauważ, że kiedy najedziemy na taki element, to w e.target, tutaj, showTooltip,
będziemy mieli dostęp do tego oto elementu.
Chciałbym zatem, w tym miejscu, stworzyć sobie taką zmienną, którą nazwę options i chciałbym, żeby to był
obiekt, bo będziemy go przekazywać dalej.
Chciałbym, żeby w tym obiekcie było x, to będzie jakaś wartość, czyli położenie naszego obiektu x i położenie
naszego obiektu y, to będzie jakaś inna wartość i jeszcze jego szerokość, która nam będzie również potrzebna
czyli width.
Jak możemy to zrobić, już pokazywałem, kiedy odwołamy się do e.target, czyli do naszego konkretnego elementu,
możemy pobrać jego offsetWidth.
Ja ci to pokażę może jeszcze tutaj.
Czyli w console będzie to s zero, pamiętasz i możemy się odwołać do offsetWidth, czyli pobrać jego szerokość do
offsetLeft, czyli sprawdzić, gdzie on się znajduje tutaj od lewej strony.
I jeszcze możemy się odwołać do offsetTop, czyli widzisz 629 pikseli od góry naszej strony, on się znajduje
i te wszystkie wartości chciałbym teraz tutaj zapisać, czyli e.target offsetWidth.
Tutaj tworzymy sobie nowy obiekt, któremu definiuje w, x oraz y i po prostu przypisuje poszczególne wartości. Uzupełnię
to do końca.
I to wszystko będzie tutaj zapisane. Możemy zrobić oczywiście console.log options, aby już na tym etapie
wiedzieć, co tam jest.
No i zobaczmy nowy obiekt gdzie mamy w: 140 x: 314 itd.
A po najechaniu na obrazek.
Są to inne zupełnie wartości, szerokość obrazka, jego odsunięcie, tutaj od tej strony oraz odsunięcie od
góry.
I teraz zapytasz, po co mi to jest potrzebne.
Otóż kiedy najadę sobie na taki element to chciałbym Tooltip wyświetlić tutaj na samym środku, czyli muszę
znać odsunięcie tego elementu od lewej strony, tutaj.
Następnie jego szerokość i będę mógł dzięki temu wyliczyć gdzie jest jego środek.
I tutaj będę chciał ustawić nasz Tooltip, zaraz sobie to zrobimy.
Mamy tutaj te opcję i do createTooltip chciałbym je również przekazywać, czyli ten obiekt, który tutaj utworzyliśmy.
Zatem wróćmy i zmodyfikuję tę naszą funkcję, żeby ona jeszcze przyjmowała drugi parametr, którym jest
options.
Przekażemy go tutaj, więc będziemy się mogli odwołać do options kropka
w, x albo y.
Dzięki temu, że w taki fajny sposób sobie to zapisaliśmy. Teraz mając ten Tooltip, w tym miejscu, będę chciał
od razu przypisać do niego pewne style.
Wstawiamy go tutaj do body, w tym miejscu i możemy mu przypisać od razu pewne style.
Albo możemy to zrobić przestawieniem go do body. Pokazywałem ci w lekcji o stylach, że poprzez kropka
style, możemy się do niego odwołać. Ja go pozycjonowałem, jeśli zerkniesz tutaj i mamy tutaj Tooltip.
Jest to position absolut, więc jedyne co on potrzebuje to właściwość CSS top.
Gdybyśmy ją tutaj wpisali. Ile ma być od góry odsunięty oraz left, czyli od lewej strony.
Dlatego teraz zrobimy to z poziomu skryptu, czyli Tooltip.style.top będę chciał przypisać to, co zostało
przekazane, czyli options.top, zaraz to zmodyfikujemy,
ale to jest wartość number,
to co widziałeś tutaj np. y.
Więc chcemy do tego dodać px. Pamiętaj, że musimy tutaj to połączyć i dodać tutaj px. Natomiast tutaj nie
będzie oczywiście top, bo w tym obiekcie będziemy mieli y, tak jak sobie to zrzuciłem i od razu będę chciał
jeszcze przypisać style.left
i tutaj będzie x, może sobie to nawet zamienię kolejnością jest jakoś dla mnie bardziej logiczne.
Zobaczmy teraz, jak to będzie wyglądać.
Czyli, po najechaniu na taki element tu mi wyświetli się, no mniej więcej w jego miejscu, czyli w tym samym
miejscu, a teraz chcemy żeby wyświetlił się trochę wyżej, mniej więcej nam
to działa. Troszkę skacze, ale jak widzisz, jest ok, a jeżeli najadę sobie tutaj, to on się pojawi tutaj.
Teraz chcemy żeby był jeszcze na środku i trochę wyżej, więc musimy sobie tutaj te obliczenia troszeczkę dostosować.
Będzie nam potrzebna wysokość takiego Tooltip'a, bo jeżeli on się teraz wyświetla, jak widzisz tutaj, to chciałbym
o całą jego wysokość odsunąć go do góry, czyli jego wysokość jest mi potrzebna.
A więc będę chciał tutaj, gdzie zrobiłem y, odsunąć go jeszcze o jego wysokość, czyli options y minus, napiszemy
sobie tutaj Tooltip i weźmiemy jego wysokość, czyli będzie to offsetHeight.
Zobaczymy, czy nam to teraz jakoś zadziała.
Nie do końca nam to zadziałało.
Zobaczmy z jakiego powodu, może spróbujmy zrobić w ogóle console.log, w tym miejscu.
Jaka jest wysokość naszego Tooltip'a.
Obawiam się, że na tym etapie może to być 0.
No właśnie, więc nam to nie zadziałało i to z tego powodu, że musimy go najpierw wstawić do body, aby przeglądarka
go wyrenderowała i wówczas kiedy będziemy chcieli pobrać jego wysokość, to już powinna tutaj jakaś być.
Zobaczmy.
Po najechaniu teraz tutaj jest 34.
Czyli w ten sposób, nam to zadziała.
Jak widzisz on się pojawia już w fajnym miejscu, ale jeszcze z 10 pikseli do góry moglibyśmy go spokojnie
odsunąć.
Czyli tu napiszmy jeszcze, minus 10.
I aby to lepiej pogrupować, to będzie działać dokładnie tak samo.
Ja sobie to zapiszę w ten sposób. Mam nadzieję, że rozumiesz, o co chodzi.
Czyli teraz on się wyświetla tam, gdzie chciałem aby się wyświetlał w przypadku obrazka, 10 pikseli nad obrazkiem.
Wszystko działa, na razie, jak należy.
I teraz chciałbym go jeszcze wyświetlić na środku i będzie to prawie koniec naszego projektu.
Aby go wyświetlić na środku, musimy tutaj operować właściwością left, którą przypisujemy, przy okazji, jeżeli
nie załapałeś jeszcze, po co jest to left i top.
To teraz niestety tego nie pokaże, bo nasz Tooltip ucieka, ale tak jak wspomniałem to jest po prostu CSS przypisanie
top i left, które działają, jeżeli mamy ustawione position absolute.
Ok, więc teraz będziemy chcieli odsunąć tutaj ten
x do połowy naszego elementu.
Nie bez powodu tutaj zrobiłem sobie w,
czyli szerokość naszego elementu, na którym najechaliśmy np. obrazka.
Przekazałem go sobie w options.
Właśnie w to miejsce, czyli mamy go tutaj, więc możemy teraz napisać options.x plus options.w, czyli szerokość
naszego elementu, zobaczmy na ile nam się to zmieni.
Ok, pojawiło się to w tym miejscu, na samym końcu, więc chcemy tutaj zrobić sobie środek, a więc szerokość
naszego elementu dzielona na dwa, zapiszmy to może
w taki sposób, czyli szerokość naszego obrazka podzielona na dwa, to będzie tutaj i chcemy Tooltip
od lewej odsunąć do tej połowy.
Zobaczmy, już jest prawie dobrze.
Teraz jeszcze musimy ten Tooltip odsunąć o połowę jego szerokości w lewo.
Czyli tutaj będziemy chcieli jeszcze zrobić minus, tooltip.offsetWidth, ale połowę jego szerokości. Najpierw
pokaże ci na całość.
Nie jest na środku, więc to również chcemy podzielić przez dwa. Dużo mamy tutaj obliczeń, ale myślę, że
to wszystko ma sens.
Okej i teraz ten Toolkit powinien się wyświetlać idealnie na środku, 10 pikseli nad każdym z takich elementów
i jak widzisz, fajnie nam to działa.
Tutaj też mieliśmy
title i działa to w porządku, czyli teraz, za każdym razem, kiedy najeżdżamy na taki element, jest tworzony
nowy div, przypisujemy mu tutaj wszystkie te właściwości. Jest on wstawiany do document.body, a na samej
górze zmienna globalTooltip, już nie ma wartości not tylko przypisujemy do niego ten tooltip.
Kiedy uciekamy myszą z elementu wykonujemy removeTooltip, bo to przypisaliśmy na mouseleave i globalTooltip,
po prostu zostaje usunięty.
I teraz za każdym razem, kiedy wejdziemy na kolejny element, kolejny typ jest tworzony i wstawiony do
body.
Działa to w bardzo fajny sposób, ten console.log możemy usunąć.
Jest jeszcze tylko jedna rzecz, która nam przeszkadza.
Mianowicie, kiedy najadę sobie na zdjęcie i poczekam chwilę, to koło mojej myszy pojawia się nadal dymek z title.
Chciałbym tego uniknąć.
I co możemy z tym zrobić.
Tutaj niestety nie możemy wykonać preventDefault.
Aby zapobiec domyślnej akcji przeglądarki. Natomiast możemy usunąć całkowicie atrybut title po najechaniu
na taki element.
Teraz, jak to zrobimy.
Otóż w showTooltip, na samym końcu odwołamy się do e.target, czyli do elementu na który najechaliśmy, będzie to np. zdjęcie.
Następnie removeAttribute title, ok, możemy go usunąć natomiast zobaczysz jaki problem się pojawi.
Najechałem,
jest wszystko ok, title się nie pojawia, bo go usunęliśmy.
Jeżeli zjadę z tego elementu i najadę raz jeszcze, mamy null, bo po kolejnym najechaniu, znowu tutaj
w showTooltip, próbujemy pobrać sobie title, a skoro go wcześniej usunąłem to ma on wartość null, czyli po
opuszczeniu myszy z naszego elementu wypadałoby z powrotem przypisać atrybut title.
A skąd możemy to wziąć.
Otóż w globalTooltip, tutaj, mamy zapisany nasz div, który wystawiliśmy do naszej strony i ten div w
textContent ma właśnie zapisaną treść naszego title, więc możemy tutaj go przypisać. Zanim go usuniemy,
możemy się odwołać do e.target. Pamiętaj, że e.target to będzie np. zdjęcie, z którego zjeżdżamy, czyli e.target,
następnie setAttribute title i skąd ten title weźmiemy.
No właśnie z tego Tooltip'a, który aktualnie się wyświetla, a więc odwołamy się do globalTooltip. Następnie
do textContent.
Teraz nam to zadziała, czyli po zjechaniu myszą z elementu z powrotem przypisze jego title. Powinno działać.
Jak widzisz, wszystko działa koło mojej myszy, koło kursora, nie pojawia się już ten tytuł bo go usunęliśmy,
a po zjechaniu z powrotem do zdjęcia powinno zostać, powinien zostać taki atrybut przypisany. Możemy to
sprawdzić w Elements.
Mamy tutaj zdjęcie, jak widzisz title znowu został przypisany, a więc po kolejnym najechaniu będzie to działać,
jak należy.
Wszystko działa bardzo fajnie, co możesz zobaczyć tutaj.
Natomiast jeszcze jedna rzecz, której nie zrobiłem, to przypisanie klasy hidden do naszego elementu tutaj
na początku, żeby on był ukryty.
Dzięki temu, kiedy na naszej stronie będzie on się pojawiał, będzie ładnie animowany, ale aby on się w
ogóle mógł pojawić, to będziemy musieli usuwać mu tę klasę hidden, którą tutaj nadałem.
Więc przejdźmy do showTooltip, a konkretnie do createTooltip.
I w tym miejscu usuniemy mu wcześniej nadaną klasę, poprzez classList.
remove hidden i teraz on będzie ładnie animowany, dlatego że w stylach zdefiniowałem
tutaj znowu transition w CSS3, czyli najeżdżamy i jak widzisz, on w taki fajny sposób jest animowany, kiedy
wchodzimy na taki element.
Tutaj również i na samym dole mamy jeszcze jeden element, który ma title.
Dzięki temu stworzyliśmy sobie świetny plugin Tooltip'a, który działa. Możemy taki skrypt komuś udostępnić
wszystkie funkcje, które są wewnątrz, na zewnątrz, nie będą widoczne, a na końcu tylko Tooltip, więc ktoś może
sobie taki skrypt tak jak ja tutaj pobrać, wstawić na stronę i następnie odwołać się do funkcji Tooltip
i przekazać wszystkie elementy, które go interesują.
Ja w tym przypadku przekazałem wszystkie elementy, które mają atrybut title, bo będzie nam on potrzebny.
Jak widzisz w bardzo fajny sposób można stworzyć ciekawy plugin Tooltip'a,
Czyli takiego dymku i wykorzystaliśmy tutaj bardzo wiele z tych metod i właściwości obiektów, które
pokazywałem ci w tym kursie.
Starałem się tak ułożyć te przykłady, aby jak najwięcej z nich wykorzystać i mam nadzieję, że teraz już
dobrze rozumiesz, jak działa sam język JavaScript,
a jak działa obiektowy model dokumentu
i jak to wszystko się ze sobą łączy.
To był już ostatni nasz projekt.
Teraz zapraszam Cię jeszcze na 10 krótkich lekcji z serii Tips and Tricks, z których również wyniesiesz wiele
ciekawych sztuczek.
Tooltip - init · 1 min
(function() {
function init(elems) {
}
window.t00ltip = init;
})();Tooltip - finish · 5 min
(function() {
var globalTooltip = null;
function assignEvents(elems, type, event) {
for(var i = 0; i < elems.length; i++) {
elems[i].addEventListener(type, event, false);
}
}
function createTooltip(text, options) {
var tooltip = document.createElement("div");
tooltip.className = "tooltip hidden";
tooltip.appendChild(document.createTextNode(text));
document.body.appendChild(tooltip);
tooltip.style.left = options.x + (options.w / 2) - (tooltip.offsetWidth / 2) + "px";
tooltip.style.top = (options.y - tooltip.offsetHeight - 10) + "px";
tooltip.classList.remove("hidden");
globalTooltip = tooltip;
}
function showTooltip(e) {
var options = {
w: e.target.offsetWidth,
x: e.target.offsetLeft,
y: e.target.offsetTop
};
var text = e.target.getAttribute("title");
createTooltip(text, options);
e.target.removeAttribute("title");
}
function removeTooltip(e) {
e.target.setAttribute("title", globalTooltip.textContent);
globalTooltip.parentNode.removeChild(globalTooltip);
}
function init(elems) {
assignEvents(elems, "mouseenter", showTooltip);
assignEvents(elems, "mouseleave", removeTooltip);
}
window.t00ltip = init;
})();Tooltip - script html · 3 min
<script>
t00ltip(document.querySelectorAll("[title]"));
</script>Tooltip - CSS · 1 min
@charset "utf-8";
* {
padding: 0;
margin: 0;
}
body {
font: 14px/18px Tahoma, Arial, sans-serif;
}
.container {
width: 80%;
margin: 30px auto;
overflow: hidden;
}
h1 {
padding-bottom: 20px;
margin-bottom: 40px;
border-bottom: 1px #D8D8D8 solid;
line-height: 1;
font-weight: normal;
color: #666666;
}
p {
margin-bottom: 30px;
line-height: 24px;
color: #4C4C4C;
}
img {
display: block;
width: 100%;
margin-bottom: 30px;
}
a {
text-decoration: none;
color: #00ACDE;
}
.tooltip {
padding: 10px 15px 12px 15px;
border-radius: 7px;
background-color: rgba(0, 0, 0, .8);
opacity: 1;
-webkit-transition: visibility 0.2s, opacity 0.2s;
transition: visibility 0.2s, opacity 0.2s;
position: absolute;
z-index: 9999;
font: 12px/1 Tahoma, Arial, sans-serif;
text-align: center;
color: #fff;
}
.tooltip:after {
content: "";
display: block;
width: 0;
height: 0;
margin-left: -6px;
border-style: solid;
border-width: 10px 6px 0 6px;
border-color: rgba(0, 0, 0, .8) transparent transparent transparent;
position: absolute;
left: 50%;
bottom: -10px;
}
.tooltip.hidden {
opacity: 0;
visibility: hidden;
}