> For the complete documentation index, see [llms.txt](https://wplake.gitbook.io/advanced-views/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wplake.gitbook.io/advanced-views/layouts/code-fields/javascript-code.md).

# Layout JavaScript code

In Advanced Views, every [*Layout*](/advanced-views/getting-started/first-layout.md) can have its own JavaScript. When present, the JavaScript is automatically injected before the page's `</body>` closing tag as `<script type="module">`.&#x20;

This ensures non-blocking execution, improving the user experience and reducing the **First Contentful Paint (FCP)**.

{% hint style="info" %}
Before the JavaScript is added to the page, Advanced Views automatically performs basic minification, so there's no need for additional optimization tools or build steps.
{% endhint %}

#### On-Demand JavaScript loading

Advanced Views uses an **on-demand** asset loading strategy. This means a *Layout*'s JavaScript is only loaded on pages where that *Layout* is actually used. Advanced Views handles this automatically behind the scenes.

{% hint style="info" %}
This approach completely eliminates the need for asset bundling, allowing you to create independent *Layouts* that editors can mix and match in any combination, without having tons of site-wide JavaScript.
{% endhint %}

## **1. How to add custom JavaScript to any&#x20;*****Layout***

1. [Create a new *Layout*](/advanced-views/getting-started/first-layout.md) or open an existing one
2. On the *Layout* edit screen, switch to the *CSS & JS* tab.
3. **Insert** or paste your JavaScript code in the *JS Code* field.
4. **Click** on the **Update** button to publish your changes.

By default, *Layout's* JavaScript is turned into a WebComponent instance, as described in the section below. You can control the WebComponent type or completely disable it using the **Web Component type** setting available on the *Layout* Options tab. &#x20;

{% hint style="warning" %}
**Syntax note:** Never omit semicolons(`;`) at the end of lines. JavaScript allows it only if you use line breaks afterward, but any line breaks will be removed during on-print optimization by Advanced Views. If you skip a semicolon, you will get a JavaScript error.
{% endhint %}

## 2.  *Layout* as a Web Component

Advanced Views natively supports [Web Components](https://developer.mozilla.org/en-US/docs/Web/API/Web_components) and creates a unique tag wrapper for every *Layout* out of the box. As soon as you add any JavaScript code, Advanced Views sets up a [Web Component instance](https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/define) for the current *Layout* and places your JavaScript code inside.

It means your code will be automatically executed for every *Layout* instance appearing on the page.

{% hint style="info" %}
When you need to add global JavaScript, you can set the 'Web Component Type' setting of your *Layout* to 'None'. Additionally, you can configure the default setting for new *Layouts* inside the Defaults tab of the Advanced Views settings.
{% endhint %}

For example, let's say we have a *Layout* and you want to track clicks on the links inside it.

Without Web Components, your JS code might look like this:

```javascript
document.addEventListener('DOMContentLoaded', function () {
  document.body.querySelectorAll('.my-object').forEach((obj) => {
    obj.querySelectorAll('a').addEventListener('click', function () {
      // some stuff here
    });
  });
});
```

With Web Components, your code is called for every instance on the page and has the `this` context. So, you can write it like this:

```javascript
this.querySelectorAll('a').addEventListener('click', function () {
  // some stuff here
});
```

As you can see, Web Components make adding custom JavaScript simpler and more maintainable, especially for Ajax-loaded content.

Without Web Components, dynamically inserted HTML usually requires a [MutationObserver](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) to detect added nodes, find the relevant elements, and attach event listeners manually. With Web Components, none of that is necessary. Your code is automatically executed for every new component instance, including those inserted via Ajax.

#### 2.2) Hidden boilerplate

Looking at the example above, you might wonder how it works. On its own, this code wouldn't work if it were pasted directly into the page.

The trick is that Advanced Views automatically wraps your JavaScript in the required boilerplate, so you don't have to write it yourself. This lets you focus on your logic while Advanced Views handles the surrounding setup:

```javascript
// your component name is injected here
class MyComponent extends HTMLElement {
    connectedCallback(){
        "loading"===document.readyState?
            document.addEventListener("DOMContentLoaded",this.setup.bind(this)):
            this.setup()
    }
    setup(){
        // content of your JS code field is injected here
    }
}
// your component name is injected here
customElements.define(MyComponent, 'my-component');
```

{% hint style="success" %}
When using the **Classic** Web Component type, this boilerplate is generated only when the JavaScript field contains some code.
{% endhint %}

You also don't need to worry about using [ES module imports](https://javascript.info/modules-intro). If you add any `import` statements, Advanced Views automatically moves them to the top of the module before outputting the code.

#### 2.2) Shadow DOM mode

By default, *Layout* is a classical Web Component. In some cases, you may prefer the [Shadow DOM mode](/advanced-views/layouts/code-fields/javascript-code/shadow-dom-mode.md), which is also natively supported by Advanced Views.

## 3. JavaScript libraries usage

To add complex interactive elements, like sliders, you'll need to use some JavaScript libraries. If you use Advanced Views Pro, read about the [Pre-built libraries](/advanced-views/layouts/features/pre-built-libraries.md) to get a hassle-free experience.

If you use Advanced Views Lite, or need to employ a specific library that is missing from the built-in list, you need to enqueue it on the target page.

The classic enqueuing in WordPress happens with the [wp\_enqueue\_script](https://developer.wordpress.org/reference/functions/wp_enqueue_script/) function, but to avoid sitewide enqueueing (which is bad for performance), it requires manual detection of the target pages.

That's why we recommend harnessing [the modules feature](https://javascript.info/modules-intro). So, you add `import x from "/wp-content/themes/theme_name/assets/library.js"` or just `import "/wp-content/themes/theme_name/assets/library.js"` to the top of the JS code, and the browser will automatically load the library only for the necessary pages.&#x20;

You shouldn't worry about duplication; according to the standard, the browser will import the script only once, even if the same import statement appears in several different *Layouts*.

**Notes on the modules**

1. You must use the correct path to the JS library\
   **Tip:** use a relative path - we recommend bypassing the domain name and starting the path from the `/wp-content` folder. This ensures that the import works dynamically, regardless of the current domain (e.g., staging and live environments).
2. You **can** use it along with the Web Components\
   According to the JavaScript policy, all imports must be placed at the top of the module. Advanced Views adheres to this policy, so before wrapping your code into a WebComponent, Advanced Views extracts the imports to ensure they remain at the top of the module. &#x20;

## 4. Advanced usage

#### 4.1) TypeScript usage

In Advanced Views, there is a [File System Storage](/advanced-views/features/file-system-storage.md) option. If you enable it, you can utilize TypeScript for *Layout's* JavaScript code - check [advanced FS storage usage](/advanced-views/features/file-system-storage/advanced-usage.md) for details.

#### 4.2) WordPress Interactivity API usage

*Layouts* [natively support WordPress Interactivity API](/advanced-views/layouts/component-options/interactivity-api.md) out of the box.
