:::: MENU ::::

AJAX avanzado en Drupal: Cómo pre-procesar la llamada AJAX

AJAX avanzado en Drupal: Cómo pre-procesar la llamada AJAX
7 votos, 3.86 media (75% puntos)

Profundizando un poco más allá del artículo anterior: AJAX básico en Drupal sin API de formularios, en este, vamos a ver cómo pre-procesar una llamada AJAX, antes de que Drupal realice su ‘magia’.

Viendo el artículo anterior nos damos cuenta que para utilizar llamadas AJAX en Drupal, no es necesario escribir ni una sola línea de código en javascript. Esto está bien, siempre que las funciones que Drupal trae por defecto sean suficientes para nuestros propositos.

Pero por el contrario, nos resta control en el procesamiento, y nos impide, por ejemplo cosas que pueden ser útiles, como por ejemplo:

  • Ocultar el contenido que vamos a actualizar con un overlay.
  • Actualizar simultáneamente otros bloques, ocultarlos o similar.
  • Mover o sustituir el throbber por defecto de Drupal.
  • Mostrar un mensaje al usuario.

El primer paso es entender cómo procesa Drupal los eventos AJAX, y para ello, la mejor forma es crear un evento AJAX manualmente.

Procesar manualmente el enlace AJAX

Como vimos en el artículo anterior, si añadimos la clase “use-ajax”, Drupal se encarga de procesar los clicks en el enlace mediante AJAX.

Básicamente, lo que hace Drupal con esos enlaces, es capturar el click y llamar a la función javascript Drupal.ajax() con los parámetros adecuados.

Si queremos hacer esto mismo manualmente, podemos hacer lo siguiente:

Generar el enlace con una clase diferente de “use-ajax”. Por ejemplo:

echo l(t('Mi enlace'),
       'nojs/destino', 
       array(
           'attributes' => array('id' => 'enlaceid', 'class' => array('custom-use-ajax')
       )
);

Nota: Observar el “custom-use-ajax” al final de la línea

Un enlace de este tipo, por supuesto no es reconocido por Drupal como un enlace AJAX, así que tenemos que indicarle manualmente que sí es un enlace AJAX y qué queremos que ocurra al hacer click. Si lo hacemos con un behavior, tendríamos que incluir lo siguiente en un fichero js que se cargue con la página.

Drupal.behaviors.mibehaviorid = { 
    attach: function (context, settings) {
        jQuery('.custom-use-ajax:not(.ajax-processed)').
            addClass('ajax-processed').
            each(function () {
                var element_settings = {};
                // For anchor tags, these will go to the target of the anchor rather
                // than the usual location.
                if (jQuery(this).attr('href')) {
                    element_settings.url = jQuery(this).attr('href');
                    element_settings.event = 'click';
                }
                var base = jQuery(this).attr('id');
                Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings);
           });
    } 
};

Este código está prácticamente copiado del fichero /misc/ajax.js de la instalación de Drupal, y básicamente lo que hace es crear una entrada en el array global Drupal.ajax que Drupal utiliza para almacenar la información de todos los eventos AJAX de la página actual.

Explicando el código un poco, las líneas:

var base = jQuery(this).attr('id');
Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings);

Le indican a Drupal a qué elemento queremos que vaya asociado el procesamiento AJAX. Cuando generamos el enlace, incluimos un identificador “enlaceid”, así que con las líneas anteriores incluimos una entrada en Drupal.ajax[“mienlace”], con la información necesaria para realizar el procesamiento AJAX.

Con las líneas siguientes, completamos la información básica, que únicamente incluye en este caso, la URL a la que se accede mediante AJAX (será el href del enlace) y con qué evento se dispara la llamada (en este caso con el evento click).

element_settings.url = jQuery(this).attr('href'); 
element_settings.event = 'click';

En ese caso, lo único que hemos conseguido es sustituir la clase “use-ajax” por “custom-use-ajax” y añadir el evento manualmente. Mucho trabajo para nada, de momento…

Preprocesar antes de la llamada AJAX de Drupal

En el ejemplo anterior, tenemos asociada la llamada AJAX al evento click, que el framework AJAX de Drupal ya captura automáticamente.

Para incluir algo de pre-procesamiento, necesitamos:

  1. Capturar el click
  2. Incluir nuestro código
  3. Lanzar el evento que dispara el procesamiento AJAX por parte de Drupal

Para ello, lo único que tenemos que hacer es no utilizar el evento click como disparador del evento AJAX, sino, ‘inventarnos’ un evento nuevo. De esa forma, el evento click queda libre para nuestro uso. Sería algo así:

Drupal.behaviors.mibehaviorid = {
    attach: function (context, settings) {     
        jQuery('.custom-use-ajax:not(.ajax-processed)').addClass('ajax-processed').each(function () {      
            var element_settings = {}; 
            // For anchor tags, these will go to the target of the anchor rather 
            // than the usual location. 
            if (jQuery(this).attr('href')) { 
                element_settings.url = jQuery(this).attr('href');
                element_settings.event = 'mievento'; 
            }
            var base = jQuery(this).attr('id'); 
            Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings);
            jQuery(this).click(function () { 
                /* 
                 * Aquí podemos incluir nuestro código 
                 * a medida antes de la llamada AJAX
                 */
                jQuery(this).trigger('mievento'); 
                return false;
            });
        }); 
    }
};

Con el código anterior:

  1. Utilizamos un nombre de evento diferente (por ejemplo ‘mievento’) como disparador del proceso AJAX.
  2. Capturamos el evento click con jQuery.
  3. Incluimos nuestro código antes de disparar el procesado AJAX.
  4. Lanzamos el evento creado (‘mievento’) con la función trigger, al que está asociado el procesamiento AJAX.

En el siguiente artículo, complementaremos éste con la posibilidad de post-procesar la respuesta AJAX de Drupal




One Comment

Hey! Qué opinas sobre el artículo?