# Close a dock when opening another - detect when a dock is open?

**URL:** <https://forum.inductiveautomation.com/t/close-a-dock-when-opening-another-detect-when-a-dock-is-open/96661>\
**Category:** Ignition\
**Tags:** ignition81, perspective\
**Created:** [October 1, 2024, 1:42pm UTC](https://forum.inductiveautomation.com/t/close-a-dock-when-opening-another-detect-when-a-dock-is-open/96661 "2024-10-01T13:42:41Z")\
**Posts on this page:** 7\
**Page:** 2

<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:** [October 2, 2024, 2:43pm UTC](https://forum.inductiveautomation.com/t/close-a-dock-when-opening-another-detect-when-a-dock-is-open/96661/21 "2024-10-02T14:43:26Z")

</div>

Oh wait does your top/left dock not have the toggle button?

Yeah thats is... for some reason the ID is only attached to the toggle button...  
I'll take another look at this tmw. But it looks like we will only be able to detect docks with a handle. (if you care about the id)

---

<div class="post-metadata">

**Author:** ![mazeyrat](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mazeyrat/32/10955_2.png) [@mazeyrat](https://forum.inductiveautomation.com/u/mazeyrat)\
**Post date:** [October 2, 2024, 3:04pm UTC](https://forum.inductiveautomation.com/t/close-a-dock-when-opening-another-detect-when-a-dock-is-open/96661/22 "2024-10-02T15:04:21Z")

</div>

Yes, exactly dock top and left are alwals visible, no toogle button !

---

<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:** [October 3, 2024, 7:56am UTC](https://forum.inductiveautomation.com/t/close-a-dock-when-opening-another-detect-when-a-dock-is-open/96661/23 "2024-10-03T07:56:51Z")

</div>

This should do it for multiple docks on the same side, it will not find the docks without handlers though. But you dont want to close those anyways.

> **markdown 'js' binding**
>
> ```python
> #make the propName the key to write too in the view.custom 
> propName = value
> code = """<img style='display:none' src='/favicon.ico' onload=\"
> const view = [...window.__client.page.views._data.values()].find(view => view.value.mountPath == this.closest('[data-component-path]').getAttributeNode('data-component-path').value.split('.')[0]).value; 		
> function getOpenDocks(){
> const openDocks = [];
> for (const side of ['top','right','bottom','left']){										
> const sidedocks = Array.from(document.querySelectorAll('.docked-view-'+side));
> for (const sd of sidedocks){
> const ids = sd.querySelectorAll('[data-dock-id]');
> if (ids.length == 1 && !sd.style.getPropertyValue(side).startsWith('-')){
> openDocks.push(ids[0].getAttribute('data-dock-id'));
> }else if (ids.length > 1){					        	
> const indexId = [...sd.querySelectorAll('.content-wrapper.view-parent > .view')]?.findIndex(x => !x.style?.display);	
> if(indexId > -1){
> openDocks.push(ids[indexId].getAttribute('data-dock-id'));
> }
> }
> }					   
> }					
> view.custom.write('"""+propName+"""',openDocks);
> };
> const callbackDock = (mutationList, observer) => {
> getOpenDocks();
> };
> const observerDocks = new MutationObserver(callbackDock); 
> const docks = document.querySelectorAll('.docked-view, .docked-view > div >.view');
> docks.forEach(dock => observerDocks.observe(dock, { attributes: true, childList: false, subtree: false }));	
> getOpenDocks();	
> \"></img>""".replace("\n", "").replace("\t", "")
> return code
> 	
> 
> ```

> **Markdown**
>
> `[{ "type": "ia.display.markdown", "version": 0, "props": { "style": { "flex": "--neutral-40" }, "markdown": { "escapeHtml": false } }, "meta": { "name": "Markdown" }, "position": { "x": 88, "y": 251, "height": 200, "width": 200 }, "custom": {}, "propConfig": { "props.source": { "binding": { "type": "expr", "config": { "expression": "\"openDocks\"" }, "transforms": [{ "code": "\t#make the propName the key to write too in the view.custom \n\tpropName = value\n\tcode = \"\"\"<img style='display:none' src='/favicon.ico' onload=\\\"\n\t\t\t\tconst view = [...window.__client.page.views._data.values()].find(view => view.value.mountPath == this.closest('[data-component-path]').getAttributeNode('data-component-path').value.split('.')[0]).value; \t\t\n\t\t\t\tfunction getOpenDocks(){\n\t\t\t\t\tconst openDocks = [];\n\t\t\t\t\tfor (const side of ['top','right','bottom','left']){\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t const sidedocks = Array.from(document.querySelectorAll('.docked-view-'+side));\n\t\t\t\t\t for (const sd of sidedocks){\n\t\t\t\t\t const ids = sd.querySelectorAll('[data-dock-id]');\n\t\t\t\t\t if (ids.length == 1 && !sd.style.getPropertyValue(side).startsWith('-')){\n\t\t\t\t\t openDocks.push(ids[0].getAttribute('data-dock-id'));\n\t\t\t\t\t }else if (ids.length > 1){\t\t\t\t\t \t\n\t\t\t\t\t const indexId = [...sd.querySelectorAll('.content-wrapper.view-parent > .view')]?.findIndex(x => !x.style?.display);\t\n\t\t\t\t\t if(indexId > -1){\n \t\t\t\t\t openDocks.push(ids[indexId].getAttribute('data-dock-id'));\n }\n\t\t\t\t\t }\n\t\t\t\t\t }\t\t\t\t\t \n\t\t\t\t\t}\t\t\t\t\t\n\t\t\t\t\tview.custom.write('\"\"\"+propName+\"\"\"',openDocks);\n\t\t\t\t};\n\t\t\t\tconst callbackDock = (mutationList, observer) => {\n\t\t\t\t\tgetOpenDocks();\n\t\t\t\t};\n\t\t\t\tconst observerDocks = new MutationObserver(callbackDock); \n\t\t\t\tconst docks = document.querySelectorAll('.docked-view, .docked-view > div >.view');\n\t\t\t\tdocks.forEach(dock => observerDocks.observe(dock, { attributes: true, childList: false, subtree: false }));\t\n\t\t\t\tgetOpenDocks();\t\n\t\\\"></img>\"\"\".replace(\"\\n\", \"\").replace(\"\\t\", \"\")\n\treturn code\n\t", "type": "script" } ] } } } } ]`

---

<div class="post-metadata">

**Author:** ![mazeyrat](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mazeyrat/32/10955_2.png) [@mazeyrat](https://forum.inductiveautomation.com/u/mazeyrat)\
**Post date:** [October 3, 2024, 12:08pm UTC](https://forum.inductiveautomation.com/t/close-a-dock-when-opening-another-detect-when-a-dock-is-open/96661/24 "2024-10-03T12:08:18Z")

</div>

Thanks a lot ! I still have some case where the list is not ok.  
On the left I have 2 **onDemand shared docks** , and for some pages **I add 2 more docks onDemand**.  
In that case when I select one added Dock (like DOCK\_TREE\_EQT or DOCK\_SAVE\_DATA) and I close it, the dock name stay on the list.

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/8/d/8d4c2f706fee70f67503dcb5586edc1bf8c01e97.png)

---

<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:** [October 3, 2024, 12:23pm UTC](https://forum.inductiveautomation.com/t/close-a-dock-when-opening-another-detect-when-a-dock-is-open/96661/25 "2024-10-03T12:23:00Z")

</div>

Right ondemand docks also has no id sigh, unless you also give it the handle button...

---

<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:** [October 3, 2024, 1:16pm UTC](https://forum.inductiveautomation.com/t/close-a-dock-when-opening-another-detect-when-a-dock-is-open/96661/26 "2024-10-03T13:16:37Z")

</div>

oke i found a way to get all id's, gimme a sec to write it in a script 🧙

@mazeyrat that should do it, found a way to use perspectives client functions.  
One of these days i'll also find the session settings maybe xd Than we wouldnt need the markdown, but no luck yet, its quite a maze to go through without any docs 😛 ...

> **js**
>
> ```python
> #make the propName the key to write too in the view.custom 
> propName = value
> code = """<img style='display:none' src='/favicon.ico' onload=\"
> const view = [...window.__client.page.views._data.values()].find(view => view.value.mountPath == this.closest('[data-component-path]').getAttributeNode('data-component-path').value.split('.')[0]).value; 		
> function getOpenDocks(){
> const openDocks = [];
> for (const side of ['top','right','bottom','left']){										
> const dock = window.__client.mounts?.docks?.get(side);					    
> if(dock?.expanded){
> openDocks.push(dock?.currentViewIndex?.observers?.values()?.next()?.value?.value?.id);                            
> }				   
> }					
> view.custom.write('"""+propName+"""',openDocks);
> };
> const callbackDock = (mutationList, observer) => {
> getOpenDocks();
> };
> const observerDocks = new MutationObserver(callbackDock); 
> const docks = document.querySelectorAll('.docked-view, .docked-view > div >.view');
> docks.forEach(dock => observerDocks.observe(dock, { attributes: true, childList: false, subtree: false }));	
> getOpenDocks();	
> \"></img>""".replace("\n", "").replace("\t", "")
> return code
> 	
> 
> ```

> **markdown**
>
> ```python
> [
> {
> "type": "ia.display.markdown",
> "version": 0,
> "props": {
> "style": {
> "flex": "--neutral-40"
> },
> "markdown": {
> "escapeHtml": false
> }
> },
> "meta": {
> "name": "Markdown_0"
> },
> "position": {
> "x": 88,
> "y": 251,
> "height": 200,
> "width": 200
> },
> "custom": {},
> "propConfig": {
> "props.source": {
> "binding": {
> "type": "expr",
> "config": {
> "expression": "\"openDocks\""
> },
> "transforms": [
> {
> "code": "\t#make the propName the key to write too in the view.custom \n\tpropName = value\n\tcode = \"\"\"<img style='display:none' src='/favicon.ico' onload=\\\"\n\t\t\t\tconst view = [...window.__client.page.views._data.values()].find(view => view.value.mountPath == this.closest('[data-component-path]').getAttributeNode('data-component-path').value.split('.')[0]).value; \t\t\n\t\t\t\tfunction getOpenDocks(){\n\t\t\t\t\tconst openDocks = [];\n\t\t\t\t\tfor (const side of ['top','right','bottom','left']){\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t const dock = window.__client.mounts?.docks?.get(side);\t\t\t\t\t \n if(dock?.expanded){\n openDocks.push(dock?.currentViewIndex?.observers?.values()?.next()?.value?.value?.id); \n }\t\t\t\t \n\t\t\t\t\t}\t\t\t\t\t\n\t\t\t\t\tview.custom.write('\"\"\"+propName+\"\"\"',openDocks);\n\t\t\t\t};\n\t\t\t\tconst callbackDock = (mutationList, observer) => {\n\t\t\t\t\tgetOpenDocks();\n\t\t\t\t};\n\t\t\t\tconst observerDocks = new MutationObserver(callbackDock); \n\t\t\t\tconst docks = document.querySelectorAll('.docked-view, .docked-view > div >.view');\n\t\t\t\tdocks.forEach(dock => observerDocks.observe(dock, { attributes: true, childList: false, subtree: false }));\t\n\t\t\t\tgetOpenDocks();\t\n\t\\\"></img>\"\"\".replace(\"\\n\", \"\").replace(\"\\t\", \"\")\n\treturn code\n\t",
> "type": "script"
> }
> ]
> }
> }
> }
> }
> ]
> 
> ```

---

<div class="post-metadata">

**Author:** ![aeliares](https://avatars.discourse-cdn.com/v4/letter/a/9fc29f/32.png) [@aeliares](https://forum.inductiveautomation.com/u/aeliares)\
**Post date:** [December 1, 2025, 5:51pm UTC](https://forum.inductiveautomation.com/t/close-a-dock-when-opening-another-detect-when-a-dock-is-open/96661/27 "2025-12-01T17:51:13Z")

</div>

Hey all, this issue has been resolved and you will now be able to modify multiple docks using system.perspective.alterDock without the last changes being reverted in 8.3.3.

[Previous page](https://forum.inductiveautomation.com/t/close-a-dock-when-opening-another-detect-when-a-dock-is-open/96661.md?page=1)
