Как переопределить поведение ajax-ссылки

mbaev 07.04.2016, 13:16

Многим известно, что в Drupal'е есть собственный ajax-фреймворк, который использует в качестве ответов, так называемые, команды. Сами запросы могут быть инициированы разными способами:

  1. Присвоив класс use-ajax на любой тэг (на стороне сервера или на стороне клиента, но перед инициализацией Drupal js части). В базовом использовании этого варианта есть обязательное условие - тэг должен иметь атрибут href содержащий путь, на который будет выполнен ajax запрос.
  2. Определив параметр #ajax в форме (на стороне сервера).
  3. Присвоив параметр use-ajax-submit форме (тэг form). Это что-то среднее между п.1 и п.2.
  4. Инициировав new Drupal.ajax() (на стороне клиента)

Изменение поведения ajax-обработчика

Рассмотрим пример с ссылкой, на которой есть класс use-ajax. Мы будет изменять состояние bootstrap кнопки на момент выполнения запроса - пример.
Наша вымышленная страница содержит такой тэг:

  1. <a class="use-ajax btn btn-primary" data-loading-text="Saving..." href="/save-something">Save</a>

Здесь data-loading-text="Saving..." говорит бутатрапу, что в момент выполнения запроса на кнопке должен отображаться текст "Saving...". Так ссылка уже будет работать как через ajax, но для нашего трюка необходимо присвоить id этому тэгу. Например, MYMODULE-save-link.

  1. <a class="use-ajax btn btn-primary" data-loading-text="Saving..." href="/mymodule-callback" id="MYMODULE-save-link">Save</a>

Теперь перейдем к JS части.

  1. /**
  2.  * @file
  3.  * Javascript for MYMODULE module.
  4.  */
  5. (function ($, Drupal) {
  6.   "use strict";
  7.   /**
  8.    * Behavior for MYMODULE module
  9.    */
  10.   Drupal.behaviors.MYMODULE = {
  11.     attach: function (context, settings) {
  12.       if (typeof Drupal.ajax['MYMODULE-save-link'] != 'undefined') {
  13.         var ajax = Drupal.ajax['MYMODULE-save-link'];
  14.         // Сохраняем функции обратного вызова, назначенные друпалом.
  15.         ajax.savedBeforeSend = ajax.beforeSend;
  16.         ajax.savedSuccess = ajax.success;
  17.  
  18.         // Заменяем их на свои.
  19.         ajax.beforeSend = function (xmlhttprequest, options) {
  20.           // Изменяем состояние кнопки перед запросом.
  21.           $(this.element).button('loading');
  22.           // Но не забываем вызывать сохраненные функции. Они нужны для правильной работы.
  23.           ajax.savedBeforeSend(xmlhttprequest, options);
  24.         };
  25.  
  26.         ajax.success = function (response, status) {
  27.          // Нативная функциональность должна выполняться раньше произвольной.
  28.           var result = ajax.savedSuccess(response, status);
  29.           // Сбрасываем состояние кнопки после завершения запроса.
  30.           $(this.element).button('reset');
  31.           return result;
  32.         };
  33.       }
  34.     }
  35.   };
  36. })(jQuery, Drupal);

Чтобы все это заработало, на сайте необходимо иметь bootstrap.

Результат
Save-bootstrap