Here’s a gif illustration featuring a decent-looking expandable menu system for a form I’m working on. Instead of trying to fit all the required fields into a single visible panel, I wanted the user to be able to view information on demand, and only have the pertinent asset info at the top of the element set.

Here’s the javascript, and this code goes in the “Script” section in the Form Builder canvas options (note – if you copy/paste, paste it first into Notepad so that the html doesn’t come along too):
/// declare global css classes classCollapsed = 'gaMenuPanelCollapsed'; classExpanded = 'gaSmallDetailsPanel'; /// collapse called panel function collapsePanel(panelid){ panelid.className = classCollapsed; } /// expand called panel function expandPanel(panelid){ panelid.className = classExpanded; } function setPanels(label, panel){ /// declare variables var panelOne = document.getElementById('Panel1'); var panelTwo = document.getElementById('Panel2'); var panelThree = document.getElementById('Panel3'); var labelOne = document.getElementById('Label1'); var labelTwo = document.getElementById('Label2'); var labelThree = document.getElementById('Label3'); /// declare array variables var panels = [panelOne, panelTwo, panelThree]; var labels = [labelOne, labelTwo, labelThree]; /// declare clicked section variables var labelElem = document.getElementById(label); var panelElem = document.getElementById(panel); /// flag current panel state var panelOpen; if (panelElem.className == classCollapsed) { panelOpen = 'False'; } else { panelOpen = 'True'; } /// declare button var goButton = document.getElementById('GoButton'); /// collapse panels for (i = 0; i < panels.length; i++) { collapsePanel(panels[i]); } /// reset labels and panels for (i = 0; i < labels.length; i++) { if (labels[i] != labels[0]) { var prevLabelIndex = (i - 1); var prevLabel = labels[prevLabelIndex]; labels[i].style.top = parseInt(prevLabel.style.top) + parseInt(prevLabel.style.height); panels[i].style.top = parseInt(prevLabel.style.top) + parseInt(prevLabel.style.height) + parseInt(labels[i].style.height); } } if (panelOpen === 'False') { expandPanel(panelElem); /// declare and refresh expanded panel height var panelElem = document.getElementById(panel); /// adjust labels and panels for (i = 0; i < labels.length; i++) { if (labels[i] != labels[0]) { if (parseInt(labels[i].style.top) > parseInt(labelElem.style.top)) { labels[i].style.top = parseInt(labels[i].style.top) + parseInt(panelElem.style.height); panels[i].style.top = parseInt(labels[i].style.top) + parseInt(labels[i].style.height) - 2; } } } } /// declare last panel in array var lastPanel = panels[panels.length - 1]; /// move button if (lastPanel.className == classCollapsed) { goButton.style.top = parseInt(lastPanel.style.top) + 8; } else { goButton.style.top = parseInt(lastPanel.style.top) + parseInt(lastPanel.style.height) + 8; } }
and here’s the CSS that goes into the IncludeHTML component on the Form canvas:
<style> /***Buttons***/ .gaButton1 { text-transform: uppercase; font-family: Verdana, Serif; font-size: 14px; letter-spacing: .5px; border: none; text-align: center; color: white; background-color: #569fbe; outline: none !important; padding-bottom: 2px; cursor: pointer; -webkit-appearance: none; border-radius: 6px; outline: none; -moz-transition: top 200ms ease-in-out; -o-transition: top 200ms ease-in-out; -webkit-transition: top 200ms ease-in-out; transition: top 200ms ease-in-out; } /******************************************/ /******************************************/ /***Labels***/ .gaSmallDetailsLabel { color: #666666; font-family: Verdana, Serif; text-align: right; font-size: 14px; padding-right: 5px; background-color: #f2f4fa; } .gaSmallDetailsData { color: #999999; font-family: Verdana, Serif; text-align: left; font-size: 14px; font-weight: normal; border-left: solid 2px #6dbdef; padding-left: 5px; z-index: 2; } .gaTitleLabel { color: #808080; font-family: Verdana, Serif; text-align: left; font-size: 18px; font-weight: 500; -webkit-font-smoothing: antialiased; } .gaMenuLabel { color: #ffffff; background: #b3b3b3; padding-left: 12px; padding-top: 3px; font-size: 14px; font-family: Verdana, Serif; font-weight: 500; border-left: solid 3px #5888d2; cursor: pointer; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; -moz-transition: all 200ms ease-in-out; -o-transition: all 200ms ease-in-out; -webkit-transition: all 200ms ease-in-out; transition: all 200ms ease-in-out; } .gaMenuLabel:hover { background: #999999; } /******************************************/ /******************************************/ /***Panels***/ .gaSmallDetailsPanel { border: solid 1px #b3b3b3; -moz-transition: all 200ms ease-in-out; -webkit-transition: all 200ms ease-in-out; -o-transition: all 200ms ease-in-out; transition: all 200ms ease-in-out; } .gaMenuPanelCollapsed { height: 0px !important; border: solid 1px #b3b3b3; -moz-transition: all 200ms ease-in-out; -webkit-transition: all 200ms ease-in-out; -o-transition: all 200ms ease-in-out; transition: all 200ms ease-in-out; } /******************************************/ </style>
The form should be structured properly as well, with the panel labels and their child panels cascading top to bottom in reverse z-index order. The z-index is adjusted with these buttons in the Form designer:


The only onclick javascript needed for each panel label is this:
setPanels(this.id, 'Panel1');
where the “Panel1” is the Control Id of the label’s child panel. This pipes the proper values into the backend script function.
In the original code I created for this feature, no functions or reusable code was implemented and every label contained everything it needed onclick to move everything else around. This became exceptionally convoluted and tedious. Adding another panel (I already had 7 in use) would have been a terrible ordeal. Adding additional panels/sections to this new, extensible code takes about 3 minutes and works seamlessly.
To extend the code, attend the label onclick event itself, the control ids of the new panel and label, and adjust the javascript variables and arrays in the form script here:
/// declare variables var panelOne = document.getElementById('Panel1'); var panelTwo = document.getElementById('Panel2'); var panelThree = document.getElementById('Panel3'); var labelOne = document.getElementById('Label1'); var labelTwo = document.getElementById('Label2'); var labelThree = document.getElementById('Label3'); /// declare array variables var panels = [panelOne, panelTwo, panelThree]; var labels = [labelOne, labelTwo, labelThree];
After adding a 4th and 5th section, the code looks like this:
/// declare variables var panelOne = document.getElementById('Panel1'); var panelTwo = document.getElementById('Panel2'); var panelThree = document.getElementById('Panel3'); var panelFour = document.getElementById('Panel4'); var panelFive = document.getElementById('Panel5'); var labelOne = document.getElementById('Label1'); var labelTwo = document.getElementById('Label2'); var labelThree = document.getElementById('Label3'); var labelFour = document.getElementById('Label4'); var labelFive = document.getElementById('Label5'); /// declare array variables var panels = [panelOne, panelTwo, panelThree, panelFour, panelFive]; var labels = [labelOne, labelTwo, labelThree, labelFour, labelFive];
Send along any questions, or suggestions for my humble attempt at extensible javascript functions.
Here is a moving picture of the results of the test scripts above.
Hi,
Can you share more details about these collapsing menus and How exactly you made it work with Workflow. It seems very interesting and I think I can make a good use of it in my application.
Regards
Sandeep
LikeLike
Ok Sandeep – scripts restructured and more details posted. Let me know if you need any more info.
LikeLike
Hi,
Can you post more details.
Iwas able to make Panel 1 and 2 work, but Panel 3 is static and when i click nothing happens.
All text is visible too.
See
Regards
Dldraco
LikeLike
Thanks Andrew, Appreciate it 🙂
LikeLike
Hello Draco – on first glance, it looks like your panels are set to “overflow”. Change that property on your workflow elements themselves (in the “Appearance” tab, “Overflow Behavior” field) to “Clip” instead.
There’s a typo in your code, as well, where:
<span id="Label3" class="cgaMenuLabel" name="Label3" onclick="setPanels(this.id, 'Panel3);"
is missing a closing apostrophe after the "Panel3" value in the onclick function call. It should be:
<span id="Label3" class="cgaMenuLabel" name="Label3" onclick="setPanels(this.id, 'Panel3');".
Try those adjustments in Workflow and ignore the Codepen positioning. Let me know how it looks afterwards, and if you're still running into issues.
LikeLike
Sandeep – glad to help!
LikeLike