Eseguire JavaScript nel tema
Utilizzando $(document).ready(function () {} il codice nella funzione viene eseguito solo al caricamento iniziale della pagina, invece con i behaviors viene eseguito anche al caricamento di nuovo contenuto dopo una chiamata AJAX.
Drupal.behaviors
Con l'utilizzo di Drupal.behaviors il codice JavaScript viene eseguito solo quando il DOM è stato caricato interamente e ogni volta che viene caricato nuovo contenuto via AJAX. Il nome di ciascun behavior deve essere univoco e in camelCase:
(function($, window, Drupal) { //per usare JQuery dichiararlo come dipendenza nel file .libraries.yml
Drupal.behaviors.nomeTemaClick = {
attach: function(context, settings) { //all'inizio context è document, dopo una chiamata AJAX è il contenuto aggiunto
// aggiungere once()
$('.example', context).click(function() {
$(this).next('ul').toggle('show');
});
$(context).find('a.cool-link').on('click', function() {
console.log("Link cliccato");
});
},
detach: function(context, settings, trigger) {
if (trigger === 'unload') {
// codice da eseguire quando l'elemento è rimosso dalla pagina
}
}
};
})(jQuery, window, Drupal);
La funzione attach()
Il parametro context
Al primo caricamento della pagina il parametro context equivale all'oggetto document, al caricamento di nuovo contenuto dopo una chiamata AJAX context contiene il nuovo contenuto, in questo modo non è necessario scansionare l'intero DOM per agganciare eventi ai selettori.
AJAX e riesecuzione dei behaviors
La funzione once()
La funzione detach()
Dipendenze JavaScript nel .libraries.yml
global-styling:
version: 1.x
js:
js/custom.js: {}
dependencies:
- core/jquery
- core/jquery.once
Passaggio di dati da PHP a JavaScript
Passare dati da PHP a JavaScript con drupalSettings
Se è necessario passare delle variabili da PHP a JavaScript si usa la libreria drupalSettings, che deve essere indicata come dipendenza nel file .libraries.yml.
Nel file .theme:
<?php
/**
* Implements hook_page_attachments_alter().
*/
function nome_tema_page_attachments_alter(array &$attachments) {
$account = \Drupal::currentUser();
if ($account->isAuthenticated()) {
// includiamo la libreria nella pagina solo se l'utente è loggato
$attachments['#attached']['library'][] = 'nome_tema/nome_libreria';
// facciamo in modo che nel file JavaScript esista la variabile drupalSettings.nome_tema.name
$attachments['#attached']['drupalSettings']['nome_tema']['name'] = $account->getDisplayName();
//dato che il nome varia per ogni utente bisogna impostare la cache in modo che ogni utente veda il proprio nome
$attachments['#cache']['contexts'][] = 'user';
}
}
?>
Nel file della libreria JavaScript:
(function (Drupal, drupalSettings) {
if (drupalSettings.nome_tema.name) {
var siteName = document.getElementsByClassName('site-branding__name')[0];
siteName.getElementsByTagName('a')[0].innerHTML = 'Ciao, ' + drupalSettings.nome_tema.name + '!';
}
})(Drupal, drupalSettings);
Cache context quando i dati variano per utente
Generazione di HTML dentro JavaScript con Drupal.theme
Quando si vuole creare al volo dei pezzi di HTML (ad esempio un messaggio di alert) è meglio non inserire delle stringhe fisse perchè altrimenti le altre funzioni non potrebbero modificarle. E' meglio scrivere una funzione riutilizzabile agganciandola all'oggetto Drupal.theme:
(function ($, window, Drupal, drupalSettings) {
Drupal.theme.mioMessaggioAvviso = function (messaggio) {
return '<div class="alert alert-warning" role="alert">' + Drupal.checkPlain(messaggio) + '</div>';
};
Drupal.behaviors.nomeTemaMessaggi = {
attach: function (context, settings) {
var html = Drupal.theme.mioMessaggioAvviso('Attenzione: sessione in scadenza!');
$('.mio-contenitore', context).html(html);
},
detach: function (context, settings, trigger) {
// Eventuale codice di pulizia
}
};
})(jQuery, window, Drupal, drupalSettings);