JavaScript, jQuery e DOM Ready no Drupal 7

tl; dr : o código JavaScript para processar elementos no carregamento da página em um site Drupal 7 deve ser semelhante a este:

(function($) {
Drupal.behaviors.doSomething = {
attach
: function(context, settings) {
$
('div.something', context).once('do-something').doSomething({
param1
: settings.somethingl.param,
param2
: 'something else'
});
}
}
})(jQuery);

O Drupal 7 fornece jQuery no modo sem conflito , o que significa que $não é o objeto / namespace jQuery. Isso não deve ser um problema com plug-ins jQuery escritos corretamente que seguem as diretrizes de criação de plug-ins jQuery . No entanto, isso é um problema para snippets de código copiados / colados sem pensar de páginas da Web aleatórias. Como a maioria deles espera $ser o namespace jQuery. Isso pode ser facilmente resolvido envolvendo esses snippets em uma função anônima imediatamente invocada que criará o alias do namespace jQuery para $:

(function($) {
// Here $ is the jQuery namespace.
})(jQuery);

Normalmente, o código JavaScript que precisa ser executado no carregamento da página também é encapsulado em uma função passada como argumento para jQueryou jQuery(document).ready:

$(function() {
// Code here is executed when the DOM is loaded.
});

Quando combinados, esses dois padrões são perfeitamente bons, mesmo com o Drupal. No entanto, se o conteúdo (ou seja, novos elementos DOM) for adicionado à página após o carregamento da página (chamadas AJAX, conteúdo gerado de JavaScript, etc.), o código em tais funções nunca será capaz de processar os elementos adicionados. Ou se alguma parte do conteúdo for removida ou movida pela página, o código não terá a opção de cancelar o registro de manipuladores de eventos ou atualizar as informações sobre os elementos já processados. O Drupal fornece uma API para esses comportamentos chamados . Usar o comportamento não é obrigatório, mas é altamente recomendado como melhor prática para evitar dores de cabeça futuras (quando o código escrito seis meses atrás começa a se comportar de forma estranha quando um módulo contrib é adicionado ao projeto). Um comportamento é escrito assim:

Drupal.behaviors.behaviorName = {
attach
: function (context, settings) {
// Do something.
},
detach
: function (context, settings, trigger) {
// Undo something.
}
};

A attachfunção de todos os comportamentos registrados (todas as propriedades do objeto) será chamada quando o comportamento deve ser adicionado aos elementos, seja quando o DOM estiver pronto (ou seja, página laod) e quando os elementos forem adicionados ao DOM. A função será chamada quando os comportamentos devem ser separados dos elementos: logo antes de os elementos serem removidos do DOM, movidos no DOM ou um formulário ser enviado. O parâmetro sempre será um pai dos elementos adicionados, o próprio elemento adicionado / removido / movido ou o elemento. Os parâmetros serão as configurações para o , geralmente o objeto definido por chamadas a partir do PHP. Para , o parâmetro conterá o tipo de evento que acionou a chamada:Drupal.behaviorsdetachcontextdocumentsettingscontextDrupal.settingsdrupal_add_js()detachtrigger'unload'(elementos removidos), 'move'(elementos movidos) ou 'serialize'(o formulário está sendo enviado).

As funções attach(e detach) de um comportamento podem ser usadas várias vezes na mesma parte da árvore DOM. Portanto, o mesmo elemento pode ser processado várias vezes pelo mesmo código. É responsabilidade do próprio código evitar o processamento (ou seja, vinculando manipuladores de eventos, alterando estilos CSS, etc.) várias vezes para os mesmos elementos. A solução mais fácil para isso é usar o plugin jQuery Once (que é fornecido pelo Drupal 7 ) assim:

$(selector).once('behavior-name').doSomething();
$
(selector).once('behavior-name', function(){ /*do something*/ });

Uma vez que um comportamento está sendo anexado / desanexado de / para um contexto, o objeto de contexto pode ser usado para restringir suas consultas jQuery apenas ao elemento afetado ou subárvore DOM, como este:

$ (seletor, contexto) .doSomething ();

Juntar tudo isso significa que o padrão básico para processar os elementos no carregamento da página deve ser assim:

(function($) {
Drupal.behaviors.doSomething = {
attach
: function(context, settings) {
$
('div.something', context).once('do-something').doSomething({
param1
: settings.somethingl.param,
param2
: 'something else'
});
}
}
})(jQuery);

Referências: