# JS Injection Hack Usefuls (JavaScript)

**URL:** <https://forum.inductiveautomation.com/t/js-injection-hack-usefuls-javascript/114714>\
**Category:** Ignition\
**Tags:** perspective\
**Created:** [March 27, 2026, 6:43am UTC](https://forum.inductiveautomation.com/t/js-injection-hack-usefuls-javascript/114714 "2026-03-27T06:43:40Z")\
**Posts on this page:** 1\
**Showing post:** 4

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [March 27, 2026, 9:21am UTC](https://forum.inductiveautomation.com/t/js-injection-hack-usefuls-javascript/114714/4 "2026-03-27T09:21:59Z")

</div>

## Accordian - Allow smooth scrolling to items based on item index

This allows you to scroll an Accordian component to show a specific item, given an item index and the Accordian’s `domId`.

### Instructions

1. Copy the JSON below and paste it into your View with the Accordian.

2. To your accordian component, add the `meta.domId` key and set it to something unique like “Accordian”

3. Inside the “JSInject\_Accordian\_ScrollToIndex” component, set the “accordianDomId” to what you set it to. Then you can scroll to a specific item index by setting the `custom.index` to the index number. You can bind to this or set its value via script

### Resources

> **Markdown Version (Includes 2x Markdown components)**
>
> This contains 2x Markdown components:
> 
> - “JSInject\_Accordian\_ScrollToIndexBase” injects the JS function `scrollToAccordionItem`
> - “JSInject\_Accordian\_ScrollToIndex” calls the function with the domID of the accordian to scroll, and the index to scroll to, based on custom props on the component.
> 
> ```json
> [
> {
> "type": "ia.display.markdown",
> "version": 0,
> "props": {
> "style": {
> "position": "absolute"
> },
> "markdown": {
> "escapeHtml": false
> }
> },
> "meta": {
> "name": "JSInject_Accordian_ScrollToIndexBase"
> },
> "position": {
> "shrink": 0,
> "basis": 0
> },
> "custom": {
> "inlineJavascript": "window.scrollToAccordionItem = function(id, index) {\n const accordion = document.querySelector('#' + id + '.ia_accordionComponent');\n if (!accordion) {\n console.warn('Accordion component not found for id: ' + id);\n return;\n }\n\n const wrapper = accordion.querySelector('.ia_accordionComponent__wrapper');\n const header = wrapper.querySelector('.ia_accordionComponent__header[data-index=&quot;' + index + '&quot;]');\n\n if (!header) {\n console.warn('Accordion item with index ' + index + ' not found.');\n return;\n }\n\n const accordionTop = accordion.getBoundingClientRect().top;\n const headerTop = header.getBoundingClientRect().top;\n const offset = headerTop - accordionTop;\n\n accordion.scrollTo({\n top: accordion.scrollTop + offset,\n behavior: 'smooth'\n });\n };"
> },
> "propConfig": {
> "custom.inlineJavascript": {
> "access": "PRIVATE"
> },
> "props.source": {
> "binding": {
> "config": {
> "struct": {
> "script": "{this.custom.inlineJavascript}"
> },
> "waitOnAll": true
> },
> "transforms": [
> {
> "code": "#\tcode = \"<img style='display:none' src='/favicon.ico' onload=\\\"\" + value.script.replace('\"', '&quot;') + '\\\"></img>'\n#\t\n#\tcode = code.replace(\"\\n\", \"\").replace(\"\\t\", \"\").replace(\"\\n\", \"\").replace(\"\\r\", \"\").replace(\"\\r\", \"\").replace(\" \", \" \").replace(\" \", \" \").replace(\" \", \" \").replace(\" \", \" \")\n#\t\n#\treturn code\n\tscript = value.script\n\tscript = script.replace('\"', '&quot;')\n\tscript = script.replace('\\n', '').replace('\\t', '').replace('\\r', '')\n\t\n\t# Collapse multiple spaces - repeat until stable\n\twhile ' ' in script:\n\t script = script.replace(' ', ' ')\n\t\n\tcode = '<img style=\"display:none\" src=\"/favicon.ico\" onload=\"{}\"></img>'.format(script)\n\treturn code",
> "type": "script"
> }
> ],
> "type": "expr-struct"
> }
> }
> }
> },
> {
> "type": "ia.display.markdown",
> "version": 0,
> "props": {
> "style": {
> "position": "absolute"
> },
> "markdown": {
> "escapeHtml": false
> }
> },
> "meta": {
> "name": "JSInject_Accordian_ScrollToIndex"
> },
> "position": {
> "shrink": 0,
> "basis": 0
> },
> "custom": {
> "accordianDomId": "ME",
> "index": 3
> },
> "propConfig": {
> "custom.accordianDomId": {
> "access": "PRIVATE"
> },
> "custom.index": {
> "access": "PRIVATE"
> },
> "custom.inlineJavascript": {
> "binding": {
> "config": {
> "expression": "if({this.custom.index} != \"\"\r\n\t,\"(function() {scrollToAccordionItem('\" + {this.custom.accordianDomId} + \"', \" + {this.custom.index} + \");})();\"\r\n \t,\"\"\r\n)"
> },
> "type": "expr"
> },
> "access": "PRIVATE"
> },
> "props.source": {
> "binding": {
> "config": {
> "struct": {
> "script": "{this.custom.inlineJavascript}"
> },
> "waitOnAll": true
> },
> "transforms": [
> {
> "code": "#\tcode = \"<img style='display:none' src='/favicon.ico' onload=\\\"\" + value.script.replace('\"', '&quot;') + '\\\"></img>'\n#\t\n#\tcode = code.replace(\"\\n\", \"\").replace(\"\\t\", \"\").replace(\"\\n\", \"\").replace(\"\\r\", \"\").replace(\"\\r\", \"\").replace(\" \", \" \").replace(\" \", \" \").replace(\" \", \" \").replace(\" \", \" \")\n#\t\n#\treturn code\n\tscript = value.script\n\tscript = script.replace('\"', '&quot;')\n\tscript = script.replace('\\n', '').replace('\\t', '').replace('\\r', '')\n\t\n\t# Collapse multiple spaces - repeat until stable\n\twhile ' ' in script:\n\t script = script.replace(' ', ' ')\n\t\n\tcode = '<img style=\"display:none\" src=\"/favicon.ico\" onload=\"{}\"></img>'.format(script)\n\treturn code",
> "type": "script"
> }
> ],
> "type": "expr-struct"
> }
> }
> }
> }
> ]
> 
> ```

> **Periscope Version (N/A yet)**
>

---

_[View the full topic](https://forum.inductiveautomation.com/t/js-injection-hack-usefuls-javascript/114714)._
