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

Прислано: Stutzer

чт, 07/10/2010 - 18:38

Добрый вечер

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

Комментарии


Настройки просмотра комментариев

Выберите нужный метод показа комментариев и нажмите "Применить"
Опубликовано neochief в чт, 07/10/2010 - 21:02.

А зачем вообще это узнавать?


Опубликовано Stutzer в чт, 07/10/2010 - 21: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
 
    ...
 
  }
 
}


Опубликовано RxB в чт, 07/10/2010 - 21:25.

Моя статистика такова, что дай бог 5% друпал-программистов юзают Drupal.behaviors(), и вопрос этот скорее лучше задать на d.o


Опубликовано neochief в сб, 09/10/2010 - 03:52.

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

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

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


Опубликовано Stutzer в вт, 26/10/2010 - 22:13.

neochief написал(а):

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

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

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

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


Опубликовано neochief в ср, 27/10/2010 - 11:10.

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


Опубликовано v1adimir@drupal.org в ср, 27/10/2010 - 11:21.

Stutzer написал(а):
neochief написал(а):

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

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

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

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

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


Опубликовано Stutzer в ср, 27/10/2010 - 20:22.

neochief написал(а):

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

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

v1adimir@drupal.org написал(а):

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

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


Опубликовано W32 в пн, 21/02/2011 - 15:07.

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

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


Новое на сайте

Ссылки партнёров