Ta strona korzysta z ciasteczek cookies Rozumiem.
przechwytywanie i bąbelkowanie

Przechwytywanie i bąbelkowanie w JavaScript

23 października 2017, Kasia Ziomek-Zdanowicz

JavaScript, nauczyć się programować


W Internecie znajdziesz wiele materiałów o przechwytywaniu i bąbelkowaniu. Dla mnie największą wartość edukacyjną miał rejestr, który znalazłam tutaj i który opisuję w tym poście. Moim zdaniem rejestr bardzo dobrze ilustruje przechwytywanie i bąbelkowanie. Przekonaj się o tym czytając ten post.

Przechwytywanie i bąbelkowanie

Przechwytywanie i bąbelkowanie odnosi się do kolejności obsługi zdarzeń. Przechwytywanie i bąbelkowanie mają miejsce, gdy jeden element jest zagnieżdżony wewnątrz drugiego elementu oraz oba elementy zarejestrowały obserwatora tego samego zdarzenia.

Opis rejestru przechwytywania i bąbelkowania

Poniżej znajdziesz kilka pól. Jeżeli najedziesz na nie myszką pola zmienią kolor. Zmiany kolorów pomagają określić, które pole zostanie kliknięte. Nie mają znaczenia jeśli chodzi o działanie rejestru.

Pola są na swój sposób wyjątkowe:

  • Każde pole ma zarejestrowanych dwóch obserwatorów zdarzeń dla zdarzenia typu ‘click’. Jednego obserwatora w fazie przechwytywania i jednego w fazie bąbelkowania. Aby to uzyskać wykorzystałam opcjonalny parametr metody addEventListener: useCapture. Parametr useCapture jest typu boolean:
    • wartość true oznacza, że zdarzenie zostanie wywołane w fazie przechwytywania,
    • wartość false oznacza, że zdarzenie zostanie wywołane w fazie bąbelkowania. Jest to wartość domyślna.
  • Po kliknięciu pola, obserwator zdarzeń wywołuje procedurę obsługi zdarzeń, którą opisałam w jednym z kolejnych punktów. Ważne jest to, że wywoływana jest nie tylko procedura obsługująca zdarzenie klikniętego pola. Wywołane są również procedury obsługujące zdarzenia ‘click’ na przodkach klikniętego pola.
  • Funkcje obsługi zdarzeń są uruchamiane w określonej kolejności. Są trzy fazy:
    • Faza przechwytywania zaczyna się od procedury obsługi zdarzenia dołączonej do najbardziej zewnętrznego pola, a następnie przechodząc w dół uruchamia procedury kolejnych potomków i kończy na rodzicu klikniętego pola.
    • Faza target uruchamia procedury obsługi zdarzenia dołączone do klikniętego pola.
    • Faza bąbelkowania rozpoczyna się od procedury obsługi zdarzenia na rodzicu klikniętego pola, następnie przechodząc w górę uruchamia procedury kolejnych przodków i kończy się na najbardziej zewnętrznym polu.
  • Zauważ, że każde pole ma dwóch obserwatorów zdarzeń, po jednym dla fazy przechwytywania i dla fazy bąbelkowania. W przypadku klikniętego pola, obie procedury obsługi zdarzeń są uruchamiane w fazie target. W przypadku pozostałych pól dana procedura jest wywoływana albo w fazie przechwytywania, albo w fazie bąbelkowania (w zależności od tego, do której fazy został przypisany wywołujący ją obserwator zdarzeń).
  • Każda procedura obsługi zdarzeń dodaje wpis do rejestru, który opisuje zdarzenia ‘click’ obsługiwane przez tę procedurę. Wpis do rejestru zawiera następujące informacje:
    • Faza, w której miało miejsce zdarzenie. Ta informacja jest dostępne za pośrednictwem właściwości zdarzenia eventPhase. Fazy 1, 2, 3 to odpowiednio: faza przechwytywania, faza target oraz faza bąbelkowania.
    • ID pola, które jest właścicielem zdarzenia ‘click’, dla którego tworzony jest wpis rejestru. Ta informacja jest dostępne dzięki właściwości obiektu event: currentTarget.
    • ID klikniętego pola. ID dostępne jest dzięki właściwości obiektu event: target.
  • Kliknij kilka pól i przeczytaj rejestr.

Rejestr przechwytywania i bąbelkowania

Wyniki rejestru przechwytywania i bąbelkowania

Analizując rejestr, zobaczysz wszystko, co opisałam. Przyjrzyjmy się szczegółom.

Liczba wpisów rejestru

  • Jedno kliknięcie uruchomiło kilka procedur obsługi zdarzeń ‘click’. To ile procedur zostało uruchomionych zależy od tego, które pole jest kliknięte. A dokładniej, zależy to od liczby przodków, którzy mają zarejestrowanego obserwatora zdarzenia ‘click’ dla fazy przechwytywania/bąbelkowania.

Fazy zdarzeń

  • Rejestr zaczyna się od zdarzeń ‘click’ w fazie przechwytywania. Natępnie ma miejsce faza target i faza bąbelkowania.
  • Kolejność wpisów w rejestrze odpowiada kolejności, w której były uruchamiane procedury, czyli:
    • od najbardziej zewnętrznego pola, poprzez kolejne pola (faza przechwytywania), aż do klikniętego pola (faza target),
    • od klikniętego pola (faza target), poprzez kolejne pola, aż do najbardziej zewnętrznego pola (faza bąbelkowania).

Fazy przepływu zdarzeń

przechwytywanie i bąbelkowanie

Current target oraz target

  • Kolumna rejestru ‘current target’ zawiera pole, które zostało kliknięte oraz pola nadrzędne. To dlatego, że wszystkie pola mają zarejestrowanych obserwatorów zdarzenia ‘click’.
  • Kolumna ‘target’ w dzienniku zawiera tylko kliknięte pole. Dzieje się tak, ponieważ użytkownik może nacisnąć tylko jedno pole naraz.

Kod rejestru

Poniżej znajdziesz kod HTML i JavaScript rejestru.

Rejestr przechwytywania i bąbelkowania – kod HTML

<div class = "captureAndBubble">
  <div class = "cab-boxesContainer"></div>
  <div class = "cab-logContainer"></div>
</div>

Rejestr przechwytywania i bąbelkowania – główna funkcja: narysuj pola, dodaj obserwatorów zdarzeń, przygotuj rejestr

$(() => {
  let headers = ["faza", "opis", "current target", "target"],
  boxes,
  $logContainer = $(".cab-logContainer");

  //dodaj obserwatora zdarzeń do okna - wyczyść rejestr po kliknięciu w okno
  window.addEventListener("click", clearLog, true);

  drawBoxes(6);
  
  //dodaj obserwatorów zdarzeń do pól
  boxes = document.getElementsByClassName("cab-box");
  boxes = [...boxes];
  
  //--faza przechwytywania
  boxes.forEach(el => el.addEventListener("click", addLogEntry, true));
  
  //--faza bąbelkowania
  boxes.forEach(el => el.addEventListener("click", addLogEntry, false));

  drawLog(headers);
});

Rejestr przechwytywania i bąbelkowania – narysuj pola

function drawBoxes(n = 6) {
  //ustaw główne pole jako pole, do którego zostanie dołączone następne pole
  let $appendTo = $(".cab-boxesContainer");

  //narysuj n zagnieżdżonych pól
  for (let i = 0; i < n; i++) {
    
    //dołącz nowe pole do ostatniego załączonego pola
    $("<div/>", {
      class: "cab-box",
      id: "pole" + (i + 1)
    }).appendTo($appendTo);
    
    //ustaw ostatnie pole jako pole, do którego zostanie dodane kolejne pole
    $appendTo = $appendTo.children().last();
  }
}

Rejestr przechwytywania i bąbelkowania – przygotuj / wyczyść rejestr

function drawLog(headers) {
  let $logContainer = $(".cab-logContainer"),
  $header = "";

  //utwórz nagłówek i wnętrze rejestru
  $("<div/>", {
    class: "table-header"
  }).appendTo($logContainer);

  $("<div/>", {
    class: "table-body"
  }).appendTo($logContainer);
   
  //pobierz nagłówek rejestru
  $header = $(".table-header");

  //dodaj komórki do nagłówka rejestru
  headers.forEach((item) => {
    $("<div/>", {
      class: "table-header-cell",
      text: item
    }).appendTo($header);
  });
}

function clearLog() {
  //pobierz i wyczyść wnętrze rejestru
  let $body = $(".table-body");
  $body.html("");
}

Rejestr przechwytywania i bąbelkowania – procedura obsługi zdarzenia – dodaj wpis do rejestru

function addLogEntry(e) {
  
  ///pobierze wnętrze rejestru i szczegóły zdarzenia
  let $tableBody = $(".table-body"),
    ePhase = e.eventPhase,
    ePhaseDescription = "",
    eTarget = e.target.id,
    eCurrentTarget = e.currentTarget.id,
    dataList = [],
    $row;
  
  //opisz fazę
  switch (ePhase) {
    case 1:
      ePhaseDescription = "przechwytywanie";
      break;
    case 2:
      ePhaseDescription = "target";
      break;
    case 3:
      ePhaseDescription = "bąbelkowanie";
      break;
    default:
      ePhaseDescription = "unknown";
      break;
  }

  //dodaj wiersz do rejestru
  $("<div/>", {
    class: "table-row"
  }).appendTo($tableBody);

  //zachowaj wiersz w zmiennej
  $row = $tableBody.children().last();
  
  //ustaw listę szczegółów zdarzenia
  dataList = [ePhase, ePhaseDescription, eTarget, eCurrentTarget];
  
  ///dla każdego szczegółu dodaj komórkę do wiersza
  dataList.forEach((item) => {
    $("<div/>", {
      class: "table-cell",
      text: item
    }).appendTo($row);
  })
}

Podsumowanie i pytanie

Mam nadzieję, że rejestr pomoże komuś zrozumieć przechwytywanie i bąbelkowanie tak jak mi pomógł. Jeśli tak, daj mi znać.

Na koniec możesz sprawdzić, czy wiesz, dlaczego w powyższym kodzie obserwator zdarzenia okna jest dodany do fazy przechwytywania.

Dlaczego ten obserwator zdarzeń został dodany do fazy przechwytywania?

window.addEventListener("click", clearLog, true);


Komentarze

Jeszcze nikt nie skomentował tego wpisu. 

Napisz pierwszy komentarz.


Napisz komentarz

Twój adres email nie zostanie opublikowany.

Wszystkie pola są wymagane.