Instantly share code, notes, and snippets.

Embed
What would you like to do?
Oracle Apex Interactive Table fixed header javascript function for creating fixed headers
/**
* ApexInteractiveFixedHeader
* @author J. Reuben Wetherbee <jrweth@gmail.com>
*
*
* Modified from UltimateScrollingTable
* http://nevcal.com/eclectic/UltimateScrollingTable.html
*
* The fixed header works by making a copy of the table for the header to insure widths are consistent.
*
* The header div height is set to the header height and overflow is set to hidden.
* A downside of this implementation is that the entire table has to be copied which can slow things down.
*
*/
function ApexInteractiveFixedHeader(options)
{
//default options
var defaultOptions = {
tableSelector: 'table.apexir_WORKSHEET_DATA',
tableHeight: 400,
tableWidth: 0
}
var options = $.extend(options, defaultOptions);
var $tableRoot = $(options.tableSelector); //jquery object for the table
var tableRoot; //root element of the original table
var parent; //parent element containing the table
var DivRoot = document.createElement('div'); //new div containing new table(s)
var DivHeader; //div containing the header table
var DivContent = document.createElement('div'); //div containing the scrolling data body
var DivFooter; //div containing the footer
var currentColumnHeader; //the column Header that has most recently been clicked
//recursive function to reposition header rollover options once it is displayed
var columnRolloverAdjust = function() {
var currentOffset, newOffset;
//still hidden try back in a bit
if($('#apexir_rollover').css('display') === 'none') {
setTimeout(columnRolloverAdjust, 50);
}
else {
currentOffset = $("#apexir_rollover").offset();
newOffset = currentColumnHeader.offset();
$("#apexir_rollover").offset({top: currentOffset.top, left: newOffset.left});
}
};
//check to see if the table exists
if ($(options.tableSelector).length === 0) {
$('.apexir_FIXED_HEADER_LOADING').hide();
return false;
}
//setup listeners for user clicking on Header
$(document).on("click", options.tableSelector + " thead th", function(e) {
currentColumnHeader = $(e.currentTarget);
});
//setup listener for when content of header rollover has ben updated
$("#apexir_rollover_content").on("change", function(e) {
columnRolloverAdjust();
});
//setup listener for when the table gets refreshed due to filtering etc.
$(document).bind("apexafterrefresh", function(){
ApexInteractiveFixedHeader(options);
});
$(document).bind("apexbeforerefresh", function(){
$('.apexir_FIXED_HEADER_LOADING').show();
$('.apexir_WORKSHEET_DATA').hide();
});
//move the th rows from the tbody into the thead (apex puts header row in the tbody section)
$tableRoot.append('<thead>' + $tableRoot.find('tbody th').not('.apexir_REPEAT_HEADING').parent().first().html() + '</thead>');
$tableRoot.find('tbody th').not('.apexir_REPEAT_HEADING').parent().remove();
//set the tableRoot and parent
tableRoot = document.getElementById($tableRoot.attr('id'));
parent = tableRoot.parentNode;
tableHeight = parseInt( options.tableHeight );
tableWidth = parseInt( options.tableWidth );
/* Style the DivRoot, put it where it belongs */
DivRoot.style.align = 'left';
DivRoot.style.height = tableHeight;
parent.insertBefore( DivRoot, tableRoot );
/* Style the Main Content width first, then heights can be obtained */
DivRoot.appendChild( DivContent );
DivContent.appendChild( tableRoot );
DivContent.style.overflow = "scroll";
DivContent.style.position = 'relative';
DivContent.style.zIndex = '1';
$tableRoot.show();
$('.apexir_FIXED_HEADER_LOADING').hide();
scrollWidth = DivContent.offsetWidth - DivContent.clientWidth;
if ( tableWidth == 0 ) {
tableWidth = $('.apexir_TOOLBAR_CLOSE').width();
tabWidth = tableRoot.clientWidth;
if ( tabWidth + scrollWidth < tableWidth ) {
tableWidth = tabWidth;
}
else {
tableWidth = tableWidth - scrollWidth;
}
}
DivContent.style.width = tableWidth + 'px';
/* Obtain the calculated heights */
headerHeight = 0;
footerHeight = 0;
scrollCount = 0;
tag = tableRoot.getElementsByTagName('thead')[ 0 ];
if ( tag != undefined ) {
headerHeight = tag.clientHeight;
DivHeader = document.createElement('div');
scrollCount += 1;
}
tag = tableRoot.getElementsByTagName('tfoot')[ 0 ];
if ( tag != undefined ) {
footerHeight = tag.clientHeight;
DivFooter = document.createElement('div');
scrollCount += 1;
}
/* Finish styling the Main Content */
DivContent.style.height = tableHeight + 'px';
if ( scrollCount == 1 ) {
DivContent.onscroll = function() {
this.nextElementSibling.scrollLeft = this.scrollLeft;
}
}
else if ( scrollCount == 2 ) {
DivContent.onscroll = function() {
this.nextElementSibling.scrollLeft = this.scrollLeft;
this.nextElementSibling.nextElementSibling.scrollLeft = this.scrollLeft;
}
}
/* Style the other items */
if ( DivHeader != undefined ) {
DivHeader.style.overflow = 'hidden'
DivHeader.style.position = 'relative';
DivHeader.style.zIndex = '10';
DivHeader.style.width = ( tableWidth - scrollWidth ) + 'px';
DivHeader.style.height = headerHeight + 'px';
DivHeader.style.top = -tableHeight + 'px';
DivHeader.appendChild( tableRoot.cloneNode( true ));
DivRoot.appendChild( DivHeader );
DivHeader.scrollTop = 0;
}
if (DivFooter != undefined ) {
DivFooter.style.overflow = 'hidden'
DivFooter.style.position = 'relative';
DivFooter.style.zIndex = '10';
DivFooter.style.width = ( tableWidth - scrollWidth ) + 'px';
DivFooter.style.height = footerHeight + 'px';
DivFooter.style.top = ( -headerHeight - footerHeight - scrollWidth ) + 'px';
DivFooter.appendChild( tableRoot.cloneNode( true ));
DivRoot.appendChild( DivFooter );
DivFooter.scrollTop = DivFooter.scrollHeight - footerHeight;
}
$('#apexir_ACTIONSMENU, .dhtmlSubMenu').css('z-index', 20);
return true;
}
@jrweth

This comment has been minimized.

Copy link
Owner Author

jrweth commented Jul 3, 2014

Caution. This almost works, but has performance issues, especially on Safari for large tables.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment