Несколько слов о Drupal.Behaviors и $(document).ready()

Сегодня неизвестный, но бдительный пользователь вновь напомнил мне о разнице между Drupal.behaviors и $(document).ready(). Причем так напомнил, что я уже обновил по горячим следам jSlider Form API. Для закрепления, напишу об этой разнице несколько слов.

Дело в том, что некоторые (и я был в их числе) принимают Drupal.behaviors за полную замену $(document).ready(), дескать, в Друпале надо вот так — и все. Виной тому, с одной стороны, невнимательность, с другой — тот факт, что в 2009-м году описание Drupal JavaScript API было не таким подробным, как теперь. Так или иначе, основная разница между ними заключается в том, что, тогда как $(document).ready() вызывается однократно, после готовности DOM, Drupal.behaviors может вызываться несколько раз: если скрипты подгружают по AJAX на страницу новые элементы и вызывают для них функцию Drupal.attachBehaviors().

При отладке с этим сталкиваешься не всегда, поэтому о разнице нетрудно забыть. Но в боевом режиме вляпаться легко. Достаточно поставить какой-нибудь Vote Up/Down — и вот уже кнопки, генерируемые нашими скриптами, при каждом голосовании генерируются вторично, а формы начинают сохраняться по несколько раз подряд.

Чтобы избежать таких глюков, необходимо в Drupal.behaviors, во-первых, использовать переменную context, и во-вторых — присваивать обработанным однажды элементам соответствующий класс и проверять его наличие при обработке. Как в данном примере, добавленном к упомянутому описанию JS в Друпале:

Drupal.behaviors.myModuleBehavior = function(context) {
  $('.module-class-object:not(.module-class-processed)', context).each(function () {
    $(this).addClass('module-class-processed');
    // Do things
  });
};

Кроме того, для глобальных задач (например, однократно добавить на страницу кнопку) можно по-прежнему пользоваться $(document).ready().

kill_windows (гость)
Аватар пользователя kill_windows

Да еще подметил такой факт, что Drupal.behaviors подключат все определенные в нем обьекты первее чем $(document).ready(). Как то провозился с такой осебенностью целый день.

Murz (гость)
Аватар пользователя Murz

Ещё по этой теме хочу добавить что в Drupal7 вообще убрали переменную $, поэтому всякие $('div').hide() уже не работают, нужно всё делать с прямым указанием JQuery.

И исходя из примеров в других модулях, насколько я понял рекомендовано делать как-то так:
<?php Drupal.Mysite = {};
Drupal.Mysite.FormatMore = function() {
$('li.hidelink').hide();
}
$(Drupal.Mysite.FormatMore);
} ?>

graker
Аватар пользователя graker

Странно это все.
Но я с JS еще в семерке не работал.

Гость (гость)
Аватар пользователя Гость

Murz пишет:
Ещё по этой теме хочу добавить что в Drupal7 вообще убрали переменную $, поэтому всякие $('div').hide() уже не работают, нужно всё делать с прямым указанием JQuery.

И исходя из примеров в других модулях, насколько я понял рекомендовано делать как-то так:
<?php Drupal.Mysite = {};
Drupal.Mysite.FormatMore = function() {
$('li.hidelink').hide();
}
$(Drupal.Mysite.FormatMore);
} ?>


Посмотрите документацию на drupal.org. http://drupal.org/node/756722 - раздел Using jQuery
Теперь используется closure - замыкания.
(function ($) {
  // All your code here
}(jQuery));

В 6-ке тоже желательно использовать такую конструкцию

Гость (гость)
Аватар пользователя Гость

(function ($) {
  // All your code here
}(jQuery));

это не замыкания, а self-invoking функция; замыкания - это немного другое
а вообще сама идея юзать эту конструкцию правильная

Отправить комментарий

CAPTCHA
Пройдите, пожалуйста, проверку. Она нужна, чтобы отличать людей от спам-роботов. А если не хотите проходить эту проверку регулярно — зарегистрируйтесь.
Image CAPTCHA
Введите цифры, изображенные на картинке (без пробелов).