This solution was built on 10.2.1.1, but should work on all versions after 10.2. Versions prior to 10.2 will need some rewriting as this is based on the Prompt API.
One of the biggest complaints I get about search prompts is the amount of real estate they take from reports. The multiselect prompts are huge, and users hate them for it. So I was asked to find a way to shrink it down.
Obviously the solution was to everything but the search input and button. The keyword and instruction text can be controlled by the properties, simply setting it to “Specified Text” is sufficient to hide them:
That leaves the Options link and the search results. Personally I don’t believe the results list need to appear unless there are actually results. The options should be at the mercy of the report author, so my solution includes a way to choose a default value and to hide the options.
First a look at the JS
14 | paulScripts.advancedSnS = function (promptName,option,hideOption){ |
15 | var prompt = paulScripts.getControl(promptName) |
16 | , elm = document.getElementsByName(prompt.getParameterName())[0].parentNode |
17 | , selectTable = elm.getElementsByTagName( 'table' )[4] |
18 | , selectDiv = document.createElement( 'div' ) |
19 | , selectOptions = cognos.Report.getReport( "_THIS_" ).prompt.getControlByName(promptName).getSelectOptions() |
20 | , selectChoices = cognos.Report.getReport( "_THIS_" ).prompt.getControlByName(promptName).getSelectChoices() |
21 | , tr = elm.getElementsByTagName( 'button' )[0].parentNode.parentNode.parentNode.appendChild(document.createElement( 'tr' )) |
22 | , td= tr.insertCell(0) |
23 | , slideDiv = document.createElement( 'div' ) |
24 | , btn = document.createElement( 'input' ); |
27 | if (option) elm.getElementsByTagName( 'input' )[option+2].checked= true ; |
28 | if (hideOption) tr.parentNode.parentNode.parentNode.parentNode.nextSibling.style.display= 'none' ; |
29 | td.setAttribute( 'colSpan' ,2); |
32 | if ( typeof oReq === 'undefined' ) oReq = new ViewerDispatcherEntry(window[ 'oCV' + '_THIS_' ].getRV().getCV()); |
33 | if (!oReq.getFormFields().m_aValues[promptName]) oReq.addFormField(promptName, 'hidden' ) |
38 | if (!selectOptions&&!selectChoices) btn.value= 'click to open' ; |
39 | if (selectOptions) btn.value = selectOptions.length + ' found. ' ; |
40 | if (selectChoices) btn.value += selectChoices.c.length + ' selected.' ; |
42 | selectTable.parentNode.insertBefore(selectDiv,selectTable); |
43 | selectDiv.appendChild(selectTable); |
46 | selectDiv.style.paddingRight= '5px' ; |
50 | selectDiv.style.position= 'absolute' ; |
51 | selectDiv.style.overflow= 'hidden' ; |
52 | selectDiv.style.backgroundColor= 'white' ; |
54 | btn.onclick = function () { |
55 | if (selectDiv.style.visibility== 'hidden' ) |
56 | {slidedown(selectDiv); |
57 | oReq.addFormField(promptName, 'visible' );} |
58 | else {slideup(selectDiv);oReq.addFormField(promptName, 'hidden' );} |
63 | selectDiv.style.visibility=oReq.getFormFields().m_aValues[promptName]; |
The JS itself is fairly straight forward. The variables define the DOM element, a JSON array of the found options, another JSON array of the selected objects, and a couple of generated elements.
If a default search option is selected, it will set that.
1 | if(option) elm.getElementsByTagName('input')[option+2].checked=true; |
If hideOption is set to true, it will hide the options link.
1 | if(hideOption) tr.parentNode.parentNode.parentNode.parentNode.nextSibling.style.display='none'; |
Then it will insert a button, and finally the “results” lists are moved into a generated div which can then be slid open or shut.
Whenever I create a solution that changes the appearance of the page, showing or hiding an element, the users demand that the change persist through a page reset. The easiest way would be to create a new parameter to store the display state. Possibly a hidden text box with box type set to none. But if we always did things the easy way, we’d never learn anything.
1 | //Hacky – Building a new dispatcher request to save the state of the SnS. Do any IBMers have any comments? |
2 | if(typeof oReq ==='undefined') oReq = new ViewerDispatcherEntry(window['oCV'+'_THIS_'].getRV().getCV()); |
3 | if(!oReq.getFormFields().m_aValues[promptName]) oReq.addFormField(promptName,'hidden') |
I haven’t tested this on a wide scale, so I don’t know of any performance impact. To be honest, while I love figuring out little hacks like these, without a more in-depth understanding of what it’s doing, it may not be wise to push this to all reports. The attached report contains two functions, the first using the hacky dispatcher request, and the second using a secondary text box to retain the state. The disadvantage of using the text box is that you’ll need to remember to add that in.
Once the JS is in place, we can call the functions with a simple:
1 | paulScripts.advancedSnS ( 'Retailers' , 3,1); |
It will look for the prompt named Retailers, set the option to “Contains any of these keywords”, and hide the options link.
And the final product:
Report XML:
Advanced SnS (4770 downloads)