Îmblanzirea JavaScript în Drupal (Include întrebări frecvente)

Publicat: 2023-02-07

Experiențele web interactive oferă utilizatorilor o experiență mai captivantă și mai plăcută. Aceasta duce la o satisfacție sporită a utilizatorilor și la o percepție pozitivă a unui site web. De exemplu, un formular care oferă feedback și validare instantanee, în loc să-l facă pe utilizator să aștepte reîmprospătarea paginii, poate îmbunătăți semnificativ experiența utilizatorului.

JavaScript joacă un rol important în Drupal, oferind mijloacele de a crea experiențe dinamice și interactive pentru utilizatorii de pe front-end-ul unui site web Drupal. Le permite dezvoltatorilor să modifice comportamentul anumitor elemente dintr-o pagină, cum ar fi formulare, link-uri sau orice alte elemente DOM, fără a fi nevoie să reîmprospăteze întreaga pagină. Comportamentele Drupal sunt funcții JavaScript care sunt executate atunci când anumite evenimente au loc pe o pagină. Comportamentele facilitează pentru dezvoltatori să întrețină și să actualizeze un site, deoarece nu trebuie să schimbe niciun cod HTML subiacent. Află tot ce ai vrut să știi despre Comportamentele Drupal în articol.

Îmblanzirea JavaScript în Drupal

Ce sunt comportamentele Drupal?

Drupal.behaviors este un obiect din structura Javascript din Drupal, care ne permite să atașăm funcții care să fie executate la anumite momente în timpul execuției aplicației. Este apelat când DOM-ul este complet încărcat, dar aceste comportamente pot fi apelate din nou. Documentația oficială JavaScript a Drupal sugerează că modulele ar trebui să implementeze JavaScript prin atașarea logicii la Drupal.behaviors .

De ce avem nevoie de comportamente Drupal?

Avantajul Comportamentelor este că sunt reaplicate automat oricărui conținut care este încărcat prin AJAX. Ele pot fi apelate oricând cu un context care reprezintă noi completări sau modificări ale DOM. Acest lucru este mai bun decât $(document).ready() sau documentul DOMContentLoaded unde codul este rulat doar o singură dată.

Când sunt comportamentele Drupal nedorite?

Comportamentele Drupal nu sunt întotdeauna soluția perfectă pentru scrierea Javascript în Drupal. În unele cazuri, după cum se precizează mai jos, comportamentele Drupal nu sunt deloc necesare!

  • Când trebuie să executăm un cod care nu afectează DOM. De exemplu. Inițializarea unui script extern precum Google Analytics
  • Când o operațiune JS trebuie efectuată pe DOM o singură dată, știind că elementul va fi disponibil când se încarcă pagina (Acest scenariu este diferit de utilizarea Once).

Când se numesc Comportamentele Drupal?

  • După ce o suprapunere de administrare a fost încărcată în pagină.
  • După ce API-ul AJAX Form a trimis un formular.
  • Când o solicitare AJAX returnează o comandă care modifică HTML, cum ar fi ajax_command_replace() .

Alte ori când sunt invocate Comportamentele Drupal

  • CTools îl apelează după ce a fost încărcat un modal.
  • Media îl apelează după ce browserul media a fost încărcat.
  • Panels îl numește după ce editarea la locul său a fost finalizată.
  • Views îl apelează după încărcarea unei noi pagini care utilizează AJAX.
  • Vizualizări Încărcați mai multe îl apelează după încărcarea următoarei bucăți de articole.
  • JavaScript din modulele personalizate poate apela Drupal.attachBehaviors() atunci când adaugă sau schimbă părți ale paginii.

Scrierea codului fără comportamente Drupal

În acest cod, adăugăm un ascultător de evenimente de clic la clasa .views-row care calculează de câte ori facem clic pe acest rând. Dar se adaugă o singură dată elementelor care vin în DOM în timpul încărcării inițiale a paginii. După ce faceți clic pe Încărcați mai multe și încărcați mai multe articole, ascultătorul de clic nu funcționează pe elementele nou încărcate.

 // No Drupal Behaviors (function () { let header = document.querySelector(".food-list-header"); if (header) { let greatFoodSpan = document.createElement("span"); greatFoodSpan.textContent = "Get ready for great food!!!!!!"; header.append(greatFoodSpan); } // Add the event listener for each click on the food let foods = document.querySelectorAll(".views-row"); foods.forEach((food) => { food.addEventListener("click", () => { let foodCounter = food.querySelector(".food-click-counter"); let timesClicked = parseInt(foodCounter.textContent.trim()); foodCounter.textContent = ++timesClicked; }); }); })(); 
ascultător de evenimente

Cum folosim comportamentele Drupal?

Răspuns: Folosind metoda atașării

Lucruri de amintit:

  • Noul obiect trebuie să aibă cel puțin o metodă de atașare.
  • Ori de câte ori Drupal.attachBehaviors este apelat, acesta va itera prin toate obiectele de comportament și va apela metodele de atașare ale acestora.

Adăugarea comportamentului Drupal la codul nostru

După adăugarea Comportamentelor Drupal, codul arată cam așa.

 (function (Drupal) { Drupal.behaviors.exampleBehaviour1 = { attach: (context, settings) => { // Add a delicious text to the top of the document let header = document.querySelector(".food-list-header"); // jQuery Equivalent // $(".food-list-header"); if (header) { let greatFoodSpan = document.createElement("span"); greatFoodSpan.textContent = "Get ready for great food!!!!!!"; header.append(greatFoodSpan); } // Add the event listener for each click on the food let foods = document.querySelectorAll(".views-row"); foods.forEach((food) => { food.addEventListener("click", () => { let foodCounter = food.querySelector(".food-click-counter"); let timesClicked = parseInt(foodCounter.textContent.trim()); foodCounter.textContent = ++timesClicked; }); }); }, }; })(Drupal);

Dar ceva ciudat apare în partea de sus când facem clic pe Încarcă mai mult:

comportament

Acest lucru se datorează faptului că comportamentul Drupal este numit de multe ori și, ulterior, obținem un comportament neintenționat.

Ce este Context în „context Drupal”?

  • La apelarea metodei attach pentru toate comportamentele, Drupal transmite un parametru de context .
  • Parametrul de context care este transmis poate oferi adesea o idee mai bună despre ce element DOM este procesat.
  • În timpul încărcării inițiale a paginii, acesta va fi documentul HTML complet; în timpul apelurilor ulterioare, acestea vor fi doar elementele care sunt adăugate în pagină sau care vor fi modificate.

Cum se adaugă Context?

Problema anterioară poate fi rezolvată folosind parametrul de context furnizat de Drupal Behaviors. În acest caz, prima dată când pagina se încarcă, obținem întregul document HTML ca context și atunci atașăm antetul. Pentru operațiuni ulterioare, partea din cod va fi afectată de Comportamentele Drupal și, prin urmare, acea parte a codului este controlată în siguranță.

 (function (Drupal) { Drupal.behaviors.exampleBehaviour2 = { attach: (context, settings) => { // Add a delicious text to the top of the document. // The context parameter now can be used for adding // certain functionality which removes unwanted repeatability let header = context.querySelector(".food-list-header"); // jQuery Equivalent // $(".food-list-header", context); if (header) { let greatFoodSpan = document.createElement("span"); greatFoodSpan.textContent = "Get ready for great food!!!!!!"; header.append(greatFoodSpan); } // Add the event listener for each click on the food let foods = context.querySelectorAll(".views-row"); foods.forEach((food) => { food.addEventListener("click", () => { let foodCounter = food.querySelector(".food-click-counter"); let timesClicked = parseInt(foodCounter.textContent.trim()); foodCounter.textContent = ++timesClicked; }); }); }, }; })(Drupal);

Din nou, există un comportament ciudat când facem clic pe Încărcare mai mult . Produsele alimentare care au fost încărcate inițial funcționează bine. Dar după ce faceți clic pe Încărcare mai mult, elementele noi primesc ascultătorul de clic și funcționează normal. Dar elementele încărcate inițial fac ascultătorul atașat din nou și, dacă faceți clic pe ele, de mai multe ori se apelează evenimentul de clic!

Incarca mai mult

Când încep comportamentele Drupal să se comporte prost?

  • Scrierea tuturor ascultătorilor de evenimente în comportamentele Drupal fără a utiliza Once și Context.
  • Declararea funcțiilor nedorite în cadrul comportamentelor Drupal, ceea ce duce la redeclararea funcțiilor de fiecare dată când este apelată metoda attach.

„O dată” la salvare

  • Once asigură că ceva este procesat o singură dată prin adăugarea unui atribut data-once într-un element DOM după ce codul a fost executat.
  • Dacă comportamentul este apelat din nou, elementul cu atributul data-once este omis pentru o execuție ulterioară.
  • Once este o implementare modernă a jQuery.once (care este un efort de a te îndepărta de jQuery)
  • Odată, în combinație cu contextul, controlează întreaga funcționalitate perfect așa cum avem nevoie.

Adăugarea Once pentru a remedia ascultătorii de evenimente din codul nostru

 (function (Drupal, once) { Drupal.behaviors.exampleBehaviour3 = { attach: (context, settings) => { once("food-header-initialized", ".food-list-header", context).forEach( (header) => { let greatFoodSpan = document.createElement("span"); greatFoodSpan.textContent = "Get ready for great food!!!!!!"; header.append(greatFoodSpan); } ); // jQuery Equivalent // $(".food-list-header", context).once("food-header-initialized", function (header) { // // }); // Add the event listener for each click on the food once("food-initialized", ".views-row", context).forEach((food) => { food.addEventListener("click", () => { let foodCounter = food.querySelector(".food-click-counter"); let timesClicked = parseInt(foodCounter.textContent.trim()); foodCounter.textContent = ++timesClicked; }); }); }, }; })(Drupal, once);
date o dată

Acum totul funcționează conform intenției. Obținem un atribut data-once pentru elementele în care sunt atașați ascultătorii de evenimente și elementele nou încărcate și elementele încărcate anterior funcționează corect.

Metoda Need for Detach

Metoda Detach acționează ca un anti-erou (nu rău), eliminând orice am făcut în metoda atașării. Orice cod din metoda detașare va fi apelat ori de câte ori conținutul este eliminat din DOM. Acest lucru ne ajută să ne curățăm aplicația. De exemplu, metoda Detach ne permite să eliminăm ascultătorii de evenimente nedoriți care consumă resurse precum o situație de sondare continuă.

Exemple de Detach

Să presupunem că avem de completat un formular ajax și că folosim un cronometru pentru a arăta timpul scurs. Folosim setTimeOut pentru a gestiona temporizatorul. Înregistrăm acest temporizator în consolă pentru monitorizare.

 (function (Drupal, once) { let counter = 0; Drupal.behaviors.exampleBehaviour4 = { attach: (context, settings) => { once("timer-initalized", ".contact-timer", context).forEach((ele) => { const timer = context.querySelector(".contact-timer-sec"); timer.textContent = counter; // Set the timer for user to see the time elapsed setInterval(() => { console.log("This is logging"); const timer = document.querySelector(".contact-timer-sec"); timer.textContent = ++counter; }, 1000); }); }, }; })(Drupal, once);
setați timeout

La trimiterea formularului, cronometrul de pe DOM este eliminat, dar consola începe să trimită o eroare. Acest lucru se datorează faptului că elementul asupra căruia setTimeOut acționează a fost eliminat din DOM:

desprinde

Pentru a evita acest lucru, putem folosi metoda detașării astfel:

 (function (Drupal, once) { let counter = 0; let intervalStopper; Drupal.behaviors.exampleBehaviour4 = { attach: (context, settings) => { // Set the timer for user to see the time elapsed once("timer-initialized", ".contact-timer", context).forEach((ele) => { const timer = context.querySelector(".contact-timer-sec"); timer.textContent = counter; intervalStopper = setInterval(() => { const timer = document.querySelector(".contact-timer-sec"); timer.textContent = ++counter; console.log("This is logging"); }, 1000); }); }, // Clear the timer on confirmation detach: (context, settings, trigger) => { const timer = context.querySelector(".contact-timer-sec"); if (trigger == "unload" && timer) { clearInterval(intervalStopper); } }, }; })(Drupal, once);

Acest lucru elimină temporizatorul la descărcare și, după cum se vede din logger, eroarea nu apare.

JS Demo

Expresii de funcție invocate imediat (IIFE) - Wrapper-ul pentru JS

Am folosit IIFE pentru a scrie codul nostru Drupal. Parantezele inițiale de deschidere definesc o funcție anonimă care ajută la prevenirea sferei de aplicare a funcției să polueze sfera globală a întregii aplicații. Puteți transmite argumente funcției dvs. anonime incluzându-le ca argumente la sfârșitul definiției funcției.

Acest lucru ne ajută, de asemenea, să creăm un spațiu de nume a parametrilor oricum dorim să fie folosiți.

Exemplu:

 // Function name crisis!!!! // The function is vulnearble to // be replaced by some other function function someFunction() { // Some code for this function } (function (Drupal) { // Function name crisis averted! function someFunction() { // Some code for this other function } Drupal.behaviors.exampleBehaviour6 = { attach: (context, settings) => { someFunction(); }, }; })(Drupal);

Gânduri finale

Implementarea comportamentelor Drupal permite interactivitate dinamică, interacțiune simplificată a utilizatorului, feedback îmbunătățit al utilizatorilor, dezvoltare eficientă și experiență generală îmbunătățită a utilizatorului site-ului dvs. Comportamentele Drupal sunt flexibile și modulare, prin aceea că pot fi executate de mai multe ori pe o pagină, pot suprascrie și extinde comportamentul existent și pot fi reaplicate automat oricărui conținut încărcat prin Ajax.

Căutați o agenție de dezvoltare Drupal care să vă ajute să construiți experiențe web interactive, profitând la maximum de Drupal? Ne-ar plăcea să vorbim!