Проверка типа контекста в javascript

Главные вкладки

Аватар пользователя Stutzer Stutzer 7 октября 2010 в 22:38

Добрый вечер

думаю, многие из вас знакомы со стандартами написания javascript для друпала, в частности с механизмом behaviors.
Как известно, грамотно написанный js-код заключается в конструкцию типа Drupal.behaviors.yourModule = function(context) { ... } и вызывается друпалом или другими модулями конструкцией типа Drupal.attachBehaviors(context);, где context — это контекст вызова. Как правило, это windows.document, т.е. в качестве контекста мы имеем целый документ. Но бывает так, что attachBehaviours вызываются сторонними модулями (и это очень хорошо и удобно), а в качестве контекста они передают, скажем, DOM элемент. Я хотел узнать, каким образом вы определяете тип объекта, переданного в качестве контекста. Мне на ум пока приходит только проверка одного из свойств объекта на существование, но это смахивает на костыли.

Комментарии

Аватар пользователя Stutzer Stutzer 8 октября 2010 в 1:25

К примеру, модуль 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-дерево уже было изменено им же при первом запуске.

С тех пор использую вот такую обертку для всех скриптов:

Drupal.behaviors.myModule = function(context) {
 
  if ( Drupal.behaviors.myModule.initState === undefined ) {
   
    Drupal.behaviors.myModule.initState = true;
   
    ...
   
    // Code here
   
    ...
   
  }

}

Аватар пользователя neochief neochief 9 октября 2010 в 7:52

Вот что обычно используется для избежания дублей в поведениях:

Drupal.behaviors.mymodule = function(context) {
  $('#mymodule-element:not(.mymodule-processed)', context).addClass('mymodule-processed').each(function() { ... });
}

Может это поможет решению вашей проблемы?

Аватар пользователя Stutzer Stutzer 27 октября 2010 в 2:13

neochief wrote:
Вот что обычно используется для избежания дублей в поведениях:

Drupal.behaviors.mymodule = function(context) {
  $('#mymodule-element:not(.mymodule-processed)', context).addClass('mymodule-processed').each(function() { ... });
}

Может это поможет решению вашей проблемы?

Спасибо, возьму на заметку. Хотя, на мой взгляд, тяжеловатый код, но для некоторых ситуаций оправдан.

Аватар пользователя v1adimir@drupal.org v1adimir@drupal.org 27 октября 2010 в 15:21

Stutzer wrote:
neochief wrote:
Вот что обычно используется для избежания дублей в поведениях:

Drupal.behaviors.mymodule = function(context) {
  $('#mymodule-element:not(.mymodule-processed)', context).addClass('mymodule-processed').each(function() { ... });
}

Может это поможет решению вашей проблемы?

Спасибо, возьму на заметку. Хотя, на мой взгляд, тяжеловатый код, но для некоторых ситуаций оправдан.


А что в нем такого тяжелого? По сравнению с другими решениями это просто няшка )

Аватар пользователя Stutzer Stutzer 28 октября 2010 в 0:22

neochief wrote:
Он наиболее правильный с позиции идеологии прицепки поведений в JS Друпала.

Когда наш скрипт производит манипуляции с DOM-элементами, то да — это, пожалуй, самый верный способ.

<a href="mailto:v1adimir@drupal.org">v1adimir@drupal.org</a> wrote:
А что в нем такого тяжелого? По сравнению с другими решениями это просто няшка )

Здесь используется довольно навороченный селектор. В случае, когда наш скрипт не манипулирует с DOM-элементами, или мы точно уверены, что скрипт должен быть вызван единожды, то на мой взгляд лучше использовать простую конструкций типа той, что приведена во втором комменте.

Аватар пользователя W32 W32 21 февраля 2011 в 18:07

И мне подскажите пожалуйста.
Я не использую какой-либо модулю, весь мой код находится в php снипете. Но этот код добавляет js скрипт (галерейка на jQuery) в страницу и он должен обработатся как положено. В каком виде я должен оформить Drupal.behaviors. ? Ведь модуля никакого у меня нет.

P.S. меня интересует формат для D7