Freezing headers in Cognos 10.2

Starting in Cognos 10.2, IBM released a way to freeze crosstab headers and rows. This method works in all major browsers, and doesn’t rely on dirty CSS hacks. To get it working, simply right-click on the list or crosstab, and select Freeze Headers. The report will even remember the state of the crosstab after the page refreshes (from a prompt, possibly).

right click action

While this method works well, there are many times where we’d want to have the lists or crosstab start off frozen; or maybe we want to give the user a button to freeze one or all of the crosstabs in one go. Somewhat surprisingly, the JavaScript is very easy to use.

First, let’s define the initial variables:

var paulScripts = {}
  , win=window['oCV'+'_THIS_'];

paulScripts.oCV = win.getRV().getCV();

Reports run from Report Studio need to use window[‘oCVRS’] while reports from the connection need window[‘oCV_NS_’]. Cognos will automatically replace _THIS_ to the correct fragment. Most of the Cognos functions we need are found inside win.getRV().getCV(), so we’re aliasing that into “paulScripts.oCV”.

The first function I’ll define is:

paulScripts.freezeContainer = function(objectName){
  var pFMngr = paulScripts.oCV.getPinFreezeManager();
  pFMngr.freezeContainer(objectName,true,true);
  window.onResizeViewerEvent()
};

All of the freezing functions are found inside getPinFreezeManager. The function getPinFreezeManager().freezeContainer() takes the object name (“Crosstab1”), and a Boolean to freeze/unfreeze the headers, and another Boolean to freeze/unfreeze the rows.

The freezing mechanism seems to have a small bug in the way it handles resizing. In my tests, it always resizes to a much smaller window than I need. The window.onResizeViewerEvent() function tricks the browser into thinking the window has been resized, and Cognos will then correctly recalculate the size of the frozen crosstab.

The unfreezing function is simple:

paulScripts.unfreezeContainer = function(objectName){
  var pFMngr = paulScripts.oCV.getPinFreezeManager();
  pFMngr.freezeContainer(objectName,false,false);
};

These two functions will let us automatically freeze a crosstab as soon as the page loads. But say we want to toggle it on and off.

/* paulScripts.toggleContainer 
 * Paul Mendelson - 2014-03-25
 * This wil check if a container has frozen headers. If so, it unfreezes it, if not, it freezes the container. 
 */
paulScripts.toggleAll = function(objectName) {
  var pFMngr = paulScripts.oCV.getPinFreezeManager();
  if(pFMngr.hasFrozenColumnHeadings(objectName)) {
    paulScripts.unfreezeContainer (objectName);
  }
  else {
    paulScripts.freezeContainer (objectName);
    window.onResizeViewerEvent()
  }
}

The hasFrozenColumnHeadings function returns a Boolean, true or false, on the state of the column headers.

And finally let’s say that we want to freeze all the crosstabs on the page in one go.

/* paulScripts.toggleAll 
 * Paul Mendelson - 2014-03-25
 * in: type {string - crosstab or list}
 * This wil loop through every "type" on the page, and freezing or unfreezing, depending if the column header is frozen. 
 */

paulScripts.toggleAll = function(type) {
  setTimeout(function(){
    var xts = win._getContainers(type)
      , xtLen = xts.length
      , pFMngr = paulScripts.oCV.getPinFreezeManager();
      for(var i =0;i<xtLen;++i){
        var lid = pFMngr.removeNamespace(xts[i].getAttribute('lid'));
        if(i<xtLen-1 && lid==pFMngr.removeNamespace(xts[i+1].getAttribute('lid'))) continue; //when the panes are frozen the crosstab is split into four elements, all with the same lid. Without this hack, the xtab would toggle four times!
        if(pFMngr.hasFrozenColumnHeadings(lid)) {
          pFMngr.freezeContainer(lid,false,false);
        }
        else {
          pFMngr.freezeContainer(lid,true,true);
          window.onResizeViewerEvent()
        }
      }
    }
  ,200);
}

That was a little bit more complex than before. We can use the _getContainers functions to get an array of all the lists or crosstabs on the page. The lid of the object is the name, plus the namespace. We can use the removeNamespace function to get it back to the name the freezeContainer functions expect.

The toggleAll function should only be used in a button. As Cognos stores the state of the object; if the headers are locked, they will remain locked after refreshing the page. Toggling them will cause them to unlock. Instead, it’s best to use a freezeAll function when loading the page:

paulScripts.freezeAll = function(type){
  var xts = win._getContainers(type)
  , xtLen = xts.length
  , pFMngr = paulScripts.oCV.getPinFreezeManager();
  for(var i =0;i<xtLen;++i){
    var lid = pFMngr.removeNamespace(xts[i].getAttribute('lid'));
    if(pFMngr.hasFrozenColumnHeadings(lid)) continue; 
    paulScripts.freezeContainer (lid);
  }
};

Once everything is working, we can see how it works.
Freezing panes

The example report in using 10.2.1, against the sales and marketing cube.
Freezing Panes report XML (1828 downloads)