При поддержке старых версий Drupal (в данной статье речь идёт о Drupal 6 и Drupal 7) часто возникает необходимость использования актуальной (современной) версии jQuery. И если в случае с самописными скриптами можно обойтись версией из ядра, то в случае использования готового jQuery плагина этот вариант может не подойти. К примеру, в Drupal 6 вы не сможете использовать такой популярный плагин, как Chosen, поскольку он просто не заработает на том jQuery, что есть в ядре. К слову о версиях: из "коробки" Drupal 7 предоставляет jQuery версии 1.4.4, а Drupal 6 - версии 1.2.6. Просто взять и обновить jQuery в ядре Drupal нельзя по двум причинам. Во-первых, это вездесущие проблемы с дальнейшим обновлением ядра. Во-вторых, скрипты Drupal и контрибных модулей не будут работать с новой версией. Безусловно можно использовать модуль jQuery Update. Он решает большинство проблем с jQuery в Drupal 7, но для Drupal 6 в настоящее время практически бесполезен -  Chosen не заработает даже с этим модулем. Можно, конечно, использовать старые (совсем старые) версии нужных плагинов или самому реализовать их функционал, но это никому не нужный труд. К счастью, есть и другие варианты решения вышеописанной проблемы. Об одном из таких решений далее и пойдёт речь.

Первым делом стоит отметить, что jQuery позволяет запускать на странице другие версии jQuery. Достигается это засчёт использования функции noConflict(). На её основе построена логика работы модуля jQuery Multi. Код "обработки" новой версии jQuery находится в файле js/switch.js относительно директории модуля.

(function($) {
  // Put together the name of the new jQuery variable.
  var version = $().jquery;
  var versionName = version.replace(/\./g, '');
  // Save the new version of jQuery globally and restore Drupal version.
  window['jq' + versionName] = jQuery.noConflict(true);
})(jQuery);

Как видно из кода - новая версия jQuery будет доступна в переменной jq{%version}, старая версия будет по-прежнему доступна в переменной jQuery или её синониме $. Например, при использовании версии 3.1.1, переменная будет jq311. С этого момента уже можно работать с новой версией (скрипты, использующие старую версию не сломаются), однако, это не совсем удобно, так как по общеиспользуемому синониму $ будет доступна старая версия, что не подходит для использования сторонних плагинов. Также подобный подход отразится на поддержке и переносимости кода.

Следующими немаловажными достоинствами модуля jQuery Multi является интеграция с модулем Libraries API и возможность определения скриптов, которые должны отрабатывать с новой версией jQuery на основе хуков hook_jqmulti_files() и hook_jqmulti_libraries(). Библиотеки, которые расположены в sites/all/libraries модуль определяет самостоятельно и ими можно управлять на странице настроек модуля.

Эти скрипты будут загружены после загрузки новой версии jQuery, но до файла switch.js, что позволит выполнить код в контексте новой версии. Это уже позволяет использовать сторонние плагины без изменения их кода (Chosen заработает). Стоит отметить, что данный подход не решает проблему с написанием ряда callback-функций.

Drupal.behaviors.mySiteExampleBehavior = function (context) {
  // Custom behavior logic.
};

Внутри функции mySiteExampleBehavior() использование синонима $ приведёт к использованию старой версии jQuery, даже если скрипт будет загружен до файла switch.js. Для использования нового jQuery после кода switch.js всё ещё нужно обращаться к переменной jq311, что неудобно. Для решения этой проблемы напишем скрипт в одном из самописных модулей:

Drupal.mySiteExample = Drupal.mySiteExample || {};
 
(function ($) {
  // Set additional jQuery variable name globally.
  var version = $().jquery;
  var versionName = version.replace(/\./g, '');
  Drupal.mySiteExample.jQueryVariable = 'jq' + versionName;
})(jQuery);

В коде модуля реализуем хук hook_jqmulti_files() и выведем скрипт на hook_init():

/**
 * Implements hook_jqmulti_files().
 */
function example_jqmulti_files() {
  // Set files to be loaded with jQuery Multi's jQuery library.
  return array(
    drupal_get_path('module', 'example') . '/js/example.js',
  );
}
 
/**
 * Implements hook_init().
 */
function example_init() {
  drupal_add_js(drupal_get_path('module', 'example') . '/js/example.js');
}

Код скрипта example.js будет выполнен в контексте новой версии jQuery, а название переменной, по которой можно будет получить к ней доступ, будет сохранено в Drupal.mySiteExample.jQueryVariable. Для использования новой версии jQuery по синониму $ достаточно добавить следующую обёртку в скрипте: 

Drupal.mySiteExample = Drupal.mySiteExample || {};
Drupal.mySiteExample.jQueryVariable = Drupal.mySiteExample.jQueryVariable || 'jQuery';
 
(function ($) {
 
  // Your code here.
 
})(window[Drupal.mySiteExample.jQueryVariable]);

Переменная $ внутри вышеуказанной функции будет относиться к новой версии jQuery, а вне функции - к jQuery из ядра Drupal. Подробно почитать о вариантах использования новых версий jQuery в Drupal можно на странице официальной документации.

Андрей Тымчук

Добавить комментарий