# On JavaScript injection in markdown component

**URL:** <https://forum.inductiveautomation.com/t/on-javascript-injection-in-markdown-component/92718>\
**Category:** Ignition\
**Tags:** perspective, scripting\
**Created:** [July 2, 2024, 9:15pm UTC](https://forum.inductiveautomation.com/t/on-javascript-injection-in-markdown-component/92718 "2024-07-02T21:15:26Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Melany\_Monroy](https://avatars.discourse-cdn.com/v4/letter/m/977dab/32.png) [@Melany\_Monroy](https://forum.inductiveautomation.com/u/Melany_Monroy)\
**Post date:** [July 2, 2024, 9:15pm UTC](https://forum.inductiveautomation.com/t/on-javascript-injection-in-markdown-component/92718/1 "2024-07-02T21:15:26Z")

</div>

Sooo in perspective you got this markdown component to parse markdown and HTML if you check `escapeHtml: true`. There are some few posts on this feature, I'd like to point some things out as I know someone else will find them useful though.

![markdown](https://us1.discourse-cdn.com/inductiveautomation/original/3X/d/6/d666f39963ad1efba5902ffa7c223937f2ce96a2.png)

1. Not every javascript event works out and if they do, not all of them as expected. In my script at the bottom of this post `onLoad` event did not work, for instance.
2. Whether the script has tab spaces and white spaces do affect its functionality. Sometimes it won't matter, sometimes that'll stop your script from running, so if you are up to try js scripting within this component be prepared to test the exact same script with some extra or less white/tab spaces.
3. Variables can be assigned and used, but it seems in a limited manner. If you're going to use the DOM to change, modify or use visual properties of components that you cannot modify otherwise (within the designer or project root) you may consider using it as directly as possible instead of defining variables for the sake of readability. Example: may work: `document.getElementById(...).innerHtml = document.getElementsByClass(...)`; may work too, but more likely won't: `var test = document.getElementById(...); document.getElementsByClass(...) = test.innerHtml`
4. This scripting has priority over React variables states setting; this means that if a label component, for instance, is changed through a js code within a markdown component no binding will make it behave differently, so this label would ultimately exists and be useful to you from markdown scripting and not the designer anymore.
5. Arrow functions do not work in the event you want to handle the script on. Instead, use regular functions. However, within this function arrow functions do work. Example: works: `onClick="function test() {..}; test();"` doesn't work: `onClick="()=>{}"`

These were my observations. I'm leaving the screenshot of my markdown component and the content of its `source` prop. If you know JavaScript, have a lot of fun and any feedback, advice or observation is more than welcome 🙂

![markdownSource](https://us1.discourse-cdn.com/inductiveautomation/original/3X/0/f/0f0bcbbccb922ab239506acb5ec1a9a0c2f2472c.png)

```python
function test(){
try{var table=document.querySelector('.ia_table.ia_container--secondary');if(table){table.addEventListener('click', () => {document.getElementById('eventValue-val').innerHTML=document.getElementById(document.querySelector('.rowSelectedOverlay~div~[data-column-id=\'eventValue\'] > div > div').innerHTML + 'fc').innerHTML;});}}catch (e) {};

```

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [July 3, 2024, 6:43am UTC](https://forum.inductiveautomation.com/t/on-javascript-injection-in-markdown-component/92718/2 "2024-07-03T06:43:25Z")

</div>

Take a look at some of my posts, i do a bunch of stuff with markdown js.  
There is a lot more you can do with this.

With some string replace, i fixed the space/tab formatting issues, allowing you to code a bit more cleanly.  
Using an img' onload function you can trigger anything screen wide,  
With some mutation observers you can trigger stuff on data changes (quite advanced js knowledge required).  
With window.\_\_client, you can access perspective properties and even write to them ect.

> [@Javascript inject in Perspective... have fun](https://forum.inductiveautomation.com/t/javascript-inject-in-perspective-have-fun/65805/5):
>
> Gonna try to keep this topic updated with all my cool injectings stuck_out_tongue Version 8.1.22 svg clicker wink

> [@Dragging rows in Perspective Table](https://forum.inductiveautomation.com/t/dragging-rows-in-perspective-table/68922/8):
>
> ah it was easy, ignition puts its row id in a data atrribute so it was easy to read. @jasoncoope[dragtable.zip](https://forum.inductiveautomation.com/uploads/short-url/AvXF36eUYUY52tcHnheVhENIotA.zip) (27.7 KB) copy the markdown and add in a custom property on the view you probably will have to adapt the onchange script in the view.custom element to your needs. sometimes the columns seem to move around too when you drag a row... not sure why or how to prevent that... probably clashing with the other drag events on the table xd edit : ahah, turn this off too, well unless you d…

> [@SVG Elements Mouse Clicked](https://forum.inductiveautomation.com/t/svg-elements-mouse-clicked/56528/10):
>
> Made something new for 8.1.22

(ive done a lot of stuff so these are just a few examples)

It can also be used to add some dynamic css to parts of components that otherwise cant be accesed

> [@\[FEATURE\] Add ability to add Icon and styling to Perspective Dropdown items](https://forum.inductiveautomation.com/t/feature-add-ability-to-add-icon-and-styling-to-perspective-dropdown-items/73823/2):
>
> put this in the markdown component binding like usual you'll ofc will have to add some python logic to append the style string based on the required labels in de dropdown (idk if everyone has these Builtin/icons or is it from my test project?) styles=".iaDropdownCommon\_options [data-label='YourLabel']:before { content: url('/system/images/Builtin/icons/16/check2.png'); }" code = """\<style\> """+styles+""" \"\>\</style\>""".replace("\n", "").replace("\t", "") return code

Not the markdown, but another way to add js in perspective, though i have not really done a lot with this yet

> [@\[feature-748\]Perspective Favicon](https://forum.inductiveautomation.com/t/feature-748-perspective-favicon/24642/29):
>
> Soo i got something for you mage Create these files (and injectables folder) (depending on install folder ofc) "C:\Program Files\Inductive Automation\Ignition\data\modules\com.inductiveautomation.perspective\injectables\head\_bottom.txt" "C:\Program Files\Inductive Automation\Ignition\webserver\webapps\main\newFavicon.ico" In the head\_bottom.txt put this: \<script\> const oldLinks = document.querySelectorAll('link[rel\*="icon"]'); oldLinks.forEach(e =\> {e.href = '/newFavicon.ico';}); \</script\>…

---

<div class="post-metadata">

**Author:** ![kgamble](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kgamble/32/8019_2.png) [@kgamble](https://forum.inductiveautomation.com/u/kgamble)\
**Post date:** [March 14, 2025, 3:36am UTC](https://forum.inductiveautomation.com/t/on-javascript-injection-in-markdown-component/92718/3 "2025-03-14T03:36:41Z")

</div>

Taking a look at these, I haven't been able to find this out, but is there a way to just have the markdown presence invoke running a script that adds content into the page?

For example this static doc

```python
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Jira Widget Static Test</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>

<body>
    <script data-jsd-embedded data-key="random-generated-key-here"
        data-base-url="https://jsd-widget.atlassian.com"
        src="https://jsd-widget.atlassian.com/assets/embed.js"></script>
</body>

</html>

```

I have tried to get the markdown to trigger the script with just the

```python
<script data-jsd-embedded data-key="random-generated-key-here"
        data-base-url="https://jsd-widget.atlassian.com"
        src="https://jsd-widget.atlassian.com/assets/embed.js"></script>

```

But I cant seem to get to do it. I am open to ideas though if anyone knows

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [March 14, 2025, 7:34am UTC](https://forum.inductiveautomation.com/t/on-javascript-injection-in-markdown-component/92718/4 "2025-03-14T07:34:50Z")

</div>

`<scripts>` dont really get triggered like that no. Thats why i always have to wrap "scripts" into the onload of an img

You should be able to add it through the injectables though.

> [@\[feature-748\]Perspective Favicon](https://forum.inductiveautomation.com/t/feature-748-perspective-favicon/24642/29):
>
> Soo i got something for you mage Create these files (and injectables folder) (depending on install folder ofc) "C:\Program Files\Inductive Automation\Ignition\data\modules\com.inductiveautomation.perspective\injectables\head\_bottom.txt" "C:\Program Files\Inductive Automation\Ignition\webserver\webapps\main\newFavicon.ico" In the head\_bottom.txt put this: \<script\> const oldLinks = document.querySelectorAll('link[rel\*="icon"]'); oldLinks.forEach(e =\> {e.href = '/newFavicon.ico';}); \</script\>…

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [March 14, 2025, 12:41pm UTC](https://forum.inductiveautomation.com/t/on-javascript-injection-in-markdown-component/92718/5 "2025-03-14T12:41:07Z")

</div>

_Pssssst!_ @bmusson

---

<div class="post-metadata">

**Author:** ![bmusson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bmusson/32/87530_2.png) [@bmusson](https://forum.inductiveautomation.com/u/bmusson)\
**Post date:** [March 14, 2025, 1:50pm UTC](https://forum.inductiveautomation.com/t/on-javascript-injection-in-markdown-component/92718/6 "2025-03-14T13:50:05Z")

</div>

> **[Dynamically Embedding Service Desk Widget](https://community.atlassian.com/forums/Jira-Service-Management/Dynamically-Embedding-Service-Desk-Widget/qaq-p/899686)**
>
> Does anyone know why when I insert the widget embed directly into the html file, it works.. but if I do it dynamicaly via JavaScript, it loads the js file but does not display the widget? Inserting this directly into the works:

I can get this to do _something_, but without the `data-key` I don't think there's much I can test.

```javascript
() => {
    const loadJiraWidget = (callback) => {
        const jhdScript = document.createElement('script')
        jhdScript.type = 'text/javascript';
        jhdScript.setAttribute('data-jsd-embedded', null)
        jhdScript.setAttribute('data-key', 'YOUR_KEY_HERE')
        jhdScript.setAttribute('data-base-url', 'https://jsd-widget.atlassian.com')
        jhdScript.src = 'https://jsd-widget.atlassian.com/assets/embed.js'
        jhdScript.onload = callback

        document.getElementsByTagName('head')[0].appendChild(jhdScript)
    }

    loadJiraWidget(() => {
        const DOMContentLoaded_event = document.createEvent('Event')
        DOMContentLoaded_event.initEvent('DOMContentLoaded', true, true)
        window.document.dispatchEvent(DOMContentLoaded_event)
    })
}

```

Options for running the code:

1. Call it from the gateway using [`system.perspective.runJavaScriptAsync`](https://docs.mussonindustrial.com/ignition/embr-periscope/scripting/perspective/system-perspective-runJavaScriptAsync).
2. Add it to an `events.dom.onMount` function of the `Chart.js` component.

I have plans to add a component that acts as a place to run scripts like this (and isn't also an entire chart 😆), but this is what we've got now.
