Monday, May 30, 2011

Scrollable Lists

Requirement: Display a Prompts Pane and a List Pane. The list should display all rows in a single page with the capability to scroll. Note: the Prompts pane should remain visible to the users while scrolling down.

The simplest way to achieve the above requirement would be to use CSS. The advantage of providing scroll bars as part of the list is you can have other objects on the page still in user's visibility.

Solution:

Step 1: Create a table with 2 columns. Add the required Prompts to Column 1 and the list object to Column 2. Set the height for the table cell in which you would like to place the scrollable list.

Step 2: Insert HTML items as shown below:







HTML 1: < div style="height: 100%; overflow: auto;" >

HTML 2: </div>
 

Friday, May 20, 2011

Chart Conditional Measures - Conditional Legend

When you create a chart based report that accepts multiple measures as input using case statements the legend is displayed for all the series and not just for the measures selected. To avoid this, disable the chart provided legend and create a manual legend next to the chart and use the colors set in the chart palette to display the right colors for the right series.




 

Wednesday, May 11, 2011

Expand / Collapse Javascript

Very recently I implemented a requirement to provide expand / collapse feature in long-spanning reports. The JavaScript for this is available on Cognos Support Site. Wish Cognos provides objects for this rather than using javascripts that can prove to be unreliable during upgrades.

What I wanted to focus on through this article is to provide an overview of what this JS does, because it is important to understand the code that you include/integrate into your reports so it is easier to debug issues.

The code is fairly self-explanatory. I have explained the code at a high level:
  • Identify the selected row (the row for which an expand/collapse has been initiated).
  • Switch the icon for the selected row from an expand to collapse or vice-versa.
  • Process all rows below the selected row.
  • For each row processed, called as current row, identify if the initiated function was an expand/collapse.
  • If collapse, then set style property for current row to "none" which will hide current row. If the current row contains an image and if the image is a collapse icon, then re-set the icon to expand icon and hide the row by setting the style property to "none". All rows below the row clicked get hidden and any collapse icons are re-set so when the higher level is expanded, the clickable rows below display an expand icon and not a collapse icon.
  • If expand, and if the current row is at level lower than immediate lower level, then set style property for current row to "none" to hide the row. If the current row is at an immediate lower level then set style to "" to display this row. If the current row contains an image, and if the current row is a sibling level for the selected level then do not process the row.
  • The StartHidden function is called on load of the page. This function gets the table element and hides all rows where padding has been set by setting the style property to "none". Thus all rows except the 1st level rows get hidden on load of the report.

[User comments: RecoveringAdmin]
I implemented this as well when I saw that article in the KB. Well, more specifically, when my users saw that article. The downsides I found with this solution are that it's HTML ONLY. if you want to export a specific state to xls or pdf (say, a few rows expanded, some contracted) you would have to screen scrape and repass those selections to cognos as part of some parameter set. Just rerunning the report to another format will disregard the javascript. (pdf and xls engine rebuilds the result set and disregards the html blocks). It's a neat trick, but not super useful as a report output.

<script>
// These settings you can change to modify the report processing
var UOM="px"; // Set to unit of measure for padding
var INDENT_SIZE=20; // Set to indent padding step size. Setting to 20 means the padding steps are 20,40,60,80. These have to match the padding applied to the report objects
var UOM_SIZE = UOM.length;
function stripTrailing(string,num) {
if ( string == "") {return parseInt(0);} else {return parseInt(string.substring(0,string.length-num));}
}
function ExpandCollapse( el )
{
// Grab the ROW that was clicked and the TABLE that contains it
var tr = el.parentElement.parentElement;
var tbl = tr.parentElement.parentElement;
// Set the alternating display values for hiding/showing the row
var sDisplay = ( el.src.indexOf( "minus" ) == -1 ) ? "" : "none";
var sDisplayReverse = ( el.src.indexOf( "minus" ) == -1 ) ? "none" : "";
//Switch the icon for the clicked row
el.src = "../pat/images/PropertyGroup_" + ( el.src.indexOf( "minus" ) == -1 ? "minus" : "plus" ) + ".gif";
// Starting with the row below the clicked row, start checking each row
for ( var i = tr.rowIndex + 1; i < tbl.rows.length; i++ )
{
// Set the Current row indicator nad the left padding value
var trCurrent = tbl.rows( i );
var trCurrentLeft = trCurrent.cells(0).style.paddingLeft;
// if the current row contains an IMG in it, it's a clickable level and we either have to stop processing,
// or reset the icons to a + as it's being collapsed
if ( trCurrent.cells( 0 ).firstChild && trCurrent.cells( 0 ).getElementsByTagName( "IMG" ).length )
{
// If the current row is at the same level or above in the tree, then stop processing,
// else reset all the signs below it, essentially collapsing all branches underneath the one that is beig collapsed.

if ( stripTrailing(trCurrentLeft , UOM_SIZE) <= stripTrailing(tr.cells(0).style.paddingLeft , UOM_SIZE) )
{ break; }
else
{
if (el.src.indexOf( "minus" ) == -1 )
{
trCurrent.cells(0).getElementsByTagName("IMG").item(0).src = "../pat/images/PropertyGroup_plus.gif";
}
}
}
// Now, we determine if the row should be hidden or shown.
if ( eval(stripTrailing(tr.cells(0).style.paddingLeft, UOM_SIZE) + INDENT_SIZE) < stripTrailing(trCurrentLeft, UOM_SIZE) && el.src.indexOf( "minus" ) > 0 )
{
trCurrent.style.display = sDisplayReverse;
} else
{
trCurrent.style.display = sDisplay;
}
}
}
function StartHidden(el)
{
var tbl=el.parentElement.parentElement.parentElement.parentElement;
for (var i = 0; i < tbl.rows.length; i++)
{
var trCurrent = tbl.rows(i);
if (trCurrent.cells(0).style.paddingLeft.indexOf(UOM) > -1)
{
trCurrent.style.display = "none";
}
}
}
</script>

Note: This technique uses JavaScript against underlying report objects in a IBM Cognos 8 BI report. For this reason, there is no guarantee that reports created using this technique will migrate or upgrade successfully to future versions without requiring modifications. Any such modifications are the responsibility of the report designer.