Monday 2 March 2015

IR Scrolling - With a Little Help From My Friends

If you are working with interactive reports you will for sure be faced with a problem of wide reports. If you are taking care of the page layout and eventually have more than just an interactive report on the page, you will want to limit it's size to something making sense. The first problem will appear if you limit the width by setting the region attribute to something like this

style="width:830px"

and you will not see some of the columns:



If you add a scrolling by wrapping the region in a div and adding the following to the region header:

<div style="width:810px;overflow-x:scroll">

and closing it in the footer by adding:

</div>



you will be able to scroll with two ugly side effects:

  • The action bar will be included in the scrolling as well and disappear as you scroll to the right.
  • The sort widgets for the columns will appear on the wrong position the more you scroll.




  • You can solve this problem in the following way:

  • Remove the scrolling DIV from the region header / footer.
  • Use this java script in the page Function and Global Variable Declaration:

    function onload_ir(p_width, p_report_id){

    $('<div id="scroll_me" style="width:' + p_width + 'px;overflow-x:auto;display:inline-block"></div>').insertBefore('#apexir_DATA_PANEL'); $("#apexir_DATA_PANEL").appendTo("#scroll_me"); $("#apexir_DATA_PANEL").show();

    var or_Finished_Loading = gReport._Finished_Loading; gReport._Finished_Loading = function(){ or_Finished_Loading(); if(gReport.current_control=='SORT_WIDGET'){

    var offset_pos = $("#" + p_report_id ).position().left; var pos_left = $('#apexir_rollover').css('left'); pos_left = pos_left.replace('px',''); if (pos_left>p_width-100) {new_pos = parseFloat(pos_left) + parseFloat(offset_pos) - 25; $('#apexir_rollover').css('left', new_pos+'px');} }; }; };


  • Create a Dynamic Action which runs After Refresh (fire on page load option should be turned on) of the IR region and execute this script there:

    onload_ir(810, 7990109002761687)


  • 810 is the widht of the scolling region, which is a bit less then the total width of the region.

  • 7990109002761687 is the id of the data grid of the interactive report. You can find this id if you use firebug and scroll to the point where the data grid is placed.




  • What this script does is:

  • It will wrap the data grid into an additional div and add a scroll bar to it.
  • It will overwrite the IR onload function and add a sort widget positioning function to it in order to reposition the widget according to the scrolling.
  • The important part of the overloading function was done by Tom Petrus, who is a big help when it comes to tricky stuff like this.

    Now, once you have done that, your report will show up properly once you scroll it.



    Enjoy.

    4 comments:

    Jeffrey Kemp said...

    Nice - but after changing the report (e.g. changing the number of rows, adding a filter), the div is lost and the page is back to normal. Perhaps the onload_ir needs to be triggered by another event?

    Denes Kubicek said...

    Jeff,

    it does work if you run it after refresh of the IR Region and set the "fire on page load" option on. I will correct my posting. Thanks for the valuable feedback.

    Regards,

    Denes

    Jeffrey Kemp said...

    Thanks Denes, that fixed that.

    I then came across a 2nd problem; when scrolled, the menus weren't being shown in the correct position. In the console I noticed it was reporting the error "cannot read property left" at the line that initialises offset_pos.

    I found it worked if I pass the report ID as a string instead of a number, e.g.:

    onload_ir(810, '7990109002761687')

    The behaviour might be different depending on the browser used.

    Jeffrey Kemp said...

    Just another idea: I wanted it to automatically pick up the width of the window, instead of using a fixed width. Also, I wanted to remove the need to hard-code the report ID. So, I changed the code as follows (couldn't post it here so linked):

    http://jsfiddle.net/vc7ba3ab/

    I then changed the dynamic action to just call onload_ir().

    To pick up changes to the window size, I added the following to the Function and Global Variable Declaration:

    var resizeTimer;

    function refreshReport() {
    $('#membersReport').trigger('apexrefresh');
    }

    (Note: I set the Static ID on the report to "membersReport")

    I then added this to the Execute when Page Loads:

    $(window).resize(function() {
    clearTimeout(resizeTimer);
    resizeTimer = setTimeout(refreshReport, 100);
    });

    Note: the offset (-35) may need to be adjusted for different themes and page templates.