Добрый вечер
думаю, многие из вас знакомы со стандартами написания javascript для друпала, в частности с механизмом behaviors.
Как известно, грамотно написанный js-код заключается в конструкцию типа Drupal.behaviors.yourModule = function(context) { ... }
и вызывается друпалом или другими модулями конструкцией типа Drupal.attachBehaviors(context);
, где context
— это контекст вызова. Как правило, это windows.document
, т.е. в качестве контекста мы имеем целый документ. Но бывает так, что attachBehaviours вызываются сторонними модулями (и это очень хорошо и удобно), а в качестве контекста они передают, скажем, DOM элемент. Я хотел узнать, каким образом вы определяете тип объекта, переданного в качестве контекста. Мне на ум пока приходит только проверка одного из свойств объекта на существование, но это смахивает на костыли.
Комментарии
А зачем вообще это узнавать?
К примеру, модуль openlayers инициализирует карту после того, как мой js уже был приаттачен друпалом и отработал.
Благо, openlayers вызывает Drupal.attachBehaviors(...) еще раз после инициализации каждой карты. Благодаря этому, в своем js я могу произвести нужные операции с картой (которые невозможно было сделать при первом аттаче моего скрипта, т.к. объект карты на этом этапе еще не существует). OpenLayers при attachBehaviors передает в качестве контекста DOM элемент, содержащий карту, сам объект карты передается с помощью jQuery.data(). Вот я и искал удобный способ проверки типа контекста. В общем-то, уже нашел — можно проверять свойства nodeName (#document в первом случае и DIV во втором) или nodeType (там числовые коды, расшифровка есть вот здесь http://www.javascriptkit.com/domref/nodetype.shtml)
Кстати, полезный совет:
Если js-код модуля обернут в
Drupal.behaviors.yourModule = function(context) { ... }
, то он может быть вызван несколько раз в течение загрузки страницы, и могут возникнуть нежелательные последствия, поскольку ваш код будет выполнен дважды (что само по себе уже не очень хорошо).Я как-то столкнулся с тем, что после установки модуля, который использовал attachBehaviors, сайт стал зависать, да так, что приходилось перезагружать машину. Оказалось дело в том, что один из моих скриптов был вызван дважды и во второй раз отрабатывал не так, как предполагалось, т.к. на тот момент DOM-дерево уже было изменено им же при первом запуске.
С тех пор использую вот такую обертку для всех скриптов:
if ( Drupal.behaviors.myModule.initState === undefined ) {
Drupal.behaviors.myModule.initState = true;
...
// Code here
...
}
}
Моя статистика такова, что дай бог 5% друпал-программистов юзают Drupal.behaviors(), и вопрос этот скорее лучше задать на d.o
Вот что обычно используется для избежания дублей в поведениях:
$('#mymodule-element:not(.mymodule-processed)', context).addClass('mymodule-processed').each(function() { ... });
}
Может это поможет решению вашей проблемы?
Спасибо, возьму на заметку. Хотя, на мой взгляд, тяжеловатый код, но для некоторых ситуаций оправдан.
А что в нем такого тяжелого? По сравнению с другими решениями это просто няшка )
Когда наш скрипт производит манипуляции с DOM-элементами, то да — это, пожалуй, самый верный способ.
Здесь используется довольно навороченный селектор. В случае, когда наш скрипт не манипулирует с DOM-элементами, или мы точно уверены, что скрипт должен быть вызван единожды, то на мой взгляд лучше использовать простую конструкций типа той, что приведена во втором комменте.
Он наиболее правильный с позиции идеологии прицепки поведений в JS Друпала.
И мне подскажите пожалуйста.
Я не использую какой-либо модулю, весь мой код находится в php снипете. Но этот код добавляет js скрипт (галерейка на jQuery) в страницу и он должен обработатся как положено. В каком виде я должен оформить Drupal.behaviors. ? Ведь модуля никакого у меня нет.
P.S. меня интересует формат для D7