JavaScript & JQuery: Eventy – przechwytywanie, bąbelkowanie i delegacja

Przypisywanie i uruchamianie eventów

Najprostszą metodą tworzenia zdarzeń w obrębie strony internetowej jest przypisywanie akcji (funkcji) bezpośrednio do odpowiednich elementów strony, np.

Każdy z powyższych przykładów robi dokładnie to samo (aczkolwiek nie tak samo) – nadaje event, w wyniku którego po naciśnięciu elementu #przycisk w konsoli pokaże się napis kliknięto. Tym prostym sposobem można przypisać zdarzenia wszystkim elementom, które powinny zmieniać stan strony. To rozwiązanie nie rodzi trudności, kiedy elementy posiadające zdarzenie są rozłączne:

natomiast kiedy jeden zawiera się w drugim, jak przedstawiono poniżej

rodzi się pytanie: Które zdarzenie powinno uruchomić się najpierw w przypadku kliknięcia myszką na elemencie .przycisk-2? Czy najpierw zdarzenie dla  .przycisk-1 a później dla  .przycisk-2 czy też odwrotnie?

W latach 90. twórcy konkurujących ze sobą przeglądarek (Netscape i IE) doszli do dwóch, całkowicie innych wniosków, w wyniku czego powstały dwa podejścia: przechwytywanie i bąbelkowanie (ang. odpowiednio: capturing, bubbling). Podejście Netscape było następujące: najpierw odpalamy zdarzenie na elemencie zawierającym ( .przycisk-1 ) a później na elemencie zawieranym ( .przycisk-2 ) – przechwytywanie. Podejście Microsoftu było odwrotne: najpierw odpala się event elementu zawieranego ( .przycisk-2), a dopiero potem elementu zawierającego ( .przycisk-1 ) – bąbelkowanie. Oba schematycznie zobrazowano na widoku 3D obu przycisków; poniżej.

capture-bubble2

Wcześniejsze wersje IE (do 8 włącznie nie posiadały opcji przechwytywania) pozostałe przeglądarki natomiast implementowały oba podejścia. Organizacja W3C w kwestii obydwu rozwiązań postanowiła zająć stanowisko pośrodku i w specyfikacji (z 2000 roku) model zdarzeń przewiduje najpierw fazę przechwytywania a następnie fazę bąbelkowania. Należy tu też zwrócić uwagę, że w przypadku przypisywań typu el.onclick = function(){} domyślnie używane jest bąbelkowanie. Podobnie sprawa ma się z JQuery, za pomocą którego możemy korzystać tylko z bąbelkowania.

Bąbelkowanie

W dalszej części to opracowanie skupia się tylko na JQuery i na następującym wycinku drzewa DOM:

Jeśli do tych elementów dodamy następujące zdarzenia:

I klikniemy myszką w obrębie elementu .przycisk-2 , to w konsoli zobaczymy następujące wpisy:

Jeżeli bąbelkowanie nie jest pożądane, to można wywołać metodę  stopPropagation()  na obiekcie event przekazanym do funkcji. Bezpiecznie jest zrobić to na samym początku funkcji. Zmieniamy zdarzenie .przycisku-2 :

i teraz w konsoli po kliknięciu na  .przycisk-2  pojawi się tylko:

Uwaga! Podobny efekt uzyskamy jeżeli funkcja zwróci false ( return false;), ale tak robić nie należy, ponieważ oprócz zatrzymania bąbelkowania do skutku nie dojdzie domyślna akcja elementu (np. wysłanie formularza). Może to też przeszkodzić przy delegowaniu (o tym dalej). Jeżeli chcemy zatrzymać bąbelkowanie i dodatkowo zapobiec odpaleniu domyślnej akcji, to najlepiej jawnie użyć do tego pary metod stopPropagation() i preventDetault().

Krótka historia metod odpalania eventów w JQuery

W pierwszej wersji biblioteki event można było dołączyć za pomocą metody  bind()  albo też aliasów takich jak click(). Praktyka pokazała, że tak nadawane zdarzenia w przypadku stron bardziej rozbudowanych były niewygodne. Np. jeżeli za pomocą AJAXu strona doczytywała fragment drzewa DOM, to należało na nowo odpalić wszystkie przypisania eventów dla elementów, które zostały dynamicznie dodane. Pojawił się plugin dodający metodę  live()  – metoda działała analogicznie do bind() , ale w przypadku dynamicznie dodanych elementów nie trzeba jej było ponownie odpalać. Po pewnym czasie metoda ta stała się częścią JQuery. W czasie jej pojawienia się w bibliotece dodano jednocześnie delegate() , która pozwalała delegować eventy (o tym dalej) i uzyskiwać efekty podobne do live() . Nadeszła wersja 1.7.  live()  zostało oznaczone jako deprecated (całkowicie zniknęło w 1.9), a pojawiła się metoda on() . Pozwala ona tak samo jak  bind()  przypisać zdarzenie do elementu, ale poza tym w pewnym układzie argumentów umożliwia delegowanie. Ta historia ma na celu zobrazowanie przemian w JQuery, a nie etapy wymyślania delegacji, bo ta nie wymaga wymienionej biblioteki.

Delegacja

Bąbelkowanie umożliwiło delegowanie zdarzeń. Event (np. click) posiada informację (odwołanie) o elemencie, “w którym został stworzony”. Wspomniana referencja jest dostępna za pomocą właściwości  target  (w IE do wersji 8 włącznie właściwość ta kryła się pod nazwą srcElement). Dzięki tej właściwości i dzięki currentTarget możliwe stało się przypisanie zdarzenia np. do  .przycisku-1  i uruchomienie go w momencie kliknięcia na .przycisk-2 . Taki właśnie proces nazywamy delegacją. Ogólnie delegacja (delegowanie) to uruchomienie zdarzenia na elemencie wewnętrznym, którego obsługa jest wykonywana dopiero przy rozpatrywaniu tego zdarzenia w elemencie zewnętrznym.

Posłużmy się wcześniejszym fragmentem DOM:

i przeanalizujmy wykorzystanie delegacji, za pomocą metody on() . Skorzystamy z wywołania do delegowania, czyli następującego wzorca  $('selektorRodzica').on('zdarzenie', 'selektorPotomka', funkcja);  :

Zgodnie z założeniami, klikamy na element wewnętrzny, a zdarzenie rozpatrywane jest na poziomie elementu zewnętrznego. Kliknięcie na  .przycisk-1 nie wywołuje żadnej akcji. Analogiczny efekt uzyskalibyśmy przypisując zdarzenie do document:

Użycie  return false;  jak wspomniano wcześniej przerywa bąbelkowanie, a co za tym idzie potrafi przerwać też delegację, zapobiegając wykonaniu określonych akcji. Znalezienie błędu może być skomplikowane, dlatego lepiej przerywanie łańcucha zdarzeń robić bardziej jawnie z wykorzystaniem wspomnianych wyżej metod.

W przypadku skorzystania z delegacji i bezpośredniego przypisania zdarzenia, najpierw wykona się to drugie.

Należy nadmienić, że w przypadku delegacji należy trochę inaczej definiować funkcje obsługujące – np. jeżeli każdy element wewnętrzny ma po kliknięciu pokazywać alert z kolejną liczbą to, w przypadku zwykłego definiowania eventów, można w pętli przypisać dla każdego elementu odpowiednie zdarzenie. Natomiast jeżeli delegujemy, to tworzymy jedno zdarzenie w którym można by wykorzystać np. atrybut  data-number  elementu, który przechowywałby liczbę:

Korzystając z delegowania można uprościć zarządzanie zdarzeniami. Przyjmijmy, że na wykonywanej stronie należy oprogramować przycisk, który może być aktywny lub nie. Przycisk jest aktywny, jeżeli posiada klasę active. Bez użycia delegowania można w funkcji obsługującej zdarzenie sprawdzać czy element posiada klasę i w zależności od tego wykonywać odpowiedni kod ALBO używać metod  bind()unbind() by w odpowiednich momentach dodawać i usuwać obsługę zdarzeń. W przypadku delegowania można wykonywać odpowiednie instrukcje osobnymi zdarzeniami np.:

Powyższy przykład nie wydaje się być dużo bardziej korzystny, ale jeżeli działanie ma zależeć od kilku elementów, które są wyżej w hierarchii, to powyższy sposób definiowania zdarzeń będzie przejrzystszy i prostszy do zmiany. Może posłużmy się przykładem następującym: po pierwsze wyobraźmy sobie, że przedmioty można opisać jak tagi HTML, a ich stan jako klasy. Pomińmy kwestię tego co zmienia stan. Załóżmy, że musimy oprogramować chowany dach kabrioletu w zależności od pogody, korzystając z delegowania można by zdarzenia zdefiniować następująco:

Zalety delegacji:

  • Dla wielu potomków tworzymy jedną obsługę zdarzenia zamiast tworzyć ich wiele. Przechowywanie jednej obsługi zdarzenia jest zdecydowanie lepsze niż np. 10 tysięcy identycznych funkcji obsługujących.
  • Nie trzeba martwić się o obsługę zdarzeń elementów dodawanych dynamicznie.
  • Łatwiejsze zarządzanie zdarzeniami, dla określonych stanów struktury DOM – zdecydowanie prostsze w przypadku wielu zależnych elementów o różnych stanach.

Wady delegowania:

  • Duża liczba zdarzeń zdefiniowana na document może spowolnić działanie strony, bo każde (lub większość) zdarzenie będzie testowane – czy nie powinna się uruchomić przypisana do niego funkcja. Można się przed tym co prawda uchronić korzystając z definiowania delegacji na bliższych rodzicach elementów, ale stworzone dynamicznie elementy będą wymagały dodatkowego przypisania eventów.

Podsumowanie

Korzystanie z delegowania niesie ze sobą wiele korzyści zarówno pod względem zużycia pamięci przeglądarki, uproszczenia obsługi stron dynamicznych, jak i zwiększenia przejrzystości kodu. To i niewielka liczba wad są dobrą rekomendacją do stosowania delegacji do oprogramowywania stron internetowych.

Źródła

Historia odwiedzanych stron a historia przeglądarek

Używanie trybu prywatnego/incognito (potocznie zwanego trybem porno) w przeglądarce lub czyszczenie pamięci przeglądarki nie jest wystarczającym sposobem na pozbycie się historii odwiedzanych stron. Windows posiada bufor programu rozpoznawania nazw DNS, który zapamiętuje odwiedzane strony.

Odwiedzane strony można wyświetlić w konsoli (<Win>+R, a potem cmd) za pomocą polecenia:

Gdyby ilość wyników była duża można wspomóc się notatnikiem, w konsoli:

Czyszczenie bufora programu rozpoznawania nazw DNS można wykonać poleceniem:

localhost a automatyczne domeny

Developując lokalnie na Windowsie większą ilość projektów php (lub html) można uprościć sobie życie korzystając z automatycznego tworzenia domen. Normalnie trzeba ustawić sobie domenę w pliku hosts, a następnie przygotować virtualkę z odpowiednią ścieżką i zrestartować serwer. Dzięki opisanym w dalszej części instrukcjom można te czynności zautomatyzować. Załóżmy, że wszystkie projekty testujemy pod domeną .local, np. blog.local. Po wykonaniu opisanych dalej czynności trzeba będzie tylko utworzyć katalog z plikami projektu (np. kermit) a od razu dostępna będzie domena utworzona z nazwy katalogu i domeny local (nawiązując do poprzedniego przykładu: kermit.local).

Poniższe instrukcje dotyczą Xamppa, ale można je pewnie bez problemów zastosować z innymi pakietami (np. Wamp).

    1. Zmiany w serwerze www
      • Plik konfiguracji virtualhostów  (<ścieżka_do_xamppa>\apache\conf\extra\http-vhost.conf) na końcu dodajemy wpis:
        • W przypadku xamppa VirtualDocumentRoot to:
      • Włączamy moduł mod_vhost_alias
        • W pliku pliku <ścieżka_do_xampp>/apache/conf/httpd.conf trzeba odkomentować (usunąć #) linię:
      • Restartujemy serwer www (Apache’a)
    2. Czyszczenie bufora DNS
      • W linii poleceń Windowsa (<Win>+R, a potem cmd ) wpisujemy ipconfig /flushdns
    3. Instalacja lokalnego proxy DNS
      • Pobieramy i instalujemy program Acrylic DNS Proxy (308)(freeware, oficjalny download)
      • Po instalacji uruchamiamy Start > Wszystkie programy > Acrylic DNS Proxy > Config > Edit Acrylic Host File
      • Na końcu w/w pliku dopisujemy 127.0.0.1 *.local
    4. Zmiana serwera DNS
      • Start > Panel sterowania > Sieć i internet > Wyświetl stan sieci i zadania > Zmień ustawienia karty sieciowej
      • Wybieramy używane przez nas połączenie sieciowe i wchodzimy do Właściwości
      • W oknie wybieramy TCP/IPv4 i klikamy Właściwości
      • Ustawiamy Preferowany serwer DNS na 127.0.0.1

Edycja userscriptów w przeglądarce

Firefox (wtyczka Greasemonkey)

W celu edycji skryptu należy:

  • wejść na stronę, na której uruchamiany jest skrypt
  • rozwijamy menu Greasmonkey (górne menu, ikona głowa małpki, strzałka)
  • klikamy Prawym Przyciskiem Myszy na nazwę skryptu
  • (przy pierwszej edycji trzeba będzie wybrać edytor tekstu, który zostanie przypisany do edycji skryptów)
  • userscript zostanie otworzony w wybranym wcześniej edytorze tekstów

Po zapisaniu pliku w edytorze i odświeżeniu strony Firefox automatycznie uruchomi zmieniony skrypt.

Chrome

Chrome bez dodatkowych wtyczek nie pozwala na tak prostą zmianę skryptu jak Firefox (z zainstalowaną wtyczką Tampermonkey już tak). W celu edycji trzeba:

  • wejść na stronę rozszerzeń chrome://extensions/ (Menu > Narzędzia > Rozszerzenia)
  • znaleźć skrypt do zmiany i odczytać jego Identyfikator (ciąg liter, np. ibdpkeeiolggnanjgonconhdmocechea)
  • przejść do katalogu, w którym trzymane są ustawienia Chrome’a i wtyczki (na Windowsie 7: C:\Users\<nazwa_użytkownika>\AppData\Local\Google\Chrome\User Data\Default\Extensions\<Identyfikator_skryptu_odczytany_wcześniej>\<numer_wersji>\)
  • otworzyć plik script.js edytorem tekstu

Uwaga. Zapisanie pliku skryptu nie wywoła zmiany w przeglądarce. W celu zaczytania userskryptu na nowo należy ponownie wejść na stronę rozszerzeń chrome://extensions/ i za pomocą checkboxa wyłączyć go, a potem włączyć ponownie.

Opera (od wersji 20, wtyczka Violentmonkey)

  • klikamy na ikonę wtyczki (głowa małpy, prawy górny róg przeglądarki)
  • następnie Zarządzaj skryptami
  • klikamy Edytuj przy wybranym skrypcie
  • po dokonaniu zmian wystarczy kliknąć Zapisz (po odświeżeniu strony skrypt zostanie automatycznie zaczytany na nowo)

 

 

 

 

Zmiana rozszerzenia pliku w Windowsie

Rozszerzenie pliku w Windowsie (testowane na Windows 7, ale w innych jest analogicznie) zmienia się w następujący sposób:

  • Klikamy Start > Komputer
  • Naciskamy klawisz Alt, żeby pokazało się menu u góry okna
  • Otwieramy okno Narzędzia > Opcje folderów
  • Przechodzimy na kartę Widok
  • Odznaczamy opcję Ukryj rozszerzenia znanych plików i klikamy Ok
  • Przechodzimy do lokalizacji pliku, którego rozszerzenie chcemy zmienić i klikamy na jego nazwie Lewym Klawiszem Myszy
  • Wybieramy Zmień nazwę
  • Jeśli pojawi się okno z pytaniem: “Czy na pewno chcesz zmienić rozszerzenie?” to potwierdzamy kliknięciem na Tak

W razie pytań zostaw komentarz.

Modlitwa programistów

Panie dziękuję Ci za kolejny dzień,
za wszystkie jego wyzwania
i możliwość kreowania nowych światów.
Panie proszę Cię o jasność umysłu
bym potrafił znaleźć rozwiązania napotkanych problemów
i sprawnie poruszać się w hiperprzestrzeni kodu,
a także o dalekowzroczność bym widział wszystkie opcje.

Amen.

Włączanie i wyłączanie dźwięku skrótem klawiszowym w Windows 7

Użytkownikom komputerów z systemem Windows (testowane w Windows 7), którzy nie posiadają klawiszy multimedialnych na klawiaturze przychodzi z pomocą program NirCmd (freeware) do pobrania ze strony producenta  (lub stąd NirCmd (425)NirCmd (64-bit) (399)).

Instalacja:

  • Po pobraniu rozpakowujemy archiwum zip
  • Uruchamiamy program nircmd z uprawnieniami administratora (lewy przycisk myszy na programie > Uruchom jako administrator)
  • W oknie programu klikamy Copy To Windows Directory, a następnie potwierdzamy: Tak.
  • Zamykamy program

Tworzenie skrótu wyłączającego/włączającego dźwięk:

  • Uruchamiamy konsolę (cmd)
  • Odpalamy polecenie:
  • Na pulpicie został stworzony skrót. Po kliknięciu dźwięk zostanie wyciszony lub włączony – poziom dźwięku zostanie ustawiony odwrotny do wcześniejszego.
  • Do tak utworzonego skrótu można stworzyć skrót klawiszowy w sposób standardowy (Prawy przycisk myszy > Właściwości > Klawisz skrótu) ALBO przeciągnąć ikonę na pasek zadań (proponuję na pierwsze miejsce) i używać skrótu <symbol_windows> + 1 (lub innej liczby w zależności, na której pozycji paska istnieje skrót).

Wyszukiwanie ciągu znaków w MSSQL

Chcąc wyszukać słowo/string we wszystkich tabelach w MSSQL można posłużyć się procedurą: