# The Cubbles mutation based start event API

## Purpose

Cubbles allows users to observe the mutations of an HTML node (See [this](https://developer.mozilla.org/en/docs/Web/API/MutationObserver)) and then dispatch an event if a mutation occurs. The mutations that can be observed are the ones corresponding to `{childList: true}`.

The [RTE](/docs/runtime-extension-rte/user-guide/rte-processing.md) contains a utility called `mutation-based-cubx-startevent` which contains the following attributes:

1. **data-cubx-target-selector**: to provide a css selector to indicate which node should be observed
2. **data-cubx-emit-event**: to indicate the name of the event, which should be dispatched when a mutation occurs.

It is important to highlight that the only mutation to be observed is the first one that occurs; after that, the event will be dispatched and the observer will be disconnected.

The following sections present a demo to show the proper use of the `mutation-based-cubx-startevent` utility.

## Prerequisites

* We will use the [cubx-textarea](https://cubbles.world/sandbox/com.incowia.basic-html-components@2.0.0-SNAPSHOT/cubx-textarea/docs/index.html) component in our example. Thus, it should be available within the store you are currently using

## Sample case

Let's say say you are building an app where a Cubbles component will be included. The component will be appended to a div container, but you need the Cubbles RTE to start working after this div suffers a mutation. Thus, you need to use the `mutation-based-cubx-startevent.`

## Using the mutation-based-cubx-startevent utility

To use the `mutation-based-cubx-startevent` first we need to:

1. Include it as script within the head of our HTML document
2. Add a root dependency to include the `cubx-textarea` in our page
3. Include the `custom-elements-es5-adapter`, `webcomponents-lite` and the `crc-loader` scripts as usual.
4. Provide a value for the `data-cubx-startevent` within the `crc-loader` script since we want the Cubbles RTE to start working after a mutation occurs

Lets say we want to observe a div, whose id is *observable*. Also, we want an event called *mutationBasedStart* to be dispatched when the mutation occurs. Therefore, the values of the `mutation-based-cubx-startevent` attributes should be:

| Attribute                 | Value              |
| ------------------------- | ------------------ |
| data-cubx-target-selector | #observable        |
| data-cubx-emit-event      | mutationBasedStart |

### The head element

Using the information presented above, the *head* element of our app should look similar to the one shown below:

```markup
<head>
    <meta charset="UTF-8">
    <title>&lt;cubx-textarea&gt;</title>
    <link rel="stylesheet" type="text/css" href="style.css">
    <script src="https://cubbles.world/sandbox/cubx.core.rte@3.0.0-SNAPSHOT/webcomponents/custom-elements-es5-adapter.js"></script>
    <script src="https://cubbles.world/sandbox/cubx.core.rte@3.0.0-SNAPSHOT/webcomponents/webcomponents-lite.js"></script>
    <script src="https://cubbles.world/sandbox/cubx.core.rte@3.0.0-SNAPSHOT/mutation-based-cubx-startevent/js/mutationBasedCubxStartevent.js"
            data-cubx-target-selector="#observable"
            data-cubx-emit-event="mutationBasedStart"></script>
    <script>
    window.cubx = {
        CRCInit: {
            rootDependencies: [
                {
                    webpackageId: 'com.incowia.basic-html-components@2.0.0-SNAPSHOT',
                    artifactId: 'cubx-textarea'  
                }
            ]
        }
    };
    </script>
    <script src="https://cubbles.world/sandbox/cubx.core.rte@3.0.0-SNAPSHOT/crc-loader/js/main.js" data-crcinit-loadcif="true" data-cubx-startevent="mutationBasedStart"></script>
</head>
```

### The body element

As you can already imagine, the *body* of our app should have a div container with an id equals to *observable*. That will be enough, however we want our app to explain how our `mutation-based-cubx-startevent` works, so we will also include the following elements:

1. A title for our app
2. A description of the values of the  attributes
3. A description explaining how the `mutation-based-cubx-startevent` works in this particular case
4. A button to append the component called `cubx-textarea`
5. And a loader to be shown while the Cubbles RTE is working

The code of the body of our app should now look as follows:

```markup
<h1>Mutation based start event demo</h1>

<h2>Attributes values</h2>
<p>In this case, the attributes of the <em>mutation-based-cubx-startevent</em> have the following values:</p>
<ul>
    <li><strong>data-cubx-mutation-target-node:</strong> "#observable"</li>
    <li><strong>data-cubx-emit-event:</strong> "mutationBasedStart"</li>
</ul>

<h2>How it works</h2>
<p>
Every change on the element with the id 'observable' will be detected, thus appending an
element will cause the 'mutationBasedStart' event to be dispatched.
</p>
<p>
Now you can <strong>click on</strong> the button below to cause the mutation to see it working:
</p>
<button id="appendComp">Append a 'cubx-textarea'</button>
<hr>
<div class="loader"></div>
<div id="observable"></div>
```

### A script to control behavior

We need a script to:

1. Create and init the `cubx-textarea` component using the [The Cubbles Tag API](/docs/runtime-extension-rte/user-guide/cubbles-tag-api.md).
2. Append the `cubx-textarea` component to the *observable* div after the *appendComp* button is clicked.
3. Show the *loader* while the Cubbles RTE is working
4. Hide the *loader* and show the *observable* when the component is ready

Our code should look similar to the one shown below:

```markup
<script>
(function () {
        'use strict';
        var loader = document.querySelector('.loader');
        var appendComp = document.querySelector('#appendComp');
        var observable = document.querySelector('#observable');

        // Append the cubx-textarea component to the observable div after the appendComp button is clicked.
        appendComp.addEventListener('click', function () {
            observable.appendChild(createTextareaComponent());
            appendComp.setAttribute('disabled', 'disabled');
            loader.style.display = 'block';
        });

        // Hide the loader and show the observable when the component is ready
        document.addEventListener('cifReady', function () {
            loader.style.display = 'none';
            observable.style.display = 'block';
        });

        // Function to Create the cubx-textarea component using the The Cubbles Tag API.
        function createTextareaComponent() {
            var init = document.createElement('cubx-core-init');
            init.style.display = 'none';
            init.appendChild(createSlotInit('label', '"Textarea label"'));
            init.appendChild(createSlotInit('cols', '40'));
            init.appendChild(createSlotInit('rows', '8'));
            var testTextarea = document.createElement('cubx-textarea');
            testTextarea.setAttribute('cubx-webpackage-id', 'com.incowia.basic-html-components@2.0.0-SNAPSHOT');
            testTextarea.appendChild(init);
            return testTextarea;
        }

        // Function to create a cubx-core-slot-init using the The Cubbles Tag API.
        function createSlotInit(slotName, slotValue) {
            var slotInit = document.createElement('cubx-core-slot-init');
            slotInit.setAttribute('slot', slotName);
            slotInit.innerHTML = slotValue;
            return slotInit;
        }
})()
</script>
```

### The style

Now we need to style the *loader* div, so that it looks like a spinner and let the user know that the component is loading; i.e., the Cubbles RTE is working on getting the component ready. Additionally, we want the *observable* div to be hidden by default. The style should look as follows:

```css
.loader {
    border: 8px solid #f3f3f3;
    border-radius: 50%;
    border-top: 8px solid #3498db;
    width: 30px;
    height: 30px;
    -webkit-animation: spin 2s linear infinite;
    animation: spin 2s linear infinite;
    display: none;
}

@-webkit-keyframes spin {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(360deg); }
}

@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}

#observable{
    display: none;
}
```

### Result

The result of the code above should look as follows:

![Mutation based startevent demo](/files/-LTY5lIeowysCRDgMwj7)

Check [this demo](https://cubbles.world/sandbox/my-first-webpackage@0.1.0-SNAPSHOT/mutation-based-startevent-demos/index.html) to see the result working online.

## Target node added dynamically

Sometimes you would like to add the target node for the mutation observer dynamically; in that case, the utility `mutation-based-cubx-startevent` will wait until the node is added to the body to observe it for changes.

The only thing should do is to append a target node that matches the css selector provided in the `data-cubx-target-selector` attribute.

### A working example

![Mutation based startevent demo with dynamically added target node](/files/-LTY5lIgQx2JwackItZR)

Check [this demo](https://cubbles.world/sandbox/my-first-webpackage@0.1.0-SNAPSHOT/mutation-based-startevent-demos/dynamic-target-node.html) to see the result working online.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://cubbles.gitbook.io/docs/runtime-extension-rte/user-guide/mutation-based-start-event.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
