{"componentChunkName":"component---src-templates-post-jsx","path":"/en/drupal-behaviors","result":{"data":{"markdownRemark":{"html":"<p>When developing custom Drupal modules or themes, it is common to write JavaScript. In this article we will look at best practices for writing clean JavaScript that integrates properly with Drupal — both server-side and in the browser.</p>\n<p>We are used to grouping jQuery code inside the <code class=\"language-text\">ready()</code> method like this:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">$</span><span class=\"token punctuation\">(</span>document<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">ready</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token comment\">// jQuery code here</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Using this method guarantees that the code will only execute after the <strong>Document Object Model (DOM)</strong> is fully loaded, and it also allows us to place our jQuery code anywhere on the page.</p>\n<p>Drupal took inspiration from this method to provide a more powerful solution: <strong>Drupal Behaviors</strong>. The principle is the same as <code class=\"language-text\">document.ready</code>, except that it is managed by Drupal once the DOM is fully loaded.</p>\n<p>Any Drupal-powered site contains the global <code class=\"language-text\">Drupal</code> object, which holds several sub-objects. The one we care about in this article is <code class=\"language-text\">Drupal.behaviors</code>, which contains the JavaScript code we want to execute once the DOM is fully loaded.</p>\n<p>Example of a Drupal Behavior:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">$<span class=\"token punctuation\">,</span> Drupal</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  Drupal<span class=\"token punctuation\">.</span>behaviors<span class=\"token punctuation\">.</span>CustomBehavior <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function-variable function\">attach</span><span class=\"token punctuation\">:</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">context<span class=\"token punctuation\">,</span> settings</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n     <span class=\"token comment\">// jQuery code here.</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span>jQuery<span class=\"token punctuation\">,</span> Drupal<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>The behaviors system is especially useful when the DOM is modified via Ajax calls without a page reload. After new elements are added to the DOM, Drupal invokes <code class=\"language-text\">Drupal.behaviors</code> to attach them to the newly added elements. The <code class=\"language-text\">context</code> object contains the part of the DOM that was just added — whether via Ajax or another method.</p>\n<p>Consider the following code:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">$<span class=\"token punctuation\">,</span> Drupal</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  Drupal<span class=\"token punctuation\">.</span>behaviors<span class=\"token punctuation\">.</span>uniqueKey <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function-variable function\">attach</span><span class=\"token punctuation\">:</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token comment\">// Search the DOM for an element with class .behavior_example and logs it in the console.</span>\n      <span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token string\">\".behavior_example\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">once</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"unique-key\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">each</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">(</span>jQuery<span class=\"token punctuation\">,</span> Drupal<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p><em>Note: you must add <code class=\"language-text\">core/jquery.once</code> as a library dependency in your module to use it.</em></p>\n<p>The problem here is that every time a new element is added to the DOM, the entire DOM is scanned for elements with the class <code class=\"language-text\">behavior_example</code>, leading to a performance loss.</p>\n<p>This is where <code class=\"language-text\">context</code> comes in to solve the problem and produce more efficient code:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">$<span class=\"token punctuation\">,</span> Drupal</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  Drupal<span class=\"token punctuation\">.</span>behaviors<span class=\"token punctuation\">.</span>uniqueKey <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function-variable function\">attach</span><span class=\"token punctuation\">:</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">context</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token comment\">// This example solves the problem by searching only in the context which contains only the part that is being added to the DOM.</span>\n      <span class=\"token function\">$</span><span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">find</span><span class=\"token punctuation\">(</span><span class=\"token string\">\".behavior_example\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">once</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"unique-key\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">each</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token function\">$</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">(</span>jQuery<span class=\"token punctuation\">,</span> Drupal<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<blockquote>\n<p>After a full page load, <code class=\"language-text\">context</code> contains the entire DOM. After Ajax calls, <code class=\"language-text\">context</code> holds only the part of the DOM that was newly loaded and added.</p>\n</blockquote>","excerpt":"When developing custom Drupal modules or themes, it is common to write JavaScript. In this article we will look at best practices for writing clean JavaScript…","frontmatter":{"date":"2020-02-23","metaDate":"2020-02-23","title":"Drupal Behaviors","tags":["jQuery","JavaScript","Module development","Performance","Ajax"],"path":"/drupal-behaviors","cover":{"childImageSharp":{"fluid":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIDAQX/xAAXAQADAQAAAAAAAAAAAAAAAAAAAQME/9oADAMBAAIQAxAAAAHm1k2uamA//8QAGBAAAwEBAAAAAAAAAAAAAAAAAAEREBL/2gAIAQEAAQUCHlR0VH//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAWEAADAAAAAAAAAAAAAAAAAAAAICH/2gAIAQEABj8CIv8A/8QAGhABAAMAAwAAAAAAAAAAAAAAAQARIRAxYf/aAAgBAQABPyE7yITFFS/YQRVLwf/aAAwDAQACAAMAAAAQfN//xAAWEQADAAAAAAAAAAAAAAAAAAABEBH/2gAIAQMBAT8QhX//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAcEAEAAgEFAAAAAAAAAAAAAAABABExIXGBkfH/2gAIAQEAAT8QtohAsYy27wbldy5d08yhCBgBiXrP/9k=","aspectRatio":1.3337311058074781,"src":"/static/796626dc39bbb34b7c94b598456e29a3/88110/coding.jpg","srcSet":"/static/796626dc39bbb34b7c94b598456e29a3/0b320/coding.jpg 480w,\n/static/796626dc39bbb34b7c94b598456e29a3/60b32/coding.jpg 960w,\n/static/796626dc39bbb34b7c94b598456e29a3/88110/coding.jpg 1920w,\n/static/796626dc39bbb34b7c94b598456e29a3/40175/coding.jpg 2880w,\n/static/796626dc39bbb34b7c94b598456e29a3/a0c5f/coding.jpg 3353w","srcWebp":"/static/796626dc39bbb34b7c94b598456e29a3/d1a9d/coding.webp","srcSetWebp":"/static/796626dc39bbb34b7c94b598456e29a3/bc3bf/coding.webp 480w,\n/static/796626dc39bbb34b7c94b598456e29a3/39337/coding.webp 960w,\n/static/796626dc39bbb34b7c94b598456e29a3/d1a9d/coding.webp 1920w,\n/static/796626dc39bbb34b7c94b598456e29a3/fcbe1/coding.webp 2880w,\n/static/796626dc39bbb34b7c94b598456e29a3/07784/coding.webp 3353w","sizes":"(max-width: 1920px) 100vw, 1920px"},"resize":{"src":"/static/796626dc39bbb34b7c94b598456e29a3/c4f3a/coding.jpg"}}}}}},"pageContext":{"isCreatedByStatefulCreatePages":false,"pathSlug":"/drupal-behaviors","locale":"en","prev":{"fields":{"locale":"en"},"frontmatter":{"path":"/cache-api","title":"Cache API","tags":["Cache","Performance","Module development","Drupal 8"]}},"next":{"fields":{"locale":"en"},"frontmatter":{"path":"/getting-ready-for-drupal9","title":"Getting Ready for Drupal 9","tags":["Drupal 8","Drupal 9","Performance","Update"]}}}}}