# Adding an outside widget to composer

**URL:** https://meta.discourse.org/t/adding-an-outside-widget-to-composer/207563
**Category:** Development
**Created:** [October 29, 2021, 4:39pm UTC](https://meta.discourse.org/t/adding-an-outside-widget-to-composer/207563 "2021-10-29T16:39:14Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![Dugen](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/dugen/32/198936_2.png) [@Dugen](https://meta.discourse.org/u/Dugen)
#### Post date: [October 29, 2021, 4:39pm UTC](https://meta.discourse.org/t/adding-an-outside-widget-to-composer/207563/1 "2021-10-29T16:39:14Z")

</div>

Im trying to add a widget to the composer, I have got far enough to where I can insert the code from the tool bar, but I am not sure how to get the javascript working within it. I am assuming that I will need to add the javascript internally either as a plug-in or theme component rather than calling it from an external site, but I am not sure how to go about doing that. Is this doable within the composer?

---

<div class="post-metadata">

### Author: ![awesomerobot](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/awesomerobot/32/142900_2.png) [@awesomerobot](https://meta.discourse.org/u/awesomerobot)
#### Post date: [October 29, 2021, 4:44pm UTC](https://meta.discourse.org/t/adding-an-outside-widget-to-composer/207563/2 "2021-10-29T16:44:36Z")

</div>

Can you be a little more specific about what you’re trying to do? Are you trying to add a new toolbar button that adds content to the composer textarea? something else?

---

<div class="post-metadata">

### Author: ![Dugen](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/dugen/32/198936_2.png) [@Dugen](https://meta.discourse.org/u/Dugen)
#### Post date: [October 29, 2021, 4:50pm UTC](https://meta.discourse.org/t/adding-an-outside-widget-to-composer/207563/3 "2021-10-29T16:50:32Z")

</div>

What I am trying to is to have users insert their specific widget from the composer where all the would have to do type a number and have the toolbar wrap around it. for example if typed 112756 it would wrap the following code around it.

```plaintext
<div id='PurpleAirWidget_112756_module_AQI_conversion_C0_average_10_layer_detailed'>Loading PurpleAir Widget...</div>
<script src='https://www.purpleair.com/pa.widget.js?key=N6HB6JJ0BP1Z05SE&module=AQI&conversion=C0&average=10&layer=detailed&container=PurpleAirWidget_112756_module_AQI_conversion_C0_average_10_layer_detailed'></script>

```

it would hopefully look something like this

 ![Screen Shot 2021-10-29 at 10.51.44 AM](https://global.discourse-cdn.com/meta/original/3X/1/6/16e5065b4e710dc65575b522225fb351c439ff87.png)

---

<div class="post-metadata">

### Author: ![awesomerobot](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/awesomerobot/32/142900_2.png) [@awesomerobot](https://meta.discourse.org/u/awesomerobot)
#### Post date: [October 29, 2021, 5:36pm UTC](https://meta.discourse.org/t/adding-an-outside-widget-to-composer/207563/4 "2021-10-29T17:36:28Z")

</div>

Ok so it sounds like you have already figured out how to add content to the composer? (If not, referencing this example may help [GitHub - discourse/discourse-gifs · GitHub](https://github.com/discourse/discourse-gifs) - this theme component opens a modal when the button is clicked from the toolbar, and then inserts content into the composer based on clicking some content in the modal).

If you’re trying to get a script to load and do something to the post content, I think this post might get you pointed in the right direction… using `loadScript` and `decorateCooked`: [Difficulties in correctly adding external JavaScript - #4 by StevenTammen](https://meta.discourse.org/t/difficulties-in-correctly-adding-external-javascript/118099/4)

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [October 29, 2021, 5:56pm UTC](https://meta.discourse.org/t/adding-an-outside-widget-to-composer/207563/5 "2021-10-29T17:56:42Z")

</div>

You might be able to use this in some way (either directly or a forked customisation): [Mentionables](https://meta.discourse.org/t/custom-mentionables/192948) which uses a special character instead of a composer button.

---

<div class="post-metadata">

### Author: ![Dugen](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/dugen/32/198936_2.png) [@Dugen](https://meta.discourse.org/u/Dugen)
#### Post date: [November 8, 2021, 9:23pm UTC](https://meta.discourse.org/t/adding-an-outside-widget-to-composer/207563/6 "2021-11-08T21:23:43Z")

</div>

Thanks for pointing me in the right direction, I do seem to run into another issue, it is not loading/rendering when opening the topic page that would use the script. Only after I refresh the page does it load properly, but not every time. Is this because Discourse is a Single Page Application, I’m am just trying to figure out if my knowledge of Discourse is lacking or if something that I need to program my self.

Here is the current code I am using. Any direction would be greatly appreciated

```plaintext
 let loadScript = require('discourse/lib/load-script').default;
  api.decorateCooked($elem => { $elem.children('div[data-PAWidget]').ready(function() {
         $elem.children('div[data-PAWidget]').append(" <div id='PurpleAirWidget_11726_module_AQI_conversion_C0_average_0_layer_standard'>Loading PurpleAir Widget...</div>");
       loadScript("https://www.purpleair.com/pa.widget.js?key=21R72LUN79CXRZ50&module=AQI&conversion=C0&average=0&layer=standard&container=PurpleAirWidget_11726_module_AQI_conversion_C0_average_0_layer_standard").then(()=>{       
    })  
  })     
  });

```

---

<div class="post-metadata">

### Author: ![awesomerobot](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/awesomerobot/32/142900_2.png) [@awesomerobot](https://meta.discourse.org/u/awesomerobot)
#### Post date: [November 9, 2021, 2:13am UTC](https://meta.discourse.org/t/adding-an-outside-widget-to-composer/207563/7 "2021-11-09T02:13:44Z")

</div>

I took a crack at this and ended up with similar results. I tried to use `decorateCookedElement` because we’ll eventually deprecate `decorateCooked`

```js
 api.decorateCookedElement(
    (element) => {
      element.childNodes.forEach((node) => {
        if (node.dataset && node.dataset.pawidget) {
          node.insertAdjacentHTML(
            "beforeend",
            "<div id='PurpleAirWidget_11726_module_AQI_conversion_C0_average_0_layer_standard'>Loading PurpleAir Widget...</div>"
          );

          loadScript(
            `https://www.purpleair.com/pa.widget.js?key=${node.dataset.pawidget}&module=AQI&conversion=C0&average=0&layer=standard&container=PurpleAirWidget_11726_module_AQI_conversion_C0_average_0_layer_standard`
          );
        }
      });
    },
    { id: "widget-append", onlyStream: true, afterAdopt: true }
  );

```

Slight difference here is that I passed in the key with the data attribute:

```xml
<div data-PAWidget="21R72LUN79CXRZ50"></div>

```

This works ok for me _if_ it’s the first time the script has been loaded. If I view a post with the script, then go back to the topic list and re-enter the topic, it does not work (until I refresh). I can see `decorateCookedElement` is firing each time when the relevant post is loaded, but there’s something preventing the script from working again.

I’m not sure if it’s related, but I also see a `Uncaught TypeError: i is null` error in the console from `pa.widget.js`:

![Screen Shot 2021-11-08 at 9.11.39 PM](https://global.discourse-cdn.com/meta/optimized/3X/e/0/e011ede9e70096522d175a0306c4cb9088a199a2_2_690x65.png)

---

<div class="post-metadata">

### Author: ![Dugen](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/dugen/32/198936_2.png) [@Dugen](https://meta.discourse.org/u/Dugen)
#### Post date: [November 9, 2021, 11:05pm UTC](https://meta.discourse.org/t/adding-an-outside-widget-to-composer/207563/8 "2021-11-09T23:05:46Z")

</div>

Thanks for taking a crack at it. I did notice that the script is called roughly every 90 seconds to two minutes if I leave the page open.

 ![Screen Shot 2021-11-09 at 3.52.24 PM](https://global.discourse-cdn.com/meta/original/3X/1/0/1098f45e902837485a23231ad099ad1b78a2554d.png)  
So it does load eventually. Is there any documentation/posts on how/why it loads in at a later point?
