13 Gennaio, 2012 | Di

Javascript in Drupal7 - parte 2

Javascript in Drupal7 - parte 2

Continuiamo la nostra serie di articoli su javascript in Drupal 7 con le due tecniche fondamentali per interagire con le funzioni Ajax e in generale con tutte le funzioni che modificano dinamicamente il DOM della pagina.

Behaviour e jQuery.once Un semplice script per controllare se il valore di un campo di testo è un numero intero potrebbe essere:

(function($, Drupal) {
  Drupal.validator = {};
  Drupal.validator.checkInteger = function(val) {
    return (val === parseInt(val,10));
  }
  Drupal.behaviors.validate = {};
  Drupal.behaviors.validate.attach = function(context, settings) {
    $('#id_element', context).once('validate-id-element', function() {
      $(this).keyup(function(event) {
        if(!Drupal.validator.checkInteger($(this).val()) {
          alert('Error');
        }
      });
    });
  };
})(jQuery, Drupal);
</pre>
<p>Analizzando lo script possiamo notare un po&#39; di cose. In javascript questa sintassi:</p>
<pre class="prettyprint">
(function($, Drupal) {
  [...]
})(jQuery, Drupal);

ha l'effetto di creare una funzione anonima (o funzione lambda) che prende come argomenti due valori e che viene chiamata subito dopo usando come argomenti gli oggetti jQuery e Drupal. In questo modo all'esterno della funzione l'oggetto jQuery è identificato dalla variabile jQuery, mentre all'interno della funzione è identificato dalla variabile $; così facendo si evita la possibile collisione con altre librerie javascript che usano $ come nome di variabile (ad esempio Prototype). Questo è reso possibile dal fatto che in drupal.js alla riga 5 viene richiamata la funzione jQuery.noConflict().

Con il codice:

Drupal.Validator = {};
Drupal.Validator.checkInteger = function(val) {
  return (val === parseInt(val,10));
}

creiamo un oggetto di nome Validator e lo inseriamo tra le proprietà dell'oggetto Drupal e definiamo per questo nuovo oggetto un metodo checkInteger per controllare se un dato argomento è o meno un numero intero.

Infine con:

Drupal.behaviors.Validate = {};
Drupal.behaviors.Validate.attach = function(context, settings) {
  $(&#39;#id_element&#39;, context).once(&#39;validate-id-element&#39;, function() {
    $(this).keyup(function(event) {
      if(!Drupal.validator.checkInteger($(this).val()) {
        alert(&#39;Error&#39;);
      }
    });
  });
};

creiamo un oggetto di nome Validate all'interno dell'oggetto behaviors all'interno dell'oggetto Drupal. Il nostro oggetto Validate ha poi un metodo chiamato attach in cui si svolge gran parte della logica e tra un attimo vedremo come viene richiamato e perché è definito così. Il metodo attach usa il plugin jQuery.once per far si che l'handler "keyup" venga attaccato una volta sola all'elemento del form che vogliamo validare. Quando l'evento si manifesta usiamo il metodo checkInteger definito in precedenza per controllare la validità dell'input.

Alla fine del caricamento di ogni pagina lo script drupal.js chiama la funzione attachBehaviors(document, Drupal.settings) che ha il compito di eseguire il metodo attach in tutti gli oggetti definiti come proprietà di Drupal.behaviors. Per quale motivo è necessario fare tutto questo? jQuery aggancia gli handler degli eventi agli elementi della pagina appena tutto il dom è disponibile; con l'uso di AJAX però alcune parti della pagina possono cambiare a fronte di nuovi dati ricevuti e su questo nuovo html jQuery non ha più controllo finché gli handler non vengono riagganciati. attachBehaviors fa proprio questo. Tutte le volte che il dom della pagina cambia basta richiamare attachBehaviors che a sua volta richiama i vari metodi attach definiti. Per ottimizzare le performance attachBehaviors andrebbe chiamato con il primo argomento settato alla parte di dom effettivamente cambiata, in modo che jQuery non debba riparsarsi tutta la struttura della pagina. Dato che il nostro codice può essere chiamato più volte (perché convive con altri script che a loro volta usano attachBehaviors) è quindi fondamentale utilizzare jQuery.once per evitare di agganciare lo stesso handler più volte allo stesso elemento.

Javascript in Drupal7 - Parte 1

Javascript in Drupal7 - Parte 3