var dummy = '$Id: fb_static_top.js,v 1.1.4.32 2010-01-26 18:27:54 cmontoya Exp $';

// Copyright (c) 2008 Orbis Technology Ltd. All Rights Reserved.
// PaddyPower Football Pages - Static Javascript Loaded *Before* Content.
// This should be as small as possible so the browser can start rendering -
// use fb_static_bottom.js for functions that aren't needed until later.

// ---------- Football Coupons (and things that resemble coupons) -------

// Football coupon details
var FBCPN    = {};
// Football coupon row details
var FBCPNROW = {};

// Handle football page-building message.
//
// To keep the size of some football pages down, some page sections are built
// up entirely by calls to this function, which dispatches to a fb_got_xxx
// function based on the msg_type argument, passing on any other args.
//
function fbmsg(msg_type) {
	
	if (msg_type == 'CPN') {
		fb_got_CPN.apply(this, arguments);
	} else if (msg_type == 'CPNROW') {
		fb_got_CPNROW.apply(this, arguments);
	} else if (msg_type == 'CPNENDROWS') {
		fb_got_CPNENDROWS.apply(this, arguments);
	} else if (msg_type == 'CPNMBS') {
		fb_got_CPNMBS.apply(this, arguments);
	} else if (msg_type == 'CPNROWMBS') {
		fb_got_CPNROWMBS.apply(this, arguments);
	} else if (msg_type == 'CPNEND') {
		fb_got_CPNEND.apply(this, arguments);
	} else {
		throw('Unexpected msg_type "' + msg_type + '"');
	}
}

// Handle CPN message - creates coupon object and table.
//
// Params:
//   fbcpn_id        - id for coupon table
//   category        -
//   disp_cat_id     -
//   more_feat_avail -
//   showing_all     -
//   has_hcaps       -
//   col_keys        - array of dynamic column keys (e.g. H, D, A)
//   col_names       - array of dynamic column names
//   coupon_sort     - Sort of coupon, e.g. SC (soccer no links) SH (soccer links) etc.
//
// Returns:
//   Nothing, but creates coupon object and table.
//
function fb_got_CPN(junk, fbcpn_id, category, disp_cat_id, more_feat_avail, showing_all, has_hcaps, coupon_sort, banker_min_matches, banker_max_matches, banker_acc_max, col_keys, col_names) {

	// Create a coupon object to hold info about this coupon.
	// NB - the parseInts are because '0' is true in JS (unlike 0)!
	var cpn =
	  { category:         category,
	    disp_cat_id:      disp_cat_id,
	    more_feat_avail:  parseInt(more_feat_avail),
	    showing_all:      parseInt(showing_all),
	    has_hcaps:        parseInt(has_hcaps),
	    col_keys:         col_keys,
	    col_names:        col_names,
	    coupon_sort:      coupon_sort,
	    banker_min_matches: parseInt(banker_min_matches),
	    banker_max_matches: parseInt(banker_max_matches),
	    banker_acc_max:    parseInt(banker_acc_max)
	  };

	FBCPN[fbcpn_id]  = cpn;

	// Mark TIME column as sorted (since it always must be) and the others as unsorted.
	cpn.sort_dirs = {};
	cpn.sort_dirs['TIME'] = 1;
	// The coupon is originally sorted by date.
	cpn.date_sort_dir = 1;
	for (var i = 0; i < col_keys.length; i++) {
		cpn.sort_dirs[col_keys[i]] = 0;
	}

	// Array of fbcpnrow_ids.
	cpn.row_ids = [];

	// Will be filled in elsewhere with more bets names.
	cpn.mb_names = {};

	// Used for section headers:
	cpn.prev_row_date = '';
	cpn.prev_type_name = '';
	
	cpn.checkbox_values =  new Hash();

	// The table always has this width (in pixels).
	var table_width = 600;
	// The static columns have these widths:
	// (time, name, icons, touchlines and more bets respectively).
	var static_widths = [55, 180, 25, 25, 70];
	
	// to cater cols for when more bets is not displayed
	if (coupon_sort == 'SC' || coupon_sort == 'BN')
	 var static_widths = [55, 280, 25];
	
	// The dynamic columns appear after the 3rd static column.
	var dynamic_posn = 3;

	// Decrease width of the the event name column if we're expecting a
	// particularly fat coupon.
	if (col_keys.length > 3 || (col_keys.length == 3 && cpn.has_hcaps)) {
		static_widths[1] -= 30;
	}
	
	// Decrease width of the the event name column and increase the width time columns for bankers coupons
	if (coupon_sort == 'BL' || coupon_sort == 'BN') {
		static_widths[0] += 30;
		static_widths[1] -= 30;
	}

	// Compute the widths of the dynamic columns, and merge them with
	// the static column widths to yield a list of col_widths.

	var col_widths = [];
	var static_width = 0;
	for(var i=0;i<static_widths.length;static_width+=static_widths[i++]);
	var dynamic_width = table_width - static_width;
	var dynamic_widths = [];
	var ncols = cpn.col_keys.length;
	var colsize = Math.round(dynamic_width / ncols);
	for (var i = 0; i < ncols; i++) {
		dynamic_widths.push(colsize);
	}
	// Because we rounded the colsize to an integer, we have to
	// correct the width of the last column (e.g. if we have a
	// width of 100 and 3 columns, we want 33,33,34).
	dynamic_widths[dynamic_widths.length-1]
	  += (dynamic_width - ncols*colsize);
	// Collate all the widths.
	for (var i = 0; i < dynamic_posn; i++) {
		col_widths.push(static_widths[i]);
	}
	for (var i = 0; i < dynamic_widths.length; i++) {
		col_widths.push(dynamic_widths[i]);
	}
	for (var i = dynamic_posn; i < static_widths.length; i++) {
		col_widths.push(static_widths[i]);
	}

	// Hack - the column widths need to add up to less than the table
	// width (particularly in IE) due to padding.
	var fudge = 6;
	for (var i = 0; i < col_widths.length; i++) {
		col_widths[i] -= fudge;
	}

	// Record the total number of columns (handy for colspans).
	// We also record the widths so we can use them when we start a
	// new table.
	cpn.total_cols  = col_widths.length;
	cpn.table_width = table_width;
	cpn.col_widths  = col_widths;

	var table_el = fbcpn_make_empty_table(fbcpn_id, cpn.table_width, cpn.col_widths);
	cpn.first_table_el = table_el;

	// Create table header.

	var thead_el = document.createElement('thead');
	var tr_el    = document.createElement('tr');
	var th_el, th_link_el;

	// Time column (sortable)
	th_el = document.createElement('th');
	th_el.id = fbcpn_id + 'colTIME';
	th_el.className = 'fbtbl';
	th_link_el = document.createElement('a');
	th_link_el.href = "javascript:fbcpn_sort('" + fbcpn_id + "','TIME');void(0);";
	th_link_el.appendChild(document.createTextNode(FB.xl_time));
	th_el.appendChild(th_link_el);
	tr_el.appendChild(th_el);

	// Event name and icon columns.
	th_el = document.createElement('th');
//	th_el.colSpan = 2;
	th_el.className = 'fbtbl';
	tr_el.appendChild(th_el);

	th_el = document.createElement('th');
//	th_el.colSpan = 2;
	th_el.className = 'fbtbl';
	tr_el.appendChild(th_el);

	// Dynamic columns (sortable).
	for (var i = 0; i < cpn.col_keys.length; i++) {
		var col_key  = cpn.col_keys[i];
		var col_name = cpn.col_names[i];
		th_el = document.createElement('th');
		th_el.id = fbcpn_id + 'col' + col_key;
		th_el.className = 'fbtbl txt-center';
		th_link_el = document.createElement('a');
		th_link_el.href = "javascript:fbcpn_sort('" + fbcpn_id + "','" + col_key + "');void(0);";
		th_link_el.appendChild(document.createTextNode(col_name));
		th_el.appendChild(th_link_el);
		tr_el.appendChild(th_el);
	}

	// Touchline and more bets columns.
	if (coupon_sort != 'SC' && coupon_sort != 'BN') {
		th_el = document.createElement('th');
		th_el.colSpan = 2;
		th_el.className = 'fbtbl';
		tr_el.appendChild(th_el);
  }
		thead_el.appendChild(tr_el);
		table_el.appendChild(thead_el);

	// The first table has no tbody. Rows with the same date will share
	// tables and tbodies, which get added to here.
	cpn.tbodies = [];

	// Add table to containing element. We do this up-front so the browser
	// has a chance to start rendering asap rather than showing a white
	// screen until the end. TODO - However, if this is ineffective, it
	// might be better not to add the table(s) to the page until later?

	cpn.holder_el = document.getElementById(fbcpn_id + '_holder');
	cpn.holder_el.appendChild(table_el);

}


// Make an empty coupon table with just classes and colgroup set up.
// Params:
//   table_id    - id to give the table
//   table_width - width of table in pixels
//   col_widths  - widths of columns in pixels
// Returns:
//   Table DOM element (not yet added to page).
//
function fbcpn_make_empty_table(table_id, table_width, col_widths) {

	var table_el = document.createElement('table');
	table_el.id                = table_id;
	table_el.className         = 'footballcard';
	table_el.style.width       = table_width + 'px';
	table_el.style.tableLayout = 'fixed';
	var cgroup_el = document.createElement('colgroup');
	var col_el;
	for (var i = 0; i < col_widths.length; i++) {
		col_el = document.createElement('col');
		col_el.style.width = col_widths[i] + 'px';
		cgroup_el.appendChild(col_el);
	}
	table_el.appendChild(cgroup_el);

	return table_el;
}


// Handle CPNROW message - creates coupon row object and adds row to table.
//
// Params:
//   fbcpn_id      - id of existing coupon table passed to fb_got_CPN
//   fbcpnrow_id   - id of proposed coupon row
//   ev_id         - event id
//   ev_name       - event name
//   srt_date      - sortable date (e.g. 2009-03-16)
//   srt_time      - sortable time (e.g. 19:45:00)
//   date_fmt      - date formatted for display to humans
//   time_fmt      - time formatted for display to humans
//   class_id      - event class id
//   type_id       - event type id
//   type_name     - event type name
//   touchline     - url for this event on Touchline website
//   has_mbs       - 0 if no Money Back Special, 1 if there is
//   has_br_flag   - 0 if no BR flag, 1 if there is
//   stations      - comma-seperated list of zero or more TV station names
//   tv_icon       - '', 'live_betting' or 'live_on_tv'.
//   stream        - 0 or 1
//   coupon_sort   - Sort of coupon, e.g. SC (soccer no links) SH (soccer links) etc.
// followed by zero or more col_key, sel_data args, where:
//   col_key       - column key for selection
//   sel_data      - array of selection data, with elements:
//     ev_oc_id
//     prc_str
//     lp_num
//     lp_den
//     hcap_str
//     hcap_val
//     tooltip
//
// Notes:
//   * Not all column keys need be supplied. A column with no selection will
//     be filled with an empty cell.
//
// Returns:
//   Nothing, but creates row object and HTML.
//
function fb_got_CPNROW(junk, fbcpn_id, fbcpnrow_id, ev_id, ev_name, srt_date, srt_time, date_fmt, time_fmt, class_id, type_id, type_name, touchline, has_mbs, has_br_flag, stations, tv_icon, stream, coupon_sort, bet_in_run,live_now, meets_banker_criteria, bankers_default, url) {

	// Position in the function arguments where the variable args start.
	// (should be equal to the number of arguments listed above).
	var vargs_offset = 22;
	
	var cpn = FBCPN[fbcpn_id];

	// Create coupon row object to hold info about this row (but not the selections).

	var cpnrow = {
	  id:        fbcpnrow_id,       fbcpn_id:    fbcpn_id,
	  ev_id:     ev_id,             ev_name:     ev_name,
	  srt_date:  srt_date,          srt_time:    srt_time,
	  date_fmt:  date_fmt,          time_fmt:    time_fmt,
	  class_id:  class_id,          type_id:     type_id,
	  type_name: type_name,         touchline:   touchline,
	  has_mbs:   parseInt(has_mbs), has_br_flag: parseInt(has_br_flag),
	  stations:  stations,          tv_icon:     tv_icon,
	  stream:    stream,            bet_in_run:  bet_in_run,
	  live_now:  live_now,
	  meets_banker_criteria:  meets_banker_criteria,
	  bankers_default:        bankers_default
	};
	
	FBCPNROW[fbcpnrow_id] = cpnrow;

	// The more bets stuff is done later 'cos it's so big.
	cpnrow.more_bets = [];

	// The srt_odds field will be filled in as selections get added:
	cpnrow.srt_odds = {};
	
	// contains the banker for this row
	cpnrow.banker = {};

	// Create new table if the date (or type for banker coupons) has changed since the last row.
	
	if (coupon_sort == 'BL' || coupon_sort == 'BN') {
		if (type_name != cpn.prev_type_name) {
			fbcpn_section_changed(fbcpn_id, type_name);
			cpn.prev_type_name = type_name;
		}
	} else {
		if (srt_date != cpn.prev_row_date) {
			fbcpn_section_changed(fbcpn_id, date_fmt);
			cpn.prev_row_date = srt_date;
		}
	}

	// Set up mapping from col_key to seln_data based on the variable
	// arguments.

	var col_keys = cpn.col_keys;
	var sel_data_for = {};
	for (var i = vargs_offset; i <= arguments.length - 2; i += 2) {
		var col_key = arguments[i];
		sel_data_for[col_key] = arguments[i + 1];
	}

	// Make coupon row element.
	var tr_el = document.createElement('tr');
	tr_el.id = fbcpnrow_id;
	var td_el, td_link_el, td_div_el;
	
	if (coupon_sort == 'BL' || coupon_sort == 'BN') {
		if (meets_banker_criteria != 1) {
			// hide the row
			tr_el.style.display = "none";
		}
	}

	var filter_array=new Array('of','st','nd', 'rd', 'th');
	// Time column
	td_el = document.createElement('td');
	td_el.className = 'time border';
	if (coupon_sort == 'BL' || coupon_sort == 'BN') {
		//td_el.appendChild(document.createTextNode(time_fmt +", "+ date_fmt));
		for (var i = 0; i < filter_array.length; i++ ) {
			date_fmt = date_fmt.replace(filter_array[i],"");
		}

		//replace year 2 digits, EG 2009 with 09
		year_value = date_fmt.substring(date_fmt.length -4, date_fmt.length);
		year_value = year_value.substring(2, 4);
		date_fmt = date_fmt.substring(0, date_fmt.length -4);
		date_fmt = date_fmt + year_value;
		//replace more than 1 run of spaces with 1 space
		date_fmt = date_fmt.replace(/\s+/g," ");
		var breakElem = document.createElement("BR");
		td_el.appendChild(document.createTextNode(time_fmt));
		td_el.appendChild(breakElem);
		td_el.appendChild(document.createTextNode(date_fmt));
		//td_el.appendChild(document.createTextNode(time_fmt +"<br />"+ date_fmt));
	} else {
		td_el.appendChild(document.createTextNode(time_fmt));
	}
	tr_el.appendChild(td_el);

	// Event name column (with link to event).
	td_el = document.createElement('td');
	td_el.className = 'time border';
	td_link_el = document.createElement('a');
	td_link_el.href = url;
// 	td_link_el.href = tld
// 	  + '?action=go_fb_event'
// 	  + '&ev_id='
// 	  + cpnrow.ev_id
// 	  + '&category='
// 	  + cpn.category
// 	  + '&disp_cat_id='
// 	  + cpn.disp_cat_id
// 	  + '&ev_class_id='
// 	  + cpnrow.class_id
// 	  ;
	// override the link if it's a betting in running event
	if (cpnrow.tv_icon == 'live_betting') {
		td_link_el.href = tld_football
		  + '?action=go_betlive_event'
		  + '&ev_id='
		  + cpnrow.ev_id
		  ;
	}
	td_link_el.appendChild(document.createTextNode(ev_name));
	td_el.appendChild(td_link_el);
	tr_el.appendChild(td_el);

	// Icons column.
	// TODO - can we make this less verbose by using innerHTML?
	td_el = document.createElement('td');
	td_el.className = 'tv border';
	if (!cpnrow.has_mbs && cpnrow.tv_icon == '' && cpnrow.stream == '') {
		td_el.innerHTML = '&nbsp;';
	} else {
		if (cpnrow.has_mbs) {
			var div_el = document.createElement('div');
			div_el.className = 'bull bred';
			div_el.title = 'Money Back Specials';
			div_el.appendChild(document.createTextNode(FB.xl_mbs));
			td_el.appendChild(div_el);
		}
		if (cpnrow.tv_icon != '') {
			var img_src = FB['img_' + cpnrow.tv_icon];
			var txt     = FB['xl_'  + cpnrow.tv_icon];
			var href    = '';
			if (cpnrow.tv_icon == 'live_on_tv') {
				if (cpnrow.stations != '') {
					txt += ' ' + cpnrow.stations;
				} else {
					txt += ' ' + 'TV';
				}
				if (cpnrow.has_br_flag) {
					href = tld + "?action=go_betlive_home";
				}
			}
			var ul1_el = document.createElement('ul');
			ul1_el.className = 'dd-tv';
			var li1_el  = document.createElement('li');
			if (href != '') {
				var a_el = document.createElement('a');
				a_el.href = href;
			}
			var img_el = document.createElement('img');
			img_el.src = img_src;
			img_el.className = 'left';


			if (href != '') {
				a_el.appendChild(img_el);
				li1_el.appendChild(a_el);
			} else {
				li1_el.appendChild(img_el);
			}
			var ul2_el = document.createElement('ul');
			var li2_el = document.createElement('li');
			li2_el.appendChild(document.createTextNode(txt));
			ul2_el.appendChild(li2_el);
			li1_el.appendChild(ul2_el);
			ul1_el.appendChild(li1_el);
			td_el.appendChild(ul1_el);
		}
		if (cpnrow.stream == '1') {
			var span_el     = document.createElement('span');
			span_el.className = 'streaming_video_icon';
			td_el.appendChild(span_el);
		}
	}
	tr_el.appendChild(td_el);

	// Dynamic columns (with odds links).
	for (var i = 0; i < cpn.col_keys.length; i++) {

		var col_key  = cpn.col_keys[i];
		var col_name = cpn.col_names[i];
		var sel_data = sel_data_for[col_key];

		td_el = document.createElement('td');
		// give the cell an id
		td_el.id = fbcpnrow_id + "_" + i;
		
		td_div_el = document.createElement('div');
		td_div_el.className = 'txt-center';

		if (sel_data == null) {
			// Non-existent or non-bettable selection.
			// Leave the cell empty.
		} else {

			var ev_oc_id  = sel_data[0];
			var prc_str   = sel_data[1];
			var lp_num    = sel_data[2];
			var lp_den    = sel_data[3];
			var hcap_str  = sel_data[4];
			var hcap_val  = sel_data[5];
			var tooltip   = sel_data[6];
			var mult_key  = sel_data[7];
			var banker    = sel_data[8];

			// Record the fractional price of the selection in this
			// column on the row - we need this for sorting.
			cpnrow.srt_odds[col_key] = [lp_num, lp_den];

			if (hcap_str != '') {
				var span_el = document.createElement('span');
				span_el.className = 'hcap_str';
				span_el.appendChild(document.createTextNode(hcap_str + ' '));
				td_div_el.appendChild(span_el);
			}
			td_link_el = document.createElement('a');

			// Give the link a dummy href & add an onclick to the cell instead.

			td_link_el.href = 'javascript:void(0)';
			
			var price_type = "L";

			// Ugly but avoids worrying about closures and avoids need to
			// compile them now.
			var placebet =
				"BS_set_leg('price_type','" + price_type + "');" +
				"BS_set_leg('lp_num','"     + lp_num     + "');" +
				"BS_set_leg('lp_den','"     + lp_den     + "');" +
				"BS_set_leg('selections','" + ev_oc_id   + "');" +
				"BS_set_leg('hcap_value','" + hcap_val   + "');" +
				"BS_go_bet();"

			 // build up the function to be called in place_bankers_bets
			// the params stake and legs will be in scope when this 
			// is eval'd in place_bankers_bets and not in scope here
			var placebet_bankers = 
				"bankers_set_leg("      +
				"'" + ev_oc_id   + "'," +
				"'" + price_type + "'," +
				"'" + lp_num     + "'," +
				"'" + lp_den     + "'," +
				"'" + hcap_val   + "'," +
				"legs,"            +
				"stake);"


			td_el.onclick = new Function(placebet);
			
			//style the cell, store this rows banker details
			if (banker == 1 && (coupon_sort == 'BL' || coupon_sort == 'BN')) {
				td_el.className += ' fbhlt fbhlt_banker';
				if (col_key  == "D") {
					tr_el.style.display = "none";
				} else {
					cpnrow.srt_odds["BANKER"] = [lp_num, lp_den];
					cpnrow.banker.price_dec        = lp_num/lp_den + 1;
					cpnrow.banker.prc_str          = prc_str;
					cpnrow.banker.ev_name          = ev_name;
					cpnrow.banker.pb_func          = placebet_bankers;
					cpnrow.banker.col_key          = col_key;
					cpnrow.banker.col_key          = col_key;
					cpnrow.banker.col_name         = col_name;
					cpnrow.banker.mult_key         = mult_key;
					cpnrow.banker.ev_oc_id         = ev_oc_id;
					cpnrow.banker.bankers_default  = bankers_default;
				}
			} else {
				td_el.className += ' fbhlt';
			}
			
			td_link_el.innerHTML = prc_str;
			if (hcap_str != '') {
				var span_el = document.createElement('span');
				span_el.className = 'hcap_prc';
				span_el.appendChild(td_link_el);
				td_div_el.appendChild(span_el);
			} else {
				td_div_el.appendChild(td_link_el);
			}

			if (tooltip != '') {
				var span_el1 = document.createElement('span');
				var span_el2 = document.createElement('span');
				span_el1.className = 'fbtip_outer';
				span_el2.className = 'fbtip_inner';
				span_el2.innerHTML = tooltip;
				span_el1.appendChild(span_el2);
				td_el.appendChild(span_el1);
			}

		}

		td_el.appendChild(td_div_el);
		tr_el.appendChild(td_el);

	}
	
	if (coupon_sort != 'SC' && coupon_sort != 'BN') {
		// Touchline column.
		td_el = document.createElement('td');
		td_el.className = 'stats txt-center';
		if (cpnrow.touchline != '') {
			td_link_el = document.createElement('a');
			td_link_el.href = cpnrow.touchline;
			var img_el = document.createElement('img');
			img_el.src = FB.img_stat;
			img_el.className = 'left';
			img_el.alt = 'stat';
			td_link_el.appendChild(img_el);
			td_el.appendChild(td_link_el);
		} else {
			td_el.innerHTML = '&nbsp;';
		}
		tr_el.appendChild(td_el);
	
		// More bets column.
		td_el = document.createElement('td');
		td_el.className = 'bets';
		tr_el.appendChild(td_el);
		// This will get populated in a later pass - see fb_get_CPNMB.
		cpnrow.more_bets_el = td_el;
	}

	// Add row to coupon's tbody.

	cpn.tbodies[cpn.tbodies.length-1].appendChild(tr_el);

	// Add row to coupon object.

	cpn.row_ids.push(fbcpnrow_id);

}


// When the date or type (banker coupons are grouped by type) changes, we split off into a new table.
// This helps rendering and sorting performance, but relies on:
//
//   a) Rows always being sorted by date
//   b) A fixed table layout so columns have the same widths
//
function fbcpn_section_changed(fbcpn_id, section_str) {

	var cpn   = FBCPN[fbcpn_id];

	var table_id = fbcpn_id + 'd' + cpn.tbodies.length;

	var table_el = fbcpn_make_empty_table(table_id, cpn.table_width, cpn.col_widths);

	// Create table header (with date string).

	var thead_el  = document.createElement('thead');
	var tr_el     = document.createElement('tr');
	var td_el     = document.createElement('td');
	td_el.colSpan = cpn.total_cols;
	var strong_el = document.createElement('strong');
	strong_el.appendChild(document.createTextNode(section_str));
	td_el.appendChild(strong_el);
	tr_el.appendChild(td_el);
	thead_el.appendChild(tr_el);
	table_el.appendChild(thead_el);

	// Create table body (empty so far).

	var tbody_el = document.createElement('tbody');
	cpn.tbody_el = tbody_el;
	table_el.appendChild(tbody_el);

	// Add table to holder.

	cpn.holder_el.appendChild(table_el);

	// Add to list of tbodies. Future rows get added to the last of these.

	cpn.tbodies.push(tbody_el);

}


// Handle CPNENDROWS message.
//
function fb_got_CPNENDROWS(junk, fbcpn_id) {

	var cpn   = FBCPN[fbcpn_id];

	// no-op for now

}


// Handle CPNMBS message - records names of all "more bets" mkts.
//
function fb_got_CPNMBS(junk, fbcpn_id) {

	// Position in the function arguments where the variable args start.
	// (should be equal to the number of arguments listed above).
	var vargs_offset = 2;

	var cpn   = FBCPN[fbcpn_id];

	for (var i = vargs_offset; i <= arguments.length; i +=2 ) {
		var mb_idx  = arguments[i + 0];
		var mb_name = arguments[i + 1];
		cpn.mb_names[mb_idx] = mb_name;
	}

}


// Handle CPNROWMBS message - sets up "more bets" for a coupon row.
//
function fb_got_CPNROWMBS(junk, fbcpnrow_id, url) {

	// Position in the function arguments where the variable args start.
	// (should be equal to the number of arguments listed above).
	var vargs_offset = 3;

	var cpnrow   = FBCPNROW[fbcpnrow_id];
	var fbcpn_id = cpnrow.fbcpn_id;
	var cpn      = FBCPN[fbcpn_id];

	var num_bets = (arguments.length - vargs_offset) / 2;

	if (num_bets == 0) {
		// No bets - nothing to do.
	} else {

		// Outer unordered list.

		var ul_el = document.createElement('ul');
		ul_el.className = 'dd-mkt';
		var li_el = document.createElement('li');
		ul_el.appendChild(li_el);

		// Link to event.

		var a_el = document.createElement('a');
		a_el.className = 'more';
		a_el.href = url;
// 		a_el.href = tld
// 		  + '?action=go_fb_event'
// 		  + '&ev_id='
// 		  + cpnrow.ev_id
// 		  + '&category='
// 		  + cpn.category
// 		  + '&disp_cat_id='
// 		  + cpn.disp_cat_id
// 		  + '&ev_class_id='
// 		  + cpnrow.class_id
// 		  ;

		// Count and more bets text.

		a_el.appendChild(document.createTextNode(num_bets));
		var span_el = document.createElement('span');
		span_el.appendChild(document.createTextNode(FB.xl_more_bets));
		a_el.appendChild(span_el);

		li_el.appendChild(a_el);
		ul_el.appendChild(li_el);
		cpnrow.more_bets_el.appendChild(ul_el);

		// We won't actually generate the list of individual markets
		// until the user puts his mouse near the table cell for the
		// first time - at which point fb_make_more_bets will kick in.

		var ul2_el = document.createElement('ul');
		li_el.appendChild(ul2_el);
		cpnrow.more_bets_inner_el = ul2_el;
		cpnrow.made_more_bets = false;
		for (var i = vargs_offset; i < arguments.length; i += 2) {
			var mb_idx  = arguments[i + 0];
			var grp_id  = arguments[i + 1];
			// The earlier CPNMBS message should have set up the
			// mb_idx -> name mapping for the coupon.
			var mb_name = cpn.mb_names[mb_idx];
			cpnrow.more_bets.push( [mb_name, grp_id ] );
		}
		//cpnrow.more_bets_el.onmouseover = function () {
			fb_make_more_bets(fbcpnrow_id);
		//}

	}

}


// See fb_got_CPNROWMBS - lazily generates the More Bets links.
//
function fb_make_more_bets(fbcpnrow_id) {

	var cpnrow   = FBCPNROW[fbcpnrow_id];

	if (cpnrow.made_more_bets || cpnrow.more_bets.length == 0) {
		return;
	}

	var fbcpn_id = cpnrow.fbcpn_id;
	var cpn      = FBCPN[fbcpn_id];

	var mb_el = cpnrow.more_bets_inner_el;

	for (var i = 0; i < cpnrow.more_bets.length; i++) {
		var mb = cpnrow.more_bets[i];
		var mb_name   = mb[0];
		var mb_grp_id = mb[1];
		var li_el = document.createElement('li');
		var a_el  = document.createElement('a');

		// If this is a betting in running event
		if ((cpnrow.tv_icon == 'live_betting' || cpnrow.stream == 1 || cpnrow.live_now == 'Y') && cpnrow.bet_in_run == 'Y') {
			a_el.href = tld_football
			+ '?action=go_betlive_event'
			+ '&ev_id='
			+ cpnrow.ev_id
			+ '&ev_oc_grp_ids='
			+ mb_grp_id
			+ '#link_'
			+ mb_grp_id;
		} else {
			a_el.href = tld_football
			+ '?action=go_fb_type'
			+ '&category='
			+ cpn.category
			+ '&disp_cat_id='
			+ cpn.disp_cat_id
			+ '&ev_class_id='
			+ cpnrow.class_id
			+ '&ev_type_id='
			+ cpnrow.type_id
			+ '&ev_oc_grp_ids='
			+ mb_grp_id
			+ '#link_'
			+ cpnrow.ev_id;
		}

		a_el.appendChild(document.createTextNode(mb_name));
		li_el.appendChild(a_el);
		mb_el.appendChild(li_el);
	}

	cpnrow.made_more_bets = true;

	return false;
}


// Handle "CPNEND" message - finishes off the coupon table.
//
function fb_got_CPNEND(junk, fbcpn_id) {

	var cpn   = FBCPN[fbcpn_id];

	// Update the sort indicators (ensures images are preloaded).

	fbcpn_upd_sort_indicators(fbcpn_id);

	// Show a no markets message if we failed to add any rows.

	if (cpn.tbodies.length == 0) {
		var tbody  = document.createElement('tbody');
		var tr     = document.createElement('tr');
		var td     = document.createElement('td');
		var h3 	   = document.createElement('h3');
		var editlink = document.createElement('a');
		td.colSpan = cpn.total_cols;
		td.className = "no-mkts-msg";
		h3.appendChild(document.createTextNode(FB.xl_cpn_no_mkts_hdr));
		td.appendChild(h3);
		td.appendChild(document.createTextNode(FB.xl_cpn_no_mkts_msg1));
		editlink.appendChild(document.createTextNode(FB.xl_cpn_edit_matches));
		editlink.setAttribute("href","?action=go_acct_details#mymatches");
		editlink.setAttribute("style","display:block;padding-top:4px");
		td.appendChild(editlink);
		tr.appendChild(td);
		tbody.appendChild(tr);
		cpn.first_table_el.appendChild(tbody);
	}

	// If there are more featured matches available than are shown,
	// add a link to show them all after the coupon table.

	if (cpn.more_feat_avail) {
		var div_el = document.createElement('div');
		div_el.className = 'footballcard details';
		var ul_el = document.createElement('ul');
		ul_el.className = 'form-race right';
		var li_el = document.createElement('li');
		var a_el = document.createElement('a');
		a_el.className = 'update';
		a_el.appendChild(document.createTextNode(FB.xl_show_all));
		a_el.href = "javascript:fb_home_load_tab('" + fbcpn_id + "', '&show_all=1');void(0);";
		li_el.appendChild(a_el);
		ul_el.appendChild(li_el);
		div_el.appendChild(ul_el);
		cpn.holder_el.appendChild(div_el);
	}

}


// Update the coupon sort direction indicators.
//
function fbcpn_upd_sort_indicators(fbcpn_id) {

	var cpn = FBCPN[fbcpn_id];

	var col_keys = ['TIME'].concat(cpn.col_keys);

	for (var i = 0; i < col_keys.length; i++) {

		var col_key = col_keys[i];

		// Find the "th" element for this column.

		var col_th_id = fbcpn_id + 'col' + col_key;
		var col_th = document.getElementById(col_th_id);
		if (col_th == null) {
			continue;
		}

		// Look for the ascending/descending images inside it.
		// Add them if they don't exist.
		
		var anchors = col_th.getElementsByTagName('a');
		var a = anchors[0];
		var imgs = a.getElementsByTagName('img');
		
		if (!imgs.length) {
			var img0 = document.createElement('img');
			img0.src = FB.img_sort_asc;
			img0.alt = '(asc.)';
			img0.style.display = 'none';
			a.appendChild(img0);
			var img1 = document.createElement('img');
			img1.src = FB.img_sort_dsc;
			img1.alt = '(desc.)';
			img1.style.display = 'none';
			a.appendChild(img1);
			imgs = [ img0, img1 ];
		}

		// Hide or show them as appropriate for this column.

		if (cpn.sort_dirs[col_key] == -1) {
			imgs[0].style.display = 'none';
			imgs[1].style.display = 'inline';
		} else if (cpn.sort_dirs[col_key] == 1) {
			imgs[0].style.display = 'inline';
			imgs[1].style.display = 'none';
		} else {
			imgs[0].style.display = 'none';
			imgs[1].style.display = 'none';
		}

	}

	return;
}

//draw the num selns option dowp down
function build_bankers_options(fbcpn_id, ccy_symbol) {
	var cpn = FBCPN[fbcpn_id];
	
	cpn.ccy_symbol = ccy_symbol;

	// build the num selns bankers calulator drop down
	var num_selns_select = document.getElementById(fbcpn_id+ "_banker_num_selns");
	
	var num_options  = cpn.bankers.length;
	
	num_selns_select.options[num_selns_select.options.length] = new Option("All", num_options);
	
	for (var option = 1; option <= num_options; option++) {
		num_selns_select.options[num_selns_select.options.length] = new Option(option, option);
	}
	
	// forse the 5th option to be selected (if exists)
	try {
		num_selns_select.options[5].selected = true;
	} catch (e){}
}

// only display up to the threshhold number of bankers events
// shortest odds first (although we actually dsiplay in type and date order)
function enforce_bankers_threshold(fbcpn_id) {
	
	var cpn = FBCPN[fbcpn_id];
	
	var domrows_by_id = [];
	var cpnrows = [];
	
	cpn.bankers         = [];
	
	var default_rows = 0;
	
	for (var j = 0; j < cpn.tbodies.length; j++) {

		var tbody = cpn.tbodies[j];

		// Loop over the DOM rows in the body of the table, looking
		// up the corresponding cpnrow objects and construcing a
		// mapping from id to DOM row.
		for (var i = 0; i < tbody.rows.length; i++) {
			var domrow       = tbody.rows[i];
			var fbcpnrow_id  = domrow.id;
			var cpnrow       = FBCPNROW[fbcpnrow_id];
			
			if (cpnrow.meets_banker_criteria == 1) {
				cpnrows.push(cpnrow);
				domrows_by_id[fbcpnrow_id] = domrow;
			}
			
			if (cpnrow.bankers_default == 1) {
				default_rows++;
			}
		}
	}
	
	// max matches not set, show all
	if (cpn.banker_max_matches == "") {
		cpn.banker_max_matches = cpnrows.length;
	}
	
	// deal with loads of default teams
	if (default_rows >  cpn.banker_max_matches) {
		default_rows = cpn.banker_max_matches;
	}
	
	// Sort the coupon rows (using a helper function/closure). by banker price
	cpnrows.sort(
		function(a,b) {
			return fbcpn_cmp_rows("BANKER",1,a,b);
		}
	);
	
	var all_rows_added     = 0;
	var default_rows_added = 0;
	
	var mult_keys =  new Hash();
	
	// go through in banker price order hide everything over the threshold
	// if we are under the threshhold add banker object arrays stored in the coupon obj
	for (var i = 0; i < cpnrows.length; i++) {
		var cpnrow = cpnrows[i];
		var fbcpnrow_id = cpnrow.id;
		
		var matches_prev_mult_key = 0;
		
		//check if we have seen this mult ke before, if we have don't add the row
		// otherwise we'll get bet placement errors
		if (cpnrow.banker.mult_key != "") {
			if (mult_keys.get(cpnrow.banker.mult_key) != cpnrow.banker.mult_key) {
				mult_keys.set(cpnrow.banker.mult_key, cpnrow.banker.mult_key);
			} else {
				var matches_prev_mult_key = 1;
			}
		}
		
		if (!matches_prev_mult_key) {
			// add rows under the threshhold but take into account the default rows we will have to add later
			if ((all_rows_added - default_rows_added) < (cpn.banker_max_matches - default_rows)) {
				
				cpn.bankers.push(cpnrow.banker);
				
				// a default row but it fits the criteria too, add it and take note
				if (cpnrow.bankers_default == 1) {
					default_rows_added++;
				}
				all_rows_added++
				
			} else if (default_rows_added < default_rows) {
				//add the remaining defaults if there is room, we should have made sure there is enough
				//space for all defaults
				if (cpnrow.bankers_default == 1) {
					cpn.bankers.push(cpnrow.banker);
					
					default_rows_added++;
					all_rows_added++
				} else {
					domrows_by_id[fbcpnrow_id].style.display = "none";
					$j('tr#'+fbcpnrow_id+' a').hide();
				}
			} else {
				// the rest remain hidden
				domrows_by_id[fbcpnrow_id].style.display = "none";
				$j('tr#'+fbcpnrow_id+' a').hide();
			}
		} else {
			// hide this as the mult key has been used already
			domrows_by_id[fbcpnrow_id].style.display = "none";
			$j('tr#'+fbcpnrow_id+' a').hide();
		}
	}
	
	// now find any tbodies that have all rows hidden
	for (var j = 0; j < cpn.tbodies.length; j++) {

		var tbody = cpn.tbodies[j];
		var shown = 0;
		for (var i = 0; i < tbody.rows.length; i++) {
			var domrow       = tbody.rows[i];
			var fbcpnrow_id  = domrow.id;
			var cpnrow       = FBCPNROW[fbcpnrow_id];
			
			if(cpnrow !== null && domrow.style.display != "none") {
				shown++
			}
		}
		
		// and hide the table
		if (shown == 0) {
			tbody.parentNode.style.display = "none";
		}
	}
	
	// if there are events over the threshhold show a widget to display them
	if (cpn.banker_max_matches < cpnrows.length) {
		document.getElementById(fbcpn_id+ "_avail_bankers").style.display = "";
		document.getElementById(fbcpn_id+ "_hide_bankers").style.display = "none";
		document.getElementById(fbcpn_id+ "_show_bankers").style.display = "";
	}
}

// show all bankers events regardless of the threshhold
function unenforce_bankers_threshold(fbcpn_id) {
	var cpn = FBCPN[fbcpn_id];
	
	for (var j = 0; j < cpn.tbodies.length; j++) {
		// Loop over the DOM rows in the body of the table, looking
		// up the corresponding cpnrow objects
		var tbody = cpn.tbodies[j];
		var shown = 0;
		for (var i = 0; i < tbody.rows.length; i++) {
			var domrow       = tbody.rows[i];
			var fbcpnrow_id  = domrow.id;
			var cpnrow       = FBCPNROW[fbcpnrow_id];
			if (cpnrow.meets_banker_criteria == 1) {
				domrow.style.display = "";
				//domrow.style.display = "block";
				shown++;
				$j(domrow).find('a').show();
			}
		}
		// and show all the tables with stuff inside them
		if (shown > 0) {
			tbody.parentNode.style.display = "";
			//tbody.parentNode.style.display = "block";
		}
	}
	
	document.getElementById(fbcpn_id+ "_hide_bankers").style.display = "";
	document.getElementById(fbcpn_id+ "_show_bankers").style.display = "none";
}

function place_bankers_bets(fbcpn_id) {
	var cpn = FBCPN[fbcpn_id];
	
	var num_selns_select = document.getElementById(fbcpn_id+ "_banker_num_selns");
	var stake_select     = document.getElementById(fbcpn_id+ "_banker_stake");
	
	var num_selns = parseInt(num_selns_select.options[num_selns_select.selectedIndex].value);
	var stake     = BS_format_stake(stake_select.options[stake_select.selectedIndex].value);
	
	var pb_func = "";
	var legs = 0
	
	// num selns must not be greter then the smallest acc max of the markets in this coupon
	if (num_selns > cpn.banker_acc_max) {
		num_selns = cpn.banker_acc_max;
	}
	
	// num selns must not be larger than the number of bankers we have found
	if (num_selns > cpn.bankers.length) {
		num_selns = cpn.bankers.length;
	}
	
	// add each leg, eval will be executing multiple 'bankers_set_leg' calls
	for (var j = 0; j < num_selns; j++) {
		// only include this in the calculations if the check box is checked
		if(cpn.checkbox_values.get(cpn.bankers[j].ev_oc_id) == true || cpn.checkbox_values.get(cpn.bankers[j].ev_oc_id) == null) {
			pb_func += cpn.bankers[j].pb_func;
			legs++
		}
	}
	
	eval(pb_func);
	
	// set the acc stake
	if (legs > 1) {
		BS_set_extra_info("acc_stake", stake);
	}
	
	// finalise and display bets in slip
	BS_go_bets();
}

// helper function, adds a leg to the bet slip
function bankers_set_leg(ev_oc_id, price_type, lp_num, lp_den, hcap_value, legs, stake) {
	BS_set_leg('price_type', price_type);
	BS_set_leg('lp_num',     lp_num);
	BS_set_leg('lp_den',     lp_den);
	BS_set_leg('selections', ev_oc_id);
	BS_set_leg('hcap_value', hcap_value);
	
	if (legs == 1) {
		BS_set_leg('stake', stake);
	}
	
	BS_select_bet(ev_oc_id);
}

function build_banker_tool(fbcpn_id) {
	var cpn = FBCPN[fbcpn_id];
	
	var num_selns_select = document.getElementById(fbcpn_id+ "_banker_num_selns");
	var stake_select     = document.getElementById(fbcpn_id+ "_banker_stake");
	var returns_span     = document.getElementById(fbcpn_id+ "_bankers_returns");
	
	var tool_table       = document.getElementById(fbcpn_id+ "_banker_bet_tool");
	
	var num_selns = parseInt(num_selns_select.options[num_selns_select.selectedIndex].value);
	var stake     = parseInt(stake_select.options[stake_select.selectedIndex].value);
	
	var mult_keys =  new Hash();
	
	var bankercount  = 1;
	
	// remove all rows from the tool
	while (tool_table.rows.length) {
		tool_table.deleteRow(tool_table.rows.length - 1);
	}
	
	if (num_selns > cpn.bankers.length) {
		num_selns = cpn.bankers.length;
	}
	
	for (var j = 0; j < num_selns; j++) {
		
		// only include this in the calculations if the check box is checked
		if(cpn.checkbox_values.get(cpn.bankers[j].ev_oc_id) == true || cpn.checkbox_values.get(cpn.bankers[j].ev_oc_id) == null) {
			stake = stake * cpn.bankers[j].price_dec;
		}
		
		add_seln_to_tool(fbcpn_id, cpn.bankers[j], bankercount, tool_table, num_selns);
		bankercount++
	}
	
	returns_span.innerHTML = cpn.ccy_symbol + BS_format_stake(stake);
}

// add an event ot the bankers bet tool
function add_seln_to_tool(fbcpn_id, banker, count, table, num_selns) {
	
	var cpn = FBCPN[fbcpn_id];
	
	var row = null;
	
	if (count % 2 == 1) {
		row = table.insertRow(table.rows.length);
	} else {
		row = table.rows[table.rows.length - 1];
	}
	
	var input_td  = document.createElement("td");
	input_td.setAttribute('class', 'nohover');	
	input_td.style.width ="20px";

	var input  = document.createElement("input");
	input.type= "checkbox";
	input.name = fbcpn_id +"_add_to_banker_name";
	input.id   = fbcpn_id +"_add_to_banker_name";
	input.value = banker.ev_oc_id;
	
	input.onclick = new Function("update_checkbox('','" +fbcpn_id+ "')");

	if(cpn.checkbox_values.get(banker.ev_oc_id) == true) {
		input.defaultChecked = true;
		input.checked = true;
	} else if (cpn.checkbox_values.get(banker.ev_oc_id) == false) {
		input.defaultChecked = false;
		input.checked = false;
	} else {
		input.defaultChecked = true;
		input.checked = true;
	}

	input_td.onmouseover = function ()
	{	
		this.style.background = "transparent url(/img/sb/football/bank_bet_bg_hover.png) repeat-x top left";
		this.nextSibling.style.background = "transparent url(/img/sb/football/bank_bet_bg_hover.png) repeat-x top left";
		this.nextSibling.nextSibling.style.background = "transparent url(/img/sb/football/bank_bet_bg_hover.png) repeat-x top left";
		this.nextSibling.nextSibling.nextSibling.style.background = "transparent url(/img/sb/football/bank_bet_bg_hover.png) repeat-x top left";
	};
	input_td.onmouseout = function ()
	{
		this.style.background = "url(/img/sb/football/bank_coupon_bg.jpg) repeat-x bottom left"; 
		this.nextSibling.style.background = "url(/img/sb/football/bank_coupon_bg.jpg) repeat-x bottom left";  
		this.nextSibling.nextSibling.style.background = "url(/img/sb/football/bank_coupon_bg.jpg) repeat-x bottom left";  
		this.nextSibling.nextSibling.nextSibling.style.background = "url(/img/sb/football/bank_coupon_bg.jpg) repeat-x bottom left";  
	};

	input_td.appendChild(input);

	var info_td  = document.createElement("td");
	var price_td  = document.createElement("td");
	var home_away_td  = document.createElement("td");
	
	info_td.onmouseover = function ()
	{	
		this.style.background = "transparent url(/img/sb/football/bank_bet_bg_hover.png) repeat-x top left";  
		this.previousSibling.style.background = "transparent url(/img/sb/football/bank_bet_bg_hover.png) repeat-x top left";
		this.nextSibling.style.background = "transparent url(/img/sb/football/bank_bet_bg_hover.png) repeat-x top left";
		this.nextSibling.nextSibling.style.background = "transparent url(/img/sb/football/bank_bet_bg_hover.png) repeat-x top left";
	};
	info_td.onmouseout = function ()
	{	this.style.background = "url(/img/sb/football/bank_coupon_bg.jpg) repeat-x bottom left"; 
		this.previousSibling.style.background = "url(/img/sb/football/bank_coupon_bg.jpg) repeat-x bottom left";  
		this.nextSibling.style.background = "url(/img/sb/football/bank_coupon_bg.jpg) repeat-x bottom left";  
		this.nextSibling.nextSibling.style.background = "url(/img/sb/football/bank_coupon_bg.jpg) repeat-x bottom left";  
	};
	
	
	price_td.onmouseover = function ()
	{	
		this.style.background = "transparent url(/img/sb/football/bank_bet_bg_hover.png) repeat-x top left";  
		this.previousSibling.previousSibling.style.background = "transparent url(/img/sb/football/bank_bet_bg_hover.png) repeat-x top left";
		this.previousSibling.style.background = "transparent url(/img/sb/football/bank_bet_bg_hover.png) repeat-x top left";
		this.nextSibling.style.background = "transparent url(/img/sb/football/bank_bet_bg_hover.png) repeat-x top left";
	};
	price_td.onmouseout = function ()
	{	this.style.background = "url(/img/sb/football/bank_coupon_bg.jpg) repeat-x bottom left"; 
		this.previousSibling.previousSibling.style.background = "url(/img/sb/football/bank_coupon_bg.jpg) repeat-x bottom left";  
		this.previousSibling.style.background = "url(/img/sb/football/bank_coupon_bg.jpg) repeat-x bottom left";  
		this.nextSibling.style.background = "url(/img/sb/football/bank_coupon_bg.jpg) repeat-x bottom left";  
	};	
	
	home_away_td.onmouseover = function ()
	{	
		this.style.background = "transparent url(/img/sb/football/bank_bet_bg_hover.png) repeat-x top left";  
		this.previousSibling.style.background = "transparent url(/img/sb/football/bank_bet_bg_hover.png) repeat-x top left";
		this.previousSibling.previousSibling.style.background = "transparent url(/img/sb/football/bank_bet_bg_hover.png) repeat-x top left";
		this.previousSibling.previousSibling.previousSibling.style.background = "transparent url(/img/sb/football/bank_bet_bg_hover.png) repeat-x top left";
	};
	home_away_td.onmouseout = function ()
	{	this.style.background = "url(/img/sb/football/bank_coupon_bg.jpg) repeat-x bottom left"; 
		this.previousSibling.style.background = "url(/img/sb/football/bank_coupon_bg.jpg) repeat-x bottom left";  
		this.previousSibling.previousSibling.style.background = "url(/img/sb/football/bank_coupon_bg.jpg) repeat-x bottom left";  
		this.previousSibling.previousSibling.previousSibling.style.background = "url(/img/sb/football/bank_coupon_bg.jpg) repeat-x bottom left";  
	};	

	var event_name_div  = document.createElement("div");
	event_name_div.setAttribute('class', 'event_name');
	event_name_div.style.cssFloat ="left";
	event_name_div.style.styleFloat ="left";			
	event_name_div.style.width = "175px";
	event_name_div.style.marginLeft ="2px";			
	event_name_div.appendChild(document.createTextNode(banker.ev_name));
	info_td.appendChild(event_name_div);
	info_td.onclick  = new Function("update_checkbox('" +banker.ev_oc_id+ "','" +fbcpn_id+ "')");
	
	home_away_td.style.borderRight ="1px solid #DDDDDD";
	home_away_td.setAttribute('class', 'hashover');		
	var home_away_div  = document.createElement("div");
	home_away_div.setAttribute('class', 'home_away');
	home_away_div.style.cssFloat ="right";
	home_away_div.style.textTransform ="uppercase";
	home_away_div.style.fontSize ="10px";
	home_away_div.style.styleFloat ="right";		
	home_away_div.style.textAlign ="right";			
	home_away_div.style.width = "36px";
	home_away_div.style.marginRight = "5px";	
	home_away_div.appendChild(document.createTextNode(banker.col_name));
	home_away_td.appendChild(home_away_div);	
	home_away_td.onclick  = new Function("update_checkbox('" +banker.ev_oc_id+ "','" +fbcpn_id+ "')");
	
	price_td.setAttribute('class', 'hashover');		
	var price_div  = document.createElement("div");
	price_div.setAttribute('class', 'price');
	price_div.style.fontWeight ="bold";
	price_div.style.cssFloat ="right";
	price_div.style.styleFloat ="right";		
	price_div.style.textAlign ="center";			
	price_div.style.width = "40px";
	price_div.style.marginRight = "10px";	
	price_div.appendChild(document.createTextNode(banker.prc_str));
	price_td.appendChild(price_div);
	price_td.onclick  = new Function("update_checkbox('" +banker.ev_oc_id+ "','" +fbcpn_id+ "')");	
	
	if(!input.checked) {
		input_td.className     = 'banker_unselected';
		info_td.className     = 'banker_unselected';		
	}
	
	row.appendChild(input_td);
	row.appendChild(info_td);	
	row.appendChild(price_td);	
	row.appendChild(home_away_td);	
	
	if((count ==  num_selns) && (num_selns % 2 == 1)) {
		var blank1  = document.createElement("td");
		blank1.setAttribute('class', 'nohover');			
		row.appendChild(blank1);	
		var blank2  = document.createElement("td");
		blank2.setAttribute('class', 'nohover');			
		row.appendChild(blank2);			
	} 

	if (num_selns == 1) {
		// blank cells
		var blank  = document.createElement("td");
		//blank.style.width = "50%"
		row.appendChild(blank);
	}

}

/*
function add_seln_to_tool(fbcpn_id, banker, count, table, num_selns) {
	
	var cpn = FBCPN[fbcpn_id];
	
	var row = null;
	
	if (count % 2 == 1) {
		row = table.insertRow(table.rows.length);
	} else {
		row = table.rows[table.rows.length - 1];
	}
	
	var input_td  = document.createElement("td");
	
	var input  = document.createElement("input");
	input.type= "checkbox";
	input.name = fbcpn_id +"_add_to_banker_name";
	input.id   = fbcpn_id +"_add_to_banker_name";
	input.value = banker.ev_oc_id;
	input.onclick = new Function("update_checkbox('','" +fbcpn_id+ "')");
	
	input_td.appendChild(input);
	
	if(cpn.checkbox_values.get(banker.ev_oc_id) == true) {
		input.checked = true;
	} else if (cpn.checkbox_values.get(banker.ev_oc_id) == false) {
		input.checked = false;
	} else {
		input.checked = true;
	}
	
	
	var event_td  = document.createElement("td");
	event_td.appendChild(document.createTextNode(banker.ev_name));
	
	var price_td  = document.createElement("td");
	price_td.appendChild(document.createTextNode(banker.prc_str));
	
	var home_away_td  = document.createElement("td");
	home_away_td.appendChild(document.createTextNode(banker.col_name));
	
	event_td.onclick  = new Function("update_checkbox('" +banker.ev_oc_id+ "','" +fbcpn_id+ "')");
	price_td.onclick  = new Function("update_checkbox('" +banker.ev_oc_id+ "','" +fbcpn_id+ "')");
	home_away_td.onclick  = new Function("update_checkbox('" +banker.ev_oc_id+ "','" +fbcpn_id+ "')");
	
	if(!input.checked) {
		input_td.className     = 'banker_unselected';
		event_td.className     = 'banker_unselected';
		price_td.className     = 'banker_unselected';
		home_away_td.className = 'banker_unselected';
	}
	
	row.appendChild(input_td);
	row.appendChild(event_td);
	row.appendChild(price_td);
	row.appendChild(home_away_td);
	
	if (num_selns == 1) {
		// blank cells
		var blank  = document.createElement("td");
		blank.style.width = "50%"
		row.appendChild(blank);
	}
}
*/
// store the values of the bankers bet tool checkboxes in a hash table
function update_checkbox(ev_oc_id, fbcpn_id) {
	var cpn = FBCPN[fbcpn_id];
	
	cpn.checkbox_values =  new Hash();
	
	var checkboxes =  document.getElementsByName(fbcpn_id+ "_add_to_banker_name");
	
	for (var c = 0; c < checkboxes.length; c++) {
		
		if (checkboxes[c].value == ev_oc_id) {
			checkboxes[c].checked = !checkboxes[c].checked;
		}
		
		cpn.checkbox_values.set(checkboxes[c].value, checkboxes[c].checked);
	}
	
	build_banker_tool(fbcpn_id);
}


// Compare coupon rows.
//
// Params:
//   sort_by       - Either TIME, or a col_key to sort by that column's odds.
//   sort_dir      - Main sort direction (1 = ascending, -1 = descending).
//   cpnrowA/B     - Coupon row objects (as found in FBCPNROW).
//
// Returns:
//   A negative number if A < B, zero if A == B or a positive number if A > B.
//
function fbcpn_cmp_rows(sort_by, sort_dir, cpnrowA, cpnrowB) {

	// How should we compare the rows?

	if (sort_by == 'TIME') {
		
		if (cpnrowA.srt_date + cpnrowA.srt_time < cpnrowB.srt_date + cpnrowB.srt_time) {
			return -sort_dir;
		} else if (cpnrowA.srt_date + cpnrowA.srt_time > cpnrowB.srt_date + cpnrowB.srt_time) {
			return sort_dir;
		}
		// No differences - fall through.

	} else {

		// sort_by must be the column key whose odds we sort by.

		var oddsA = cpnrowA.srt_odds[sort_by];
		var oddsB = cpnrowB.srt_odds[sort_by];

		// Empty cells should sort after everything else,
		// regardless of the sort order.

		if (oddsA == null) {
			oddsA = sort_dir < 0 ? [1,9999] : [9999,1];
		}
		if (oddsB == null) {
			oddsB = sort_dir < 0 ? [1,9999] : [9999,1];
		}

		// Compare using classic fraction inequality:

		var d = oddsA[0] * oddsB[1] - oddsA[1] * oddsB[0];
		if (d < 0) {
			return -sort_dir;
		} else if (d > 0) {
			return sort_dir;
		}

		// No differences - fall through.

	}

	// No differences found so far - compare ids. We ignore the sort
	// direction in the hope of preserving the original ordering.

	if (cpnrowA.id < cpnrowB.id) {
		return -1;
	} else if (cpnrowA.id > cpnrowB.id) {
		return 1;
	}

	// No differences found whatsoever.
	return 0;
}

// ---------- Football Tabs -------

function fb_home_init_tab() {
	
	//construct regexp to search for target name/value pair
	var regexp = new RegExp("fb_home_tab=[^;]*", "i");
	
	if (document.cookie.match(regexp)) {
		//if cookie found
		var cookie_val = document.cookie.match(regexp)[0].split("=")[1];
	} else {
		var cookie_val = "fbcpnFEAT";
	}
	
	fb_home_choose_tab(cookie_val);
}

// Called when the user selects a Football Matches tab.
// Params:
//   chosen_tabname - tab identifier (e.g. fbcpnFEAT)
// Returns:
//   Nothing, but highlights tab, shows content holder and
//   makes AJAX request to load content if not already done so.
//
function fb_home_choose_tab(chosen_tabname) {

	fb_home_current_tab = chosen_tabname;

	for (var i = 0; i < fb_home_tabnames.length; i++) {
		var tabname = fb_home_tabnames[i];
		var holder_el = document.getElementById(tabname + '_holder');
		var tab_el    = document.getElementById('li_' + tabname);
		if (tabname == chosen_tabname) {
			holder_el.style.display = 'block';
			tab_el.className = 'on';
		} else {
			holder_el.style.display = 'none';
			tab_el.className = '';
		}
	}
	
	// store a cookie, with 24hrs persistence, to retain the last football tab
	var expireDate = new Date("January 01, 2036 00:00:00");
	document.cookie = "fb_home_tab"+"="+chosen_tabname+"; path=/; expires="+expireDate.toGMTString();
	
	if(chosen_tabname == 'fb_other_mkts')
	 document.getElementById('fb_upd_prices').style.display = 'none';
	else
	 document.getElementById('fb_upd_prices').style.display = 'block';

	if (fb_home_tabs_loaded[chosen_tabname]) {
		// Content already loaded.
	} else {
		fb_home_load_tab(chosen_tabname);
	}
	
	if(typeof(netinsight) != "undefined"){
		if(netinsight){
			//Unica event tracking
			ntptAddPair("fbp",chosen_tabname);
			ntptEventTag("ev=fbtab");
		}
	}

}

// Load content (via AJAX) into a football home page tab.
// Params:
//   tabname      - tab identifier (e.g. fbcpnFEAT)
//   xtra_qry_str - optional string to add to end of URL
// Returns:
//   Nothing useful, but removes existing tab content and makes AJAX
//   request to load the tab content. Note that highlighting the tab
//   and showing the content is the caller's reponsibility.
//
function fb_home_load_tab(tabname, xtra_qry_str) {

	if (xtra_qry_str == null) {
		xtra_qry_str = '';
	}

	var holder_el = document.getElementById(tabname + '_holder');
	if (holder_el == null) {
		return;
	}

	// Remove content from the tab.
	holder_el.innerHTML = '';

	// TODO - nice loading message?
	holder_el.innerHTML =
	  '<div class="notes"><p><strong>' + FB.xl_loading +
	  '</strong></p></div>';

	// If this is a coupon tab...
	if (FBCPN[tabname] != null) {
		// Preserve the show all argument.
		if (FBCPN[tabname].showing_all) {
			xtra_qry_str += '&show_all=1';
		}
		// Cleanup the existing JS data.
		fbcpn_cleanup_data(tabname);
	}

	var url = tld;
	if (tabname == 'fbcpnFEAT') {
		url += '?action=go_fb_feat_matches_ajax';
	} else if (tabname == 'fbcpnMY') {
		url += '?action=go_fb_my_matches_ajax';
	} else if (tabname == 'fbcpnLIVE') {
		url += '?action=go_fb_live_betting_ajax';
	} else if (tabname == 'fb_other_mkts') {
		url += '?action=go_fb_other_mkts_ajax';
	} else {
		throw('unknown tab ' + tabname);
	}

	if (xtra_qry_str != '') {
		url += xtra_qry_str;
	}

	fb_simple_ajax_request(url,tabname,fb_got_ajax_content);

	// Not strictly true yet!
	fb_home_tabs_loaded[tabname] = true;

}


// Called when we get some content via AJAX for a football page section.
// Params:
//    id           - tab identifier (e.g. fbcpnFEAT)
//    ok           - true if AJAX call succeeded, false otherwise
//    reponse      - text of response (or error message if ok is false)
//    content_type - content type of response (or null if ok is false)
// Returns:
//   Nothing, but the tab's holder element is updated with the content.
//
function fb_got_ajax_content(id, ok, response, content_type) {

	var holder_el = document.getElementById(id + '_holder');
	if (holder_el == null) {
		return;
	}

	var is_fb_tab = false;
	for (var i = 0; i < fb_home_tabnames.length; i++) {
		if (fb_home_tabnames[i] == id) {
			is_fb_tab = true;
			break;
		}
	}

	if (is_fb_tab) {
		fb_home_tabs_loaded[id] = ok;
	}

	if (!ok) {
		holder_el.innerHTML =
		  '<div class="notes"><p><strong>' +
		  FB.xl_error + ' (' + response + ')' +
		  '</strong></p></div>';
	} else {

		if (content_type.indexOf('javascript') != -1) {

			// Pure javascript - blank element and run the JS.
			holder_el.innerHTML = '';
			eval(response);

		} else {

			// Assume response is a mixture of HTML and JS.
			// We'll do a basic parse into HTML and JS, stuff the HTML in
			// the element, then run the JS.
			// There are some problems with this ...
			//   * the JS will run after all the HTML
			//   * document.writes won't work
			//   * our parsing can no doubt be tripped up by comments
			//     and things
			// ... but it gets the job done well enough for now.

			var parts = fb_parse_script_tags(response);
			holder_el.innerHTML = parts[0];
			if (parts[1].length) {
				eval(parts[1]);
			}

			// Ensure highlighting works for content loaded via AJAX.
			fbm_add_mouseovers(holder_el);

		}
	
	}

}


// Look for script tags in HTML text.
// Params:
//   str - HTML as a string
// Returns:
//   Array of the form [ html, js ] where html contains everything outside
//   script tags, and js contains everything from inside script tags.
// Notes:
//   1) We have to be a bit careful not to end our own script by saying
//      "< / s c r ... i p t >" out loud here!
//   2) The parser is easily tripped up by comments and things
//   3) script tags with src attributes are ignored
//   4) We fail to preserve the interleaving of html and js so the caller
//      can't execute the js as the same time a browser would do.
//
function fb_parse_script_tags(str) {

	var html = '';
	var js   = '';

	var i = 0;
	var state = 'HTML';
	var script_re =
	  new RegExp('<(/?)' + 'scr'+'ipt' + '([^>]*)>', 'gi');

	while ((mtch = script_re.exec(str)) != null) {

		mS = mtch.index;
		if (state == 'HTML') {
			html += str.substring(i, mS);
		} else {
			js += str.substring(i, mS) + ';\n';
		}

		var closer = mtch[1];
		var attrs  = mtch[2];

		if (closer == '/') {
			state = 'HTML';
		} else {
			if ( attrs.charAt(attrs.length - 1) != '/' &&
			     attrs.indexOf('src=') == -1 ) {
				state = 'JS';
			}
		}

		i = script_re.lastIndex;

	}

	if (state == 'HTML') {
		html += str.substring(i);
	} else {
		js += str.substring(i);
	}

	return [ html, js ];
}


// Submit an AJAX GET request.
// Params:
//   url      - URL to retrieve
//   id       - identifier passed through to callback
//   callback - function object to call on success / failure
// Returns:
//   Nothing - but the callback function will be called on success with:
//     id, true, response_text, content_type
//   or on failure with:
//     id, false, error_code
//
function fb_simple_ajax_request(url, id, callback) {

	var req = null;

	if (window.XMLHttpRequest) {
		req = new XMLHttpRequest();
	} else if (window.ActiveXObject) {
		req = new ActiveXObject('Microsoft.XMLHTTP');
	}

	if (req) {

		req.onreadystatechange = function() {

			if (req.readyState != 4) return;

			var reqStatus;
			try {
				reqStatus = req.status;
			} catch (e) {
				reqStatus = '';
			}

			if (reqStatus != 200) {
				callback(id,false,'HTTP');
			} else {
				var content_type = req.getResponseHeader("Content-Type");
				callback(id,true,req.responseText,content_type);
			}

		}

		try {
			req.open('GET', url, true);
			req.send(null);
		} catch (e) {
			callback(id,false,'UNSUPPORTED');
		}

	} else {
		callback(id,false,'UNSUPPORTED');
	}

}
