//##################################################################
// This code is necessary for browsers that don't reflect the DOM
// constants (like IE).
if (document.ELEMENT_NODE == null) 
{
	document.ELEMENT_NODE 	= 1;
	document.TEXT_NODE 		= 3;
}
//##################################################################

//##################################################################
// Global vars 

//to hold class names
document.css_row_a 		= 'row_a'; 
document.css_row_b 		= 'row_b';
document.css_row_a_sel	= 'row_a_sel'; 
document.css_row_b_sel	= 'row_b_sel';
document.css_head		= 'col_head';
document.css_head_sel	= 'col_head_sel';

//sort dir images
document.up_arrow 		= '/outreach/images/uparrow_white.gif'; 
document.down_arrow 	= '/outreach/images/downarrow_white.gif';
//##################################################################

//------------------------------------------------------------------
//------------------------------------------------------------------
//------------------------------------------------------------------


/* ########################### 
GET ELEMENT TEXT
 - Arguments:
 		e : element to retrieve content from
 - Return:
 		normalized, concatenated text content
#############################*/
function get_element_text(e) 
{
	var i;
	var s = '';
	
	//for each child
	for (i=0; i < e.childNodes.length; i++)
	{
		if (e.childNodes[i].nodeType == document.TEXT_NODE)
	   		s += e.childNodes[i].nodeValue;
	  	else if (e.childNodes[i].nodeType == document.ELEMENT_NODE && e.childNodes[i].tagName == "BR")
	    	s += " ";
	    // use recursion to get text within sub-elements.
	  	else
	    	s += get_element_text(e.childNodes[i]);
	}
	
	return normalize_string(s);
}


/* ########################### 
NORMALIZE STRING
 - Arguments:
 		s : string to be normalized
 - Return:
 		normalized, concatenated text content
#############################*/
function normalize_string(s) 
{
	// Regular expressions for normalizing white space.
	var whtSpEnds = new RegExp("^\\s*|\\s*$", "g");
	var whtSpMult = new RegExp("\\s\\s+", "g");
	
  	s = s.replace(whtSpMult, " ");  // Collapse any multiple white space.
  	s = s.replace(whtSpEnds, "");   // Remove leading or trailing white space.

  	return s;
}

/* ########################### 
GUESS TYPE
 - Purpose: guess the type of a column based on its first non-blank row
 - Arguments:
 		text : id of table body to sort
 - Return:
 		s_type
#############################*/
function guess_col_type(tbl_id,col) 
{
	var i;
    var s_type;
    var e;
    var n;
    var allowed_types = 'sort_alpha,sort_numeric,sort_ddmm,sort_mmdd';
    
    s_type = 'sort_alpha';					//default value
	e = document.getElementById(tbl_id); 	//get the table section to sort.
    
    //For each row of column (until first non blank row)
	for(i=0; i < e.rows.length; i++) 
    {
	    n = e.rows[i].cells[col];
	    
	    //If column has specified sort_type
	    if(n.getAttribute('sort_type') != null)
	    {
			if(allowed_types.indexOf(n.getAttribute('sort_type')) != -1)
			{
		    	s_type = n.getAttribute('sort_type');
		    	break;
	    	}
	    }
	    
	    
	    col_sck = n.getAttribute('sort_custom_key');
	    if(col_sck != null)
			text = col_sck;
	    else
	    	text = get_element_text(n);
		
      	if(text != '')
      	{
			//Numeral
		    if(text.match(/^-?[£$¤]?[\d,.]+%?$/))
			    s_type = 'sort_numeric';
			// check for a date: dd/mm/yyyy or dd/mm/yy 
			// can have / or . or - as separator
			// can be mm/dd as well
		    else
		    {		
			    poss_date = text.match(/^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/)
			    if(poss_date) 
			    {
			    	// looks like a date
			      	first = parseInt(poss_date[1]);
			      	second = parseInt(poss_date[2]);
			      	// definitely dd/mm
			      	if (first > 12) 
			       		s_type =  'sort_ddmm';
			   		else if (second > 12) 
			        	s_type =  'sort_mmdd';
			   		else 
			      	{
			        	// looks like a date, but we can't tell which, so assume
			        	// that it's dd/mm (English imperialism!) and keep looking
			        	s_type =  'sort_ddmm';
			      	}
			    }
			}
			break;	   
		}
	}
	
	return s_type;
}

function open_prog_dsp()
{
	var stat_div,stat_swf,swf_p1,swf_p2,swf_em;		//Sorting Status Div and Image
	
	if(! document.getElementById('sort_status_div'))
	{
		var stat_div, stat_img;
	
		stat_div = document.createElement('div');
		document.body.appendChild(stat_div);
			
		stat_div.setAttribute('id','sort_status_div');
		stat_div.setAttribute('style','');
		stat_div.style.border = '1 solid black';
		stat_div.style.position = 'absolute';
		stat_div.style.left = '5';
		stat_div.style.top = '95';
		stat_div.style.visibility = 'visible';
		stat_div.style.width = '219';
		stat_div.style.height = '42';
		stat_div.style.zIndex = '55';
			
		stat_swf  = '<object ';
		stat_swf += 'classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" ';
		stat_swf += 'codebase="https://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab##version=6,0,29,0" ';
		stat_swf += 'width="219" height="42">';
		
		stat_swf += '<param name="movie" value="https://ifdev08.owg.fs.lmco.com/cfs/outreach/images/status_sort.swf">';
		stat_swf += '<param name="quality" value="high">';
		stat_swf += '<embed src="https://ifdev08.owg.fs.lmco.com/cfs/outreach/images/status_sort.swf" ';
		stat_swf += 'quality="high" ';
		stat_swf += 'pluginspage="https://www.macromedia.com/go/getflashplayer" ';
		stat_swf += 'type="application/x-shockwave-flash" ';
		stat_swf += 'width="219" height="42"></embed>';
		
		stat_div.innerHTML = stat_swf;
	}
	else
	{
		stat_div = document.getElementById('sort_status_div');
		stat_div.style.visibility='visible';
	}
	
	return true;
}

/* ########################### 
SORT TABLE
 - Arguments:
 		tbl_id : id of table body to sort
 		col : coloumn index to sort
 - Return:
 		-1: v1 <  v2
 		 0: v1 == v2
 		 1: v1 >  v2
#############################*/
function xxx_sort_table(tbl_id,col) 
{
	var tmp;	
	
	//Open Progress Window
	/*
		- Create Dynamic Div, if it doesn't exist already
			- Set position to middle of screen/browser
			- Insert gif into div
		- If exists, make div visible
	*/
	open_prog_dsp();
	
	setTimeout("alt_sort_table('" + tbl_id + "'," + col + ")",1000);
	
	stat_div = document.getElementById('sort_status_div');
	stat_div.style.visibility = 'hidden';
	return false;
}

function sort_table(tbl_id,col) 
{
	var e				//Table Body Element
	var tmp_e;			//Temp Element
	var i, j;			//Loop Indexes
	var tmp_val;		//Minimum/Maximum Value
	var tmp_idx;		//Minimum/Maximum Value Row Index
	var test_val;		//Test Value
	var cmp;			//Compare Indicator (function return result)
	var tmp_n;			//Node, to check for custom sort key
	var test_n;			//Test Node, to check for custom sort key
			
	//Get the table body section to sort.
	e = document.getElementById(tbl_id);
	
	//Set last column, used for the sort order
	//Set -1 for deafult (no last column)
	if(e.last_col == null)
		e.last_col = -1;
	//Array for holding sort direction info
	if(e.sort_dirs == null)
		e.sort_dirs = new Array();

	//Remember Each Column Direction (ascending[0]/descending[1])		
	if(e.sort_dirs[col] == null || col != e.last_col) 
		e.sort_dirs[col] = 0;
	else
	{
		if(e.sort_dirs[col] == 0)
			e.sort_dirs[col] = 1;
		else
			e.sort_dirs[col] = 0;
	}
	
	//Set Last Column
	e.last_col = col;
	
	//Get Column Type
	col_type = guess_col_type(tbl_id,col);
	
	// Sort the rows based on the content of the specified column
	// using a selection sort.
	for(i=0; i < e.rows.length - 1; i++) 
	{
		// Assume the current row has the minimum/maximum value.
		//minimum/maximum value row index
	  	tmp_idx = i;		
	  	
	  	//Get Row Node, Check sort_custom_key value : alternate sorting weight
		tmp_n = e.rows[i].cells[col];
		
		//minimum/maximum value
		tmp_sck = tmp_n.getAttribute('sort_custom_key')
	  	if(tmp_sck != null)
	  		tmp_val = tmp_sck;
	  	else
			tmp_val = get_element_text(tmp_n);	
		
	  	// Search the rows that follow the current one for a smaller value.
	  	for(j = i + 1; j < e.rows.length; j++) 
	  	{
		  	test_n = e.rows[j].cells[col];
		  	test_sck = test_n.getAttribute('sort_custom_key');
		  	if(test_sck != null)
		  		test_val = test_sck;
		  	else
	    		test_val = get_element_text(test_n);
	    	
	    	//alert(tmp_val + ' , ' + test_val);	
	    	cmp = compare_values(col_type, tmp_val, test_val);
	    	
	    	// If this row has a smaller/larger value than the current minimum/maximum,
	    	// remember its position and update the current minimum/maximum value.
	    	if ((e.sort_dirs[col] == 0 && cmp > 0) || (e.sort_dirs[col] == 1 && cmp < 0)) 
	    	{
	      		tmp_idx = j;
	      		tmp_val = test_val;
	    	}
	 	}
	  
	  	// By now, we have the row with the smallest/largest value. Remove it from
	  	// the table and insert it before the current row.
	  	if (tmp_idx > i) 
	  	{
	    	tmp_e = e.removeChild(e.rows[tmp_idx]);
	    	e.insertBefore(tmp_e, e.rows[i]);
	  	}
	}
	
	// Restore the table's display style.
	//e.style.display = old_dsp;
	
	//Selected Column CSS
	change_cell_styles(e,col);
	add_arrow_img(e,col);
	
	//returns false so not to trigger link properties
	return false;
}

function add_arrow_img(e,col)
{
	var i,j;
	var c; 			//Cell element to add arrow img to
	var main_tbl;	//Parent table of the tbody
	var img;		//Image to add
	
	main_tbl = e.parentNode;	//Get parent table
	
	if(e.sort_dirs[col] == 1)
		img_path = document.down_arrow;
	else
		img_path = document.up_arrow;
		
	img = document.createElement('img');	//Build new image
	img.src  = img_path;
	img.name = 'sort_img'
	img.style.marginLeft = 5;
	
	for(i=0; i<main_tbl.tHead.rows[0].cells.length; i++)
	{
		c = main_tbl.tHead.rows[0].cells[i];
		
		//remove old images
		for(j=0; j< c.childNodes.length; j++)
		{
			if(c.childNodes[j].name == 'sort_img')
				c.removeChild(c.childNodes[j]);
		}
		
		//append image
		if(i == col)
			c.appendChild(img);
		
	}
}

function change_cell_styles(e,col)
{
	var i,j;
	var c; 			//Cell element to change
	var main_tbl;	//Parent table of the tbody
	
	// Regular expressions for setting class names.
	var re_ra 		= new RegExp(document.css_row_a, "gi");
	var re_ras 		= new RegExp(document.css_row_a_sel, "gi");
	var re_rb   	= new RegExp(document.css_row_b, "gi");
	var re_rbs		= new RegExp(document.css_row_b_sel, "gi");
	var re_head  	= new RegExp(document.css_head, "gi");
	var re_heads 	= new RegExp(document.css_head_sel, "gi");
	
	main_tbl = e.parentNode;	//Get parent table
	
	//Header Style
	for(i=0; i<main_tbl.tHead.rows[0].cells.length; i++)
	{
		c = main_tbl.tHead.rows[0].cells[i];
		if(i == col)
		{
			c.className = c.className.replace(re_head, "");
			c.className += ' ' + document.css_head_sel;
		}
		else
		{
			c.className = c.className.replace(re_heads, "");
			c.className += ' ' + document.css_head;
		}
	}
	
	//Reset row styles after sorting
	for(i=0; i<e.rows.length; i++)
	{
		//Remove script applied styles;
		//Rows
		e.rows[i].className = e.rows[i].className.replace(re_ra, "");
		e.rows[i].className = e.rows[i].className.replace(re_rb, "");
		//Columns
		for(j=0; j<e.rows[i].cells.length; j++)
		{
			e.rows[i].cells[j].className = e.rows[i].cells[j].className.replace(re_ras, "");
			e.rows[i].cells[j].className = e.rows[i].cells[j].className.replace(re_rbs, "");
		}
		
		//Aplly new styles
		if(i % 2 == 0)
		{
			e.rows[i].className += ' ' + document.css_row_a;
			e.rows[i].cells[col].className += ' ' + document.css_row_a_sel;
		}
		else
		{
			e.rows[i].className += ' ' + document.css_row_b;
			e.rows[i].cells[col].className += ' ' + document.css_row_b_sel;
		}
	}	
}
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

/* ########################### 
COMPARE VALUES
 - Arguments:
 		v1,v2 : values to be compared 
 - Return:
 		-1: v1 <  v2
 		 0: v1 == v2
 		 1: v1 >  v2
#############################*/
function compare_values(sort_type,v1, v2) 
{
	var cmp; 
	
	switch(sort_type)
	{
		case 'sort_alpha':
			return compare_alpha(v1,v2);
			break;
		case 'sort_numeric':
			return compare_numeric(v1,v2);
			break;
		case 'sort_ddmm':
			return compare_ddmm(v1,v2);
			break;
		case 'sort_mmdd':
			return compare_mmdd(v1,v2);
			break;
		default:
			return compare_alpha(v1,v2);
			break;
	}
}

function compare_alpha(v1,v2)
{
  	// Compare the two values.
  	if (v1 == v2)
    	return 0;
  	else if (v1 > v2)
    	return 1
  	else
  		return -1;
}

function compare_numeric(v1,v2)
{
	var f1;
	var f2;
	
  	// If the values are numeric, convert them to floats.
  	f1 = parseFloat(v1.replace(/[^0-9.-]/g,''));
  	f2 = parseFloat(v2.replace(/[^0-9.-]/g,''));
  
  	if (!isNaN(f1) && !isNaN(f2)) 
  	{
    	v1 = f1;
    	v2 = f2;
  	}

  	// Compare the two values.
  	if (v1 == v2)
    	return 0;
  	else if (v1 > v2)
    	return 1
  	else
  		return -1;
}

function compare_ddmm(v1,v2)
{
    //Rebuild Date 1
    date_1 = rebuild_date('ddmm',v1);
    //Rebuild Date 2   
    date_2 = rebuild_date('ddmm',v2);
    
    if(date_1 == date_2)
    	return 0;
    else if (date_1 < date_2) 
    	return -1;
    else
    	return 1;
}

function compare_mmdd(v1,v2)
{
    //Rebuild Date 1
    date_1 = rebuild_date('mmdd',v1);
    //Rebuild Date 2   
    date_2 = rebuild_date('mmdd',v2);
   
    if(date_1 == date_2)
    	return 0;
    else if (date_1 < date_2) 
    	return -1;
    else
    	return 1;
}

function rebuild_date(format,date)
{
	var date_parts,tmp_m,tmp_d,tmp_y,tmp_dt;
	var y = '0';
	var m = '0';
	var d = '0';
	var date_reg_exp = '';
	
	//Get Date Parts
	date_parts = date.match(/^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/);
	
	if(date != '')
	{
		y = date_parts[3]; 
	    
	    if(format == 'mmdd')
	    {
	    	m = date_parts[1];
	    	d = date_parts[2];
		}
		else if(format == 'ddmm')
		{
			m = date_parts[2];
	    	d = date_parts[1];
		}
		
		tmp_y = y.toString();
		tmp_m = m.toString();
		tmp_d = d.toString();
		
	    //Add Leading Zero
	    if (tmp_m.length == 1) tmp_m = '0' + tmp_m;
	    if (tmp_d.length == 1) tmp_d = '0' + tmp_d;
	    
	    tmp_dt = tmp_y + tmp_m + tmp_d;
	}
	else
		tmp_dt = '19000101';

    //Rebuild Date 1
   return tmp_dt;/* */
}
