// =========================================================================
// CHANGE LOG (most recent first)
// =========================================================================
//
// -------------------------------------------------------------------------
//
// 13 Aug 2009.	 Reverted fix for IE8 below to previous version - should now
//		 work correctly due to change in browser detection rules.
//		 (see browser-detect.js)
// 12 Aug 2009.	 Fix for IE8, to prevent alternate tables in user view from
//		 losing their top border.
// 09 Jun 2009.	 Updated for tabbed user view.
// 01 May 2009.  Fixes for IE8.
// 25 Mar 2009.	 Added functions CT_highlight and CT_unhighlight for cell
//		 highlighting. Surprisingly it's more efficient (in IE at 
//		 least) to handle this via .js than by putting a:hover on 
//		 the links (which delays big table display, and also causes 
//		 delay for highlight effect to appear).  
// 16 Mar 2009.	 Added style for .ct-linked, to make clickable work in IE6.
// 02 Mar 2009.	 Tweaks to make work for BMJ user view.
// 27 Feb 2009.	 Tidy up top fixed text for very narrow screen widths.
// 26 Feb 2009.	 Adjusted 'CT_add_right' for Safari 4 PC support. Mac OK.
// 19 Feb 2009.	 Prevent tables going out of alignment on window resize.
// 10 Feb 2009.  Fix ADAT x-scroll-only cross tabs.
// 09 Feb 2009.	 Fix for an edge case in IE7, where a table finishing 1 pixel 
//		 shorter than the screen width gets and overly wide 
//		 horizontal scrollbar, with spare white space to the right. 
//		 The solution is to use the existing IE6 conditions for IE7 
//		 too, so that the wrapper in IE7 has its height set explicitly, 
//		 rather than relying on max-height to achieve the same effect. 
//		 On the plus side, this simplifies the code, as all special 
//		 conditions for IE7 only are now removed.
//		 Related simplifications to CT_resize().
// 06 Feb 2009.	 Fixes for FF3, Chrome, Safari to fix some edge cases where
//		 data cols were not lining up with header in user details. 
// 02 Feb 2009.	 Corrected browser detect logic to exclude FF3 Mac.
// 30 Jan 2009.	 Additional optimisations for IE (see NOTE [1])
// 23 Jan 2009.	 Optimised for case where row heights are constant.
//		 Browser fixes for Safari Mac / FF2 PC. Disable FF3 Mac.
//		 Extended case to fix Safari Mac to Win Mac and Chrome, as
//		 resolves a minor issue with unwanted y-scrollbar on narrow
//		 tables wich are only one row high (see 'overflow_fix' in code)
// 21 Jan 2009.	 Further tweaks so that the table's top-most header text also 
//		 appears to be fixed. 
//		 Re-enable (and disable) please wait message whilst fixed
//		 headers are being applied to the table.
// 17 Jan 2009.	 Optimised to run faster.
// 05 Jan 2009.	 Code for new scrolly cross tabs with fixed headers.
// 08 Dec 2008.  Now uses var BD_supported_browser to simplify checks
//		 on whether to run this.
// 30 Nov 2007.  Option added for no scrolling at all
// 08 Nov 2007.  Option added for x-scroll-only
// 08 Oct 2007.  Enable IE5 Mac
// 04 Oct 2007.  Enable Mac Safari and Firefox
// 03 Oct 2007.  Fix IE5.5 lose y-scroll bar (on changing tabs) problem
// 28 Sep 2007.  Fix IE7 x-scroll bar on resize problem
// 28 Sep 2007.  Fix IE vanish (on changing tabs) problem
// 28 Sep 2007.  Include all PC browsers.
// 26 Sep 2007.  Include IE7.
// 19 Sep 2007.  First versioned version.
//
// -------------------------------------------------------------------------


// ---------------------------------
// Actions to run on script load
// ---------------------------------

CT_script_loaded = 1;
var CT_max_height = 300; // [3] of [3] for cross tab height - see CSS for [1] and [2]
var CT_add_right = 17;
var CT_add_bot   = 17;
var CT_delay	 = 100; // 100th second
var CT_avail_width; // starting width of page, without scrollbar
var BD_browser = BrowserDetect.browser;
var BD_version = BrowserDetect.version;
var BD_OS      = BrowserDetect.OS;

// [Tabbed user view: 1 of 9]
var CT_set_scroll_y = 0;
var CT_resize_submit_id; // form id to submit on resize, otherwise reload window 

if ( BD_script_loaded && BD_supported_browser ) {
	CT_run_this = 1;
}

if ( CT_run_this && BD_OS == 'Windows' ) {	
	// Internet Explorer
	
	if ( BD_browser == 'Explorer' ) {
		// IE5/6 - min-height not supported - this needed to crop table as page loads
		// IE7 	 - setting height like this fixes an edge case (see versioning notes)
		document.write('<style>');
		document.write('#main .ct-data-wrap { padding: 0; width: 100%; height: ' + CT_max_height +'px }');
		document.write('#main .ct-dummy-left { height: ' + CT_max_height +'px }');
		document.write('#main .ct-linked a { zoom: 1 }'); // IE6 - hasLayout needed for link on entire cell  
		document.write('</style>');

	}
	// Firefox
	else if ( BD_browser == 'Firefox' ) {
		if ( BD_version < 2 ) { 
			CT_add_right = 20;
		}
	} 
	// Netscape
	else if ( BD_browser == 'Netscape' && BD_version >= 8 && BD_version < 9 ) {
		CT_add_right = 20;
	}
	// Chrome
	else if ( BD_browser == 'Chrome' ) {
		CT_add_right = 18;
	}
	// Safari 
	else if ( BD_browser == 'Safari' ) {
		if ( BD_version < 4 ) {
			CT_add_right = 16; // OR disable CT_resize
		}
		else {
			// previous PC versions had Mac style scrollbars
			// v4 has PC style scrollbars and looks equivalent to Chrome
			CT_add_right = 18;
		}
	}
}
else if ( CT_run_this && BD_OS == 'Mac' ) {
	if ( BD_browser == 'Explorer' && BD_version >= 5 ) {
		// min-height not supported - this needed to crop table as page loads
		document.write('<style>');
		document.write('#main .ct-data-wrap { padding: 0; width: 100%; height: ' + CT_max_height +'px }');
		document.write('#main .ct-dummy-left { height: ' + CT_max_height +'px }');
		document.write('</style>');
	}

	// Safari 
	else if ( BD_browser == 'Safari' ) {
		CT_add_right = 16; // OR disable CT_resize
	}

	// Firefox
	else if ( BD_browser == 'Firefox' ) {
		// this ensures top and left borders appear OK
		document.write('<style>');
		document.write('#main .ct-data-wrap { padding-left: 1px }');
		document.write('</style>');
	}
}

// ########################################################
// Styles for scrolly cross tabs with fixed headers
// ########################################################
var CT_run_fixed_headers = 0;

// list of browsers where we can run fixed headers
if ( CT_run_this && (
	( BD_OS == 'Windows' && (
		   ( BD_browser == 'Explorer' && BD_version >= 6 )
		|| ( BD_browser == 'Firefox'  && BD_version >= 2 )
		|| ( BD_browser == 'Opera'    && BD_version >= 9 )
		|| ( BD_browser == 'Safari'   && BD_version >= 3 )
		|| ( BD_browser == 'Chrome' ) 
	) )
	|| ( BD_OS == 'Mac' && (
		   ( BD_browser == 'Safari'   && BD_version >= 3 )
	) )  	
)) {
	CT_run_fixed_headers = 1;
}

if ( CT_run_fixed_headers ) {

	// enable the dummy content blocks
	document.write('<style>');

	// see NOTE [1]
	if ( BD_browser != 'Explorer' ) { document.write('.ct { display: none }') } // applies to top-fixed and top-left fixed
	else 				{ document.write('.ct-mask { display: block }') };

	document.write('.ct-dummy-top { display: block }'); // applies to top-fixed and top-left fixed
	
	// disappear the top two table rows (but only if 'fixed' class is present - see BMJ)
	var overflow_fix =  (BD_browser == 'Safari' || BD_browser == 'Chrome' || ( BD_browser == 'Firefox' && BD_version >= 3 )) ? ' overflow: hidden;' : '' ; 
	document.write('.fixed .ct-top-2 div, .fixed .ct-top-1 div { height: 0px; visibility: hidden; margin-bottom: -1000px;' + overflow_fix + '}' ); 
	document.write('.fixed .ct-top-1 td, .fixed .ct-top-2 td, .fixed .ct-top-1 th, .fixed .ct-top-2 th { border-top: 0; border-bottom: 0; padding-top: 0; padding-bottom: 0; }' );
	document.write('.fixed .ct-row-1 td, .fixed .ct-row-1 th { border-top: 0; }');
	
	document.write('#ct-empty-sources { height: 0px; overflow: hidden; }');
	
	document.write('</style>');

	// browser specific rules
	if ( BD_OS == 'Windows' && BD_browser == 'Explorer' ) {
		document.write('<style>');
		document.write('.ct-dummy-left .first { margin-top: 2px; }');
	
		var this_padding = BD_version >= 8 ? 3 : 4;
		document.write('.ct-dummy-top-left .last { padding-bottom: ' + this_padding + 'px }'); // 1 or 2 less

		document.write('.ct-dummy-top, .ct-dummy-top-left, .ct-dummy-top-text { top: 2px; z-index: 100 }');



		document.write('</style>');
	}
	else if ( BD_browser == 'Firefox' ) {
		// this ensures top and left borders appear OK
		document.write('<style>');
		document.write('#main .ct-data-wrap { padding-left: 1px }');
		document.write('#main .ct-dummy-top, #main .ct-dummy-top-text { padding-top: 1px; padding-left: 1px }');
		document.write('</style>');
	}

	else if ( BD_browser == 'Chrome' || BD_browser == 'Safari' ) {
		// prevent horizontal scrollbar on tables that appear to fit width OK
		document.write('<style>');
		document.write('.ct-data-wrap table { margin-right: 1px }');
		document.write('</style>');
	}
	
	// [Tabbed user view: 2 of 9]
	// Disappear top-most header in record view
	// NOTE: it's a lot easier to vanish this than not print it at all in Template.pm, since the .js below assumes the
	// cross-tab table strcuture will always have a first row that is the table heading.
	if ( BD_browser == 'Explorer' && BD_version >= 8 ) { // IE8: Prevents alternate tables losing their top border
		document.write('<style>');
		document.write('.ct-hide-top-row .ct-top-1 th, .ct-hide-top-row .ct-top-1 td { display: none !important }');
		document.write('.ct-hide-top-row .ct-top-2 th { border-top: 1px #cccccc solid }');
		document.write('</style>');
	}
	else { // Other browsers
		document.write('<style>');
		document.write('.ct-hide-top-row .ct-top-1 { display: none !important }');
		document.write('</style>');	
	}
}

// --------------------------------------
// Actions to run when page fully loaded
// --------------------------------------
// Below var allows us to 'cheat' and get the height of a table row fast (it's the height of padding + borders)
// An alternative is in commented out function CT_row_height(), but this is inefficient as it needs to iterate every
// cell in the row to find the tallest one. If this does need to be swapped back in, see lines commented 'get height'
var CT_row_padding = 11; 
var CT_col_padding = 11;

// ########################################################
// New functions for scrolly cross tabs with fixed headers
// ########################################################

// The concept for the fixed headers is to extract the top and left header rows from the orignal HTML table, and insert them
// into their own divs within separate tables. These are then positioned to the top and left of the original table via CSS,
// and the scroll positions are set via an 'onscroll' event on the original table, to keep them aligned with the data. 
// The catch is that once extracted from the original table grid, the header cells lose their original heights and widths, 
// so these need to be set explicitly to make sure everything lines up correctly.

// NOTES:
// [1] In IE6/7, starting with table as display 'none' then switching to 'block' causes significant slowdown in the display
// of very large tables (e.g. 10,000 rows takes 2 mins versus 1 min to load and display). Even When other content on the page
// (e.g. info box beneath tables) which seems to be unrelated switches between 'none' and 'block', this also has an effect on
// the speed of the table display. For OTHER browsers, the opposite is true - switching between display 'none' and
// 'block' is about twice as fast as the IE workaround.

var CT_lefts = new Array;
var CT_tops  = new Array;
var CT_table_count = 0;

function CT_init() {
		
	// grab a heading to use as width comparison
	// this assumes that headings are set to 100% width
	var heading_els = document.getElementsByTagName('H1');

	// if no heading found, exit gracefully
	if ( !heading_els.length ) { return };

	var heading_el  = heading_els[0];
	CT_avail_width = heading_el.offsetWidth;

	// first build list of target cross tab table ids
	var tables = document.getElementsByTagName('table');
	for ( var h=0; h<tables.length; h++ ) {
		if ( tables[h].getAttribute('id') && tables[h].getAttribute('id').match(/^ct\-/) ) {
			CT_table_count++;
			CT_tops[CT_table_count]  = document.getElementById( 'ct-' + CT_table_count + '-js-top' );
			CT_lefts[CT_table_count] = document.getElementById( 'ct-' + CT_table_count + '-js-left' );
		}
	}

	if ( CT_table_count > 0 ) {		
		CT_process( 1, CT_table_count );
	}	
}


function CT_process( ct_count, ct_max ) {

	if ( ct_count > ct_max ) { 		
		// display 'empty sources' box on user details page last
		var empty_sources_div = document.getElementById('ct-empty-sources');
		if ( empty_sources_div ) { empty_sources_div.style.height = 'auto' }; // see NOTE[1]
		
		// hide (re-disable) please wait		
		var pw_els = document.getElementsByTagName('B');		
		for ( var i = 0; i < pw_els.length;  i++ ) {
			if ( pw_els[i].className == 'please-wait' ) {
				pw_els[i].style.display = 'none';
			}
		}

		// [Tabbed user view: 3 of 9]
		// set page scroll position, if asked to
		if ( CT_set_scroll_y ) {
			HS_set_win_scrollpos( 0, CT_set_scroll_y, 10 );
		}

		// [Tabbed user view: 4 of 9]
		// Setup resize event here (previously in CT_fix_headers)
		// Ensures event is set even if last table is set to 'defer' (as it will be)
		var last_table = document.getElementById( 'ct-' + (ct_count-1) + '-table' );
		var last_wrap_div = last_table.parentNode;
		if ( last_wrap_div.className.match( /top\-fixed/ ) ) {
			// delay prevents event firing immediately		
			setTimeout( "CT_resize_fix_init()", 500 );
		}

		return;
	}
	
	var table = document.getElementById( 'ct-' + ct_count + '-table' );
	var wrap_div = table.parentNode;

	// [Tabbed user view: 5 of 9]
	// Supports class 'defer', meaning that the fixed headers will be applied
	// on demand, when table is made visible, rather than as page loads.
	if ( wrap_div.className.match( /defer/ ) ) {
		var this_count = ct_count + 1;
		CT_process( this_count, ct_max ); // recurse ...
		return;				  // still need to terminate when recursion returns
	}
		
	if ( CT_run_fixed_headers && wrap_div.className.match( /-fixed/ ) ) {
	
		// show (re-enable) please wait
		var pw_els = document.getElementsByTagName('B');		
		for ( var i = 0; i < pw_els.length;  i++ ) {
			if ( pw_els[i].className == 'please-wait' ) {
				pw_els[i].style.display = 'block';
			}
		}
		
		// run code for fixed headers		
		var run_str = ("CT_fix_headers(" + ct_count + ' ,' + ct_max + ")" );
		setTimeout( run_str, CT_delay );
	}
	else {
		// enable the containing div to display

		// see NOTE [1]
		if ( BD_browser != 'Explorer' ) {
			var ct_outer_div = document.getElementById( 'ct-' + ct_count + '-outer' );
			ct_outer_div.style.display = 'block';
		}

		// run code for no fixed headers
		CT_resize( table );

		// see NOTE [1] - this for case where table not fixed (e.g. too big) 
		if ( BD_browser == 'Explorer' ) {
			CT_unmask( ct_count );
		}
		
		ct_count++;
		CT_process( ct_count, ct_max );
	}
}

function CT_fix_headers( ct_count, ct_max ) {
	
	// enable the containing div to display - calculations below don't work 
	// if cross tab table set to display: none. Note this won't appear on-screen yet
	var ct_outer_div = document.getElementById( 'ct-' + ct_count + '-outer' );
	
	// see NOTE [1]
	if ( BD_browser != 'Explorer' ) { ct_outer_div.style.display = 'block'; } // [DELAY in IE]
																																							
	// need to retrieve this again using number, due to setTimeout
	var table = document.getElementById( 'ct-' + ct_count + '-table' );

	var table_width  = table.offsetWidth;
	var table_height = table.offsetHeight;
	
	var ct_wrap_div = table.parentNode;	
	var ct_wrap_div_width = ct_wrap_div.offsetWidth;

	// In case we want to enforce persistent y-scrollbar in FF/others like IE
	// (worried disappearing/appearing scrollbar may break alignment, but
	// not found any cases yet, so don't worry for now) 
	// if ( ct_wrap_div.className.match( /defer/ ) ) {
	//	if ( BD_browser != 'Explorer' ) {
	//		document.documentElement.style.overflowY = 'scroll';
	//		document.documentElement.style.overflowX = 'auto';
	//	}
	// }

	// ensure scrollbars reset if page is refreshed
	if ( BD_browser == 'Explorer' && BD_version >= 8 ) {  // don't need to do this with other browsers?
		ct_wrap_div.scrollLeft = 0;
		ct_wrap_div.scrollTop = 0;
	}

	// special case for top scrolling only
	var top_fixed_only = 0;
	if ( ct_wrap_div.className.match( /top\-fixed/ ) ) {
		top_fixed_only = 1;
	} 
	
	// disable this for no fixed top text
	var top_fixed_text = 1;

	// allows optimisation
	var const_row_height = 0;
	var const_matches = new Array;
	if ( const_matches = ct_wrap_div.className.match( /row\-height\-(\d+)/ ) ) {
		const_row_height = const_matches[1]; // number
	} 

	// correction for FF2 PC - ensures horizontal scrollbar appears on short but wide tables
	if (       top_fixed_only 
		&& (BD_OS == 'Windows' && BD_browser == 'Firefox' && BD_version < 3 ) 
		&& (table_height < CT_max_height) 
		&& (table_width > ct_wrap_div_width ) 
	)  {
		table.style.height = ( (table_height + 5) + 'px' );
	}

	// corrections for non-IE browsers
	if ( BD_browser != 'Explorer' ) {
		// prevent case where table is drawn, page gets longer, gets a y scrollbar
		// and table is nudged out of alignment. In this case, undo 'fixed' magic and
		// just display a regular table
		if ( ct_wrap_div_width - table_width >= 0 && ct_wrap_div_width - table_width <= CT_add_right ) {
			if ( table_height < CT_max_height ) {
				document.getElementById( 'ct-' + ct_count ).className = '';					
				document.getElementById( 'ct-' + ct_count + '-js-top' ).style.display = 'none';					
				top_fixed_text = 0;
			} 
		}		
	}

	// Add 'onscroll' event handler to wrapper div. Since 'onscroll' is not a valid XHTML Strict 
	// attribute, we do this here to keep the document valid.
	ct_wrap_div.onscroll=function() {
		CT_align( this );
	}
	
	// get orig left col width
	var real_top_header = document.getElementById( 'ct-' + ct_count + '-top-2' );
	var real_top_header_cols  = real_top_header.getElementsByTagName('DIV');
	var left_width = real_top_header_cols[0].offsetWidth + CT_col_padding + 1; // +1 fixes top left text wrap

	var dummy_top_header = document.getElementById( 'ct-' + ct_count + '-js-top' );
	var dummy_top_left_header = document.getElementById( 'ct-' + ct_count + '-js-top-left' );

	var ct_new_width;
	if ( !top_fixed_only ) {
		// vanish left col (note class may already be set to 'align-left')
		table.className += ' ct-js-hide-left'; // [DELAY]
		
		// shift table to right
		var ie8_fix = (BD_browser == 'Explorer' && BD_version >= 8 ) ? 1 : 0;
		ct_wrap_div.style.marginLeft = ( (left_width + ie8_fix) + 'px' ); // [DELAY]
	
		// .. and reduce its width
		ct_new_width = (ct_wrap_div_width - left_width); 
		if ( ct_new_width < 0 ) { ct_new_width = 0 }; // prevent negative width (.js error)
		
		ct_wrap_div.style.width = ( ( ct_new_width ) + 'px' ); // [DELAY]
	
		// shift dummy top col to right
		dummy_top_header.style.marginLeft = ( left_width + 'px' );
			
		// .. and reduce its width	
		dummy_top_header.style.width = ( ( ct_new_width ) + 'px' );
		
		// set dummy left col width
		var dummy_left_header = document.getElementById( 'ct-' + ct_count + '-js-left' );
		dummy_left_header.style.display = 'block'; // make dummy left col appear
		dummy_left_header.style.width = ( left_width + 'px' );

		// make dummy top-left col display
		dummy_top_left_header.style.display = 'block';

		// set dummy top left col width
		dummy_top_left_header.style.width = (left_width + 'px' );

		// ensure left col all lined up if user backs up onto page after previously
		// moving y-scrollbar (only applies to a get request - see BMJ user view)
		if ( BD_browser == 'Explorer' ) {
			CT_align( ct_wrap_div );
		}
	}

	if ( top_fixed_text ) { 
		var dummy_top_text = document.getElementById( 'ct-' + ct_count + '-js-top-text' );
		var dummy_top_text_avail_width = !top_fixed_only ? ct_new_width : ( ct_wrap_div_width - left_width );
		
		// shift dummy top text to the right
		dummy_top_text.style.left = ( left_width + 'px' );
				
		// ... and make it appear
		dummy_top_text.style.display = 'block';

		// ... check it fits (can only get width after is visible)		
		if ( dummy_top_text.offsetWidth > dummy_top_text_avail_width ) {
			dummy_top_text.style.display = 'none';
		}
		else {
			// .. and the real top text underneath disappear (visible on horizontal scroll if top fixed only)
			var real_top_text = document.getElementById( 'ct-' + ct_count + '-top-text' );
			real_top_text.className = 'ct-js-hide-text';
		}
		
	}
		
	// set top header widths
	var h_offset = top_fixed_only ? 0 : 1;
	var dummy_top_header_cols = dummy_top_header.getElementsByTagName('DIV');			

	for ( var h=h_offset; h<real_top_header_cols.length; h++ ) {

		var real_width = real_top_header_cols[h].offsetWidth; // get
		dummy_top_header_cols[(h-h_offset)].style.width = ( real_width + 'px' ); // set	

		// Can also put the FF3 PC fix here if needed
		//real_top_header_cols[h].parentNode.style.width = ( real_width + 'px' ); // FF3 alt fix

		// This fixes FF3 Mac - but is too expensive, as needs to reset data table cols too
		// real_width += 1;
		// dummy_top_header_cols[(h-h_offset)].style.width = ( real_width + 'px' );
		// real_top_header_cols[h].style.width = ( real_width + 'px' );		
	}

	// correction for IE8, to prevent columns going out of alignment in some cases		
	if ( top_fixed_only && BD_browser == 'Explorer' && BD_version >= 8 ) {
		var make_narrower = 0;
		var make_wider    = 0;
		for ( var try_fix = 1; try_fix <= 10; try_fix++ ) { // trial and error
				
			var ie8_extra_col_width = dummy_top_header_cols[(dummy_top_header_cols.length-1)].offsetWidth-1 + CT_col_padding;
			var ie8_dummy_header_width = dummy_top_header.getElementsByTagName('table')[0].offsetWidth;
			var ie8_real_header_width  = real_top_header.offsetWidth + ie8_extra_col_width;

			// [Tabbed user view: 6 of 9]
			ie8_dummy_header_width += 10; // adjustment needed

			if ( ie8_dummy_header_width != ie8_real_header_width ) {	
				// adjust table width
				if ( !make_narrower && !make_wider ) {
					if (ie8_dummy_header_width > ie8_real_header_width) {
						make_narrower++;
					}
					else if ( ie8_dummy_header_width < ie8_real_header_width ) {
						make_wider++;
					} 
				}
				if ( make_narrower ) {
					table.style.width = ( (table.offsetWidth - 1) + 'px' ); 
				}
				else if ( make_wider ) {
					table.style.width = ( (table.offsetWidth + 1) + 'px' ); 
				}
				// reset the top header for adjusted table
				for ( var h=h_offset; h<real_top_header_cols.length; h++ ) {
					var real_width = real_top_header_cols[h].offsetWidth;
					dummy_top_header_cols[(h-h_offset)].style.width = ( real_width + 'px' ); // set	
				}
			}
			else {
				break; // all ok
			}
		}
	}

	// correction for FF3, to prevent columns going out of alignment in some cases		
	if ( BD_browser == 'Firefox' && BD_version >= 3 ) {
		var ff_extra_col_width = dummy_top_header_cols[(dummy_top_header_cols.length-1)].offsetWidth-1 + CT_col_padding;
		var ff_dummy_header_width = dummy_top_header.getElementsByTagName('table')[0].offsetWidth;
		var ff_real_header_width  = real_top_header.offsetWidth + ff_extra_col_width;
		if ( ff_dummy_header_width != ff_real_header_width ) {
			for ( var h=h_offset; h<real_top_header_cols.length; h++ ) {
				var real_width = real_top_header_cols[h].offsetWidth; // get
				dummy_top_header_cols[(h-h_offset)].style.width = ( real_width + 'px' ); // set		
				real_top_header_cols[h].parentNode.style.width  = ( real_width + 'px' ); // FIX ??
			}
		}
	}
					
	if ( !top_fixed_only ) {
	
		// set dummy top-left col heights
		var dummy_top_header_height_1 = dummy_top_header.getElementsByTagName('TR')[0].offsetHeight - CT_row_padding;
		var dummy_top_header_height_2 = dummy_top_header.getElementsByTagName('TR')[1].offsetHeight - CT_row_padding;
		
		var dummy_top_left_header_rows = dummy_top_left_header.getElementsByTagName('DIV');
		dummy_top_left_header_rows[0].style.height = ( dummy_top_header_height_1 + 'px' );
		dummy_top_left_header_rows[1].style.height = ( dummy_top_header_height_2 + 'px' );
			
		if ( !const_row_height ) {
			// get table rows
			var real_table_rows = table.getElementsByTagName('tr');

			// set left header heights
			var dummy_left_header_cols = dummy_left_header.getElementsByTagName('DIV');

			var g;
			var real_table_rows_length = real_table_rows.length;
			for ( g=2; g<real_table_rows_length; g++ ) { 
										
				var real_height =  real_table_rows[g].offsetHeight - CT_row_padding; 		// get
				var dummy_height = dummy_left_header_cols[g-2].offsetHeight - CT_row_padding;   // get
					
				// corrections for IE - first row reported 1 pixel short, last row 1 too tall
				if (BD_browser == 'Explorer' ) {
					if ( g == 2 ) {
						if ( BD_version < 8 ) { // not needed for IE8
							real_height++; 
						}
					}
					else if (  g == (real_table_rows_length-1) ) {
						real_height--;
					}
				}
												
				if ( real_height == dummy_height ) {
					continue; // next
				}		
				else if ( real_height > dummy_height ) {
					dummy_left_header_cols[g-2].style.height = ( real_height + 'px' ); // set
				}
				else if ( dummy_height > real_height ) {
					real_table_rows[g].getElementsByTagName('DIV')[1].style.height = (dummy_height + 'px' ); // [DELAY]
				}
			}
		}
		else {
			// 1-char high only supported for now - no extra adjustments needed
			// For 2-chars or more, add logic here 
		}

		// crop the left div height so that the extra (invisible) cell we added does not 
		// overlap content below, when there is no scrollbar present. It's easier to
		// do this than try to check whether the scrollbar is there or not.		
		var left_max = table_height < CT_max_height ? table_height : CT_max_height;
		dummy_left_header.style.height = ( left_max + 'px' );
	}

	CT_resize( table );

	// see NOTE [1]
	if ( BD_browser == 'Explorer' ) {
		CT_unmask( ct_count );
	}
			
	// call this recursively for each cross tab on the page
	// we do this, rather than in the controlling loop, so that the next timeout is not set up
	// until the previous one completes. This give temporary control back to the page, so that 
	// the tables will render one by one.
	ct_count++;
	CT_process( ct_count, ct_max );
}		

function CT_resize_fix_init() {
	window.onresize = function() {
		CT_throttle(CT_resize_fix, window);	    
	};
}

function CT_throttle(method, scope) {
    clearTimeout(method._tId);
    method._tId= setTimeout(function(){
	method.call(scope);
    }, 500);
}

function CT_resize_fix() {
		
	for ( var ct_count=1; ct_count<CT_table_count+1; ct_count++ ) {

		// [Tabbed user view: 7 of 9]
		// If table has been disappeared (e.g. as part of a tabbed view), don't trigger
		// the onresize event. Note the container with display: none set on it will be 
		// elsewhere on the page, and style.display won't be inherited downwards so
		// display: none can't be checked for directly here. However, if the table is 
		// not visible, it won't have a height, so we can check for that.
		var table = document.getElementById( 'ct-' + ct_count + '-table' );
		var ct_wrap_div = table.parentNode;	
		if ( ct_wrap_div.offsetHeight == 0 ) { // won't have a height if not displayed
			continue;
		}

		var real_top_header  = document.getElementById( 'ct-' + ct_count + '-top-2' );
		var dummy_top_header = document.getElementById( 'ct-' + ct_count + '-js-top' );			
		var dummy_top_header_cols = dummy_top_header.getElementsByTagName('DIV');			
		
		var this_extra_col_width = dummy_top_header_cols[(dummy_top_header_cols.length-1)].offsetWidth-1 + CT_col_padding;
		var this_dummy_header_width = dummy_top_header.getElementsByTagName('table')[0].offsetWidth;
		var this_real_header_width  = real_top_header.offsetWidth + this_extra_col_width;
		
		// [Tabbed user view: 8 of 9]
		// correction for case where header is linked
		if ( BD_browser == 'Explorer' && dummy_top_header.getElementsByTagName('A') ) {
			this_dummy_header_width += 10;
		}
		
		//alert( this_dummy_header_width + ' ' + this_real_header_width ); 
		 		 		 	
		if ( BD_browser == 'Safari' || BD_browser == 'Chrome' ) {
			this_real_header_width++;
			if (this_dummy_header_width == 0) { this_dummy_header_width = this_real_header_width };
		}
		
		var window_width = document.documentElement.clientWidth;
		var scroll_width = document.documentElement.scrollWidth;
						  	 		  		 		 	
		if (  this_real_header_width != this_dummy_header_width     // narrow to wide
			|| window_width != scroll_width ) {	    	    // wide to narrow (window has x-scrollbar)

			// [Tabbed user view: 9 of 9]
			// enable page to be reloaded via form submit to preserve state
			if ( CT_resize_submit_id && document.getElementById( CT_resize_submit_id ) ) {
				//document.getElementById( CT_resize_submit_id ).submit();
			}
			else { 
				window.location.reload();
			}	
		}		
	}
}

function CT_unmask( ct_count ) {
	var ct_mask = document.getElementById( 'ct-' + ct_count + '-mask-1' );
	if ( ct_mask ) { ct_mask.style.display = 'none'; }
	var ct_mask_2 = document.getElementById( 'ct-' + ct_count + '-mask-2' );
	if ( ct_mask_2 ) { ct_mask_2.style.display = 'none'; }
}

function CT_highlight(cell) {
	if ( !CT_run_fixed_headers ) { return };

	cell.style.cursor = 'pointer';

	if ( cell.className.match( /hot/ ) ) {
		cell.style.backgroundColor = '#FFCCAE';
	}
	else if ( cell.className.match( /warmer/ ) ) {
		cell.style.backgroundColor = '#FFEBAE';				
	}
	else if ( cell.className.match( /warm/ ) ) {
		cell.style.backgroundColor = '#FFFFAE';
	}
	else {
		cell.style.backgroundColor = '#FFFFE8';
	}
}

function CT_unhighlight(cell) {
	if ( !CT_run_fixed_headers ) { return };
	cell.style.cursor = 'default';
	cell.style.backgroundColor = '';
}


function CT_align( table_div ) {

	var ct_id = table_div.getAttribute('id');
	var ct_no = ct_id.replace( /ct\-/,'' );
	
	var top   = CT_tops[ct_no];
	var left  = CT_lefts[ct_no];

	if ( top ) { top.scrollLeft = table_div.scrollLeft };
	if ( left ) { left.scrollTop = table_div.scrollTop }; 
}
	

// ###################################################################
// Old function still needed - ensures scrollbars present and correct
// ###################################################################

function CT_resize( ct_table ) {
		
	var cross_div_el = ct_table.parentNode;

	// --------------------------------------
	// special case for no scrolling
	// --------------------------------------
	if ( cross_div_el.className.match( /no\-scroll/ ) ) {		
		cross_div_el.style.height = 'auto';				
		cross_div_el.style.overflow = 'visible';				
		return;
	}

	// --------------------------------------
	// initialisation
	// --------------------------------------
	
	// find the inner <table> tag
	var table_els = cross_div_el.getElementsByTagName('TABLE');	
	var table_el = table_els[0];

	var shrink_wrap_x = 0;
	// shrink-wrap table if less wide than full width
	if ( cross_div_el.offsetWidth >= table_el.offsetWidth ) {
		shrink_wrap_x = 1;
	}
					
	// --------------------------------------------------
	// special case where we want X scrollbar only [ADAT]
	// --------------------------------------------------
	if ( cross_div_el.className.match( /x\-scroll\-only/ ) ) {

		cross_div_el.style.overflowY = 'visible';
		cross_div_el.style.overflowX = 'auto';
		cross_div_el.style.maxHeight = 'none'; 
		cross_div_el.style.width = ( '100%' );		

		if ( BD_browser == 'Explorer' ) { // IE Win, IE5 MAC
			// set height including height of scrollbar
			cross_div_el.style.height = ( (table_el.offsetHeight + CT_add_bot) +'px');
			
			if ( BD_OS == 'Windows' && BD_version >= 6 && BD_version < 7 ) { // prevent horiz scrollbar IE6
				cross_div_el.style.marginRight = '-2px';
			}	
		}
		else { // Others
			cross_div_el.style.height = 'auto';
		}

		return;
	}

	// --------------------------------------
	// set the HEIGHT of the cross-tab <div>
	// --------------------------------------

	if ( BD_browser == 'Explorer' ) { // INCLUDE IE5 MAC, IE 5 / 5.5 / 6

		if ( table_el.offsetHeight >= 1 // catch weird case IE6 when combined with tab menu
						// .. flicking between tabs makes table vanish

			&& table_el.offsetHeight < CT_max_height ) {

			if ( shrink_wrap_x == 1 ) {
				// shrink wrapped - no scrollbar, so just set height
				cross_div_el.style.height = ( table_el.offsetHeight +'px');
			}
			else {
				// set height including height of scrollbar
				cross_div_el.style.height = ( (table_el.offsetHeight + CT_add_bot) +'px');
			}
		}
		else {
			if ( BD_OS == 'Windows' && BD_browser == 'Explorer' ) {
				cross_div_el.style.overflowY = 'scroll'; 
			}
		}
	}
	
	// (other browsers handle this via max-height)

	// --------------------------------------
	// set the WIDTH of the cross-tab <div>
	// --------------------------------------

	// shrink-wrap table if less wide than full width
	if ( shrink_wrap_x ) {
		cross_div_el.style.width = ( ( table_el.offsetWidth + CT_add_right ) + 'px' );
	}

	// set to 100% wide scrolly box if greater than full width
	if ( BD_OS == 'Windows' 
		&& BD_browser == 'Explorer' 
		&& BD_version > 5.1 && BD_version < 6  ) { // IE5.5
		if ( table_el.offsetWidth > CT_avail_width ) {		
			cross_div_el.style.width = ( '100%' );
			cross_div_el.style.overflowX = 'scroll';
		}
		if ( shrink_wrap_x ) {
			cross_div_el.style.overflowX = 'visible';
		}
	}

	else {	
		if ( cross_div_el.offsetWidth > CT_avail_width ) {				
			cross_div_el.style.width = ( '100%' );
		}
	}
}
