// JavaScript Document



function blockMe(){
	$.blockUI({ message: '<div style="background-image:url(\'wait_data.png\'); width:212px; height:46px;">&nbsp;&nbsp;&nbsp;&nbsp;<img style="padding-top:16px;" src="busy.gif" /></div>' });	
}
function unBlockMe(){
	$.unblockUI();
}



// WE START WHEN THE PAGE IS LOADED

var boxItTpl="";







function login(){
	location.href="/admin";
}



$(document).ready(function() {





	//Login button

	$('#login').click(function() {

	login();

	});



	



	//Register button

	$('#register').click(function() {

	 	 $("#page-bgbtm").slideToggle("slow", function(){

				$.get("tpl/register.tpl",function(html){

					$("#page-bgbtm").html("<div id='slide'></div><div id='regForm'>"+$.boxit("REGISTER FORM",html)+"</div>");

					$("#page-bgbtm").slideToggle("slow");

				});

		});

	});





//######################### TEMPLATE CACHE ###########################################

	//Load boxit template



	if($.cookie("boxIt")=="" || $.cookie("boxIt")==null ){

		$.get("tpl/boxit.php",function(html){

			$.cookie("boxIt", html);

		});

	}

	

	if($.cookie("SearchTable")=="" || $.cookie("SearchTable")==null ){

		$.get("tpl/SearchTable.tpl",function(html){

			$.cookie("SearchTable", html);

		});

	}

	

	if($.cookie("Login")=="" || $.cookie("Login")==null ){

		$.get("tpl/login.tpl",function(html){

			$.cookie("Login", html);

		});

	}

	

	

	

	

	

//######################## END TEMPLATE CACHE ########################################





});

jQuery.fn.reset = function () {

  $(this).each (function() { this.reset(); });

}


function _hideMe(id){

if($("#docking").size()) {







	$("#content"+id).toggle(150, function(){

		$("#mainBoxIt"+id).toggle(500, function(){

			$("#docking").html($("#docking").html()+"<td  style='cursor:pointer; font-size:16px; color:#FFF; padding:2px;' id='dock"+id+"' valing='middle' align='center' width='164' height='50' background='/images/dockImg.png' onclick='_showMe(\""+id+"\")'>"+ $("#title"+id).html()+"</td>");

		})

	});

}

}

function _showMe(id){

	$("#dock"+id).hide(250,function(){

		$("#dock"+id).remove();

		$("#content"+id).toggle(150, function(){

			$("#mainBoxIt"+id).toggle(500);

		});

	});

}



// FUNCTION TO ENBOX A HTML CODE

jQuery.boxit=function(title,html){

	var boxItTpl=$.cookie("boxIt");

	boxItTpl = boxItTpl.replace("{title}",title);

	boxItTpl = boxItTpl.replace("{html}",html);

	var id=title;

	id=id.replace(/ /g,"_");

	boxItTpl = boxItTpl.replace(/{id}/g,id);

	return boxItTpl;	

}



/*

jQuery.boxme=function(title,element){

	$("#"+element).html($.boxit(title,$("#"+element).html()));	

}

*/

//////////////////////////////////////////////



////// FUNCTION FOR SEARCHS TABLES




function popOrder(URL) {
day = new Date();
id = day.getTime();
eval("page" + id + " = window.open(URL, '" + id + "', 'toolbar=0,scrollbars=1,location=0,statusbar=0,menubar=0,resizable=0,width=1000,height=600,left = 0,top = 0');");
}



function setRows(value,wich){

	document.getElementById(wich).className = 'tablesorter paginate-'+value+' max-pages-5';

    $("#"+wich+"_Content").slideToggle("fast", function(){

 	tablePaginater.init(wich);			

	$("#"+wich+"_Content").slideToggle("fast");

	});

	





	}




function setPage(page){
				var where=$("#wherePage").val();
				var id=$("#frmId").val();
				var str= $("form#Frm"+id).serialize()+"&idstatus="+$("#s").val()+"&page="+page;
				$("#"+id+"_Content").html('<tr><td colspan = "12" align = "center"><img src="/images/loading_content.gif" border="0" /></td></tr>');
				$.post(where,str,function(html){
					
				$("#"+id+"_Content").html(html);
				});
		  }



jQuery.searchForm=function(id,width,search,title,controls,Col,w,nrows,params){

	
	

	if (nrows==2){

		nrows='<div align="rigth" style="padding-bottom:2px;">Show <select name="select" id="select" onchange="setRows(this.value,\''+id+'\')">  <option value="10">10</option>  <option value="20">20</option>  <option value="30">30</option>  <option value="999999999">All</option></select> Results by page.</div>'+"<table id="+id+" border='0' class='tablesorter paginate-10 max-pages-5 ' ><thead><tr>";

	}else{

		

		nrows="<table id="+id+" border='0' class='tablesorter paginate-999999 max-pages-5 ' ><thead><tr>";

		}

	

	var mainTpl=$.cookie("SearchTable");

	var controls=""+controls;

	var tbl="";

	var cols=Col.val; 

	tbl = tbl + nrows;

	for(x=0;x<=cols.length-1;x++){

		if (!w){

		tbl=tbl+"<th aling='center' >" + Col.val[x] + "</th>";

		var width='100%';

		}else{

			try{ if (w.val[x]==""){

				width="";

				}else{

					width= "width='"+w.val[x]+"'";

					}

			}catch(e){}

			tbl=tbl+"<th aling='center' " + width + " >" + Col.val[x] + "</th>";

			}

	}

	tbl=tbl+"</tr></thead><tbody id="+id+"_Content></tbody></table>";

	mainTpl = mainTpl.replace("{title}",title);

	

	

	frm="<input type='hidden' value='"+id+"' id='frmId' /><input type='hidden' value='"+uri.get(search)+"' id='wherePage' /><input type='hidden' value='1' id='actualPage' />  <form id='Frm"+id+"'>"+controls+"</form>";

	mainTpl = mainTpl.replace("{controls}",frm);

	mainTpl = mainTpl.replace("{width}",width);

	mainTpl = mainTpl.replace("{table}",tbl);

	mainTpl = mainTpl.replace("{id_btn}","btn_"+id);

	$("#Frame"+id).html(mainTpl);

    $("#"+id+"_Content").html('<tr><td colspan = "'+(cols.length)+'" align = "center"><img src="/images/loading_content.gif" border="0" /></td></tr>');

	 

	 $.post(uri.get(search),params,function(data){

	   	    tablePaginater.init(id);

    		$("#"+id+"_Content").html(data)

    		tablePaginater.init(id); 

			$("#"+id).tablesorter({widthFixed: true});

			$("table.tablesorter tr:even").css("background-color", "#FFF");

	  		$("table.tablesorter tr:odd").css("background-color", "#EEE");

	 		});

	 

	 $("#btn_"+id).click(function() {
     	$("#"+id+"_Content").slideToggle("fast");
   	    $("#"+id+"_Content").html('<tr><td colspan = "'+cols.length+'" align = "center"><img src="/images/loading_content.gif" border="0" /><td></tr>');
         str = $("form#Frm"+id).serialize();
			$.post(uri.get(search),str,function(html){
			 $("#"+id+"_Content").html(html);
			  tablePaginater.init(id);
					$("table.tablesorter tr:even").css("background-color", "#FFF");
	  				$("table.tablesorter tr:odd").css("background-color", "#EEE");
    			    $("#"+id).trigger("update"); 
                    $("#"+id+"_Content").slideToggle("fast");
					});
				});

				 	 

return true;

}

//////////////////////////////////////////////////////////////////////////////////////





///////////////SHAKE FUNCTION

jQuery.fn.shake = function(intShakes /*Amount of shakes*/, intDistance /*Shake distance*/, intDuration/*Time duration*/) {

this.each(function() {

var jqNode = $(this);

jqNode.css({position: 'relative'});

for (var x=1; x<=intShakes; x++) {

jqNode.animate({ left: (intDistance * -1) },(((intDuration / intShakes) / 4)))

.animate({ left: intDistance },((intDuration/intShakes)/2))

.animate({ left: 0 },(((intDuration/intShakes)/4)));

}

});

return this;

}

/////////////////////////////////////////////////////////////////////////////////////////



///////////////////////////////Cookies function

jQuery.cookie = function(name, value, options) {

    if (typeof value != 'undefined') { // name and value given, set cookie

        options = options || {};

        if (value === null) {

            value = '';

            options.expires = -1;

        }

        var expires = '';

        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {

            var date;

            if (typeof options.expires == 'number') {

                date = new Date();

                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));

            } else {

                date = options.expires;

            }

            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE

        }

        // CAUTION: Needed to parenthesize options.path and options.domain

        // in the following expressions, otherwise they evaluate to undefined

        // in the packed version for some reason...

        var path = options.path ? '; path=' + (options.path) : '';

        var domain = options.domain ? '; domain=' + (options.domain) : '';

        var secure = options.secure ? '; secure' : '';

        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');

    } else { // only name given, get cookie

        var cookieValue = null;

        if (document.cookie && document.cookie != '') {

            var cookies = document.cookie.split(';');

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

                var cookie = jQuery.trim(cookies[i]);

                // Does this cookie string begin with the name we want?

                if (cookie.substring(0, name.length + 1) == (name + '=')) {

                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));

                    break;

                }

            }

        }

        return cookieValue;

    }

};

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



///////////////////////////TABLE SORTING

(function($){$.extend({tablesorter:new

function(){var parsers=[],widgets=[];this.defaults={cssHeader:"header",cssAsc:"headerSortUp",cssDesc:"headerSortDown",cssChildRow:"expand-child",sortInitialOrder:"asc",sortMultiSortKey:"shiftKey",sortForce:null,sortAppend:null,sortLocaleCompare:true,textExtraction:"simple",parsers:{},widgets:[],widgetZebra:{css:["even","odd"]},headers:{},widthFixed:false,cancelSelection:true,sortList:[],headerList:[],dateFormat:"us",decimal:'/\.|\,/g',onRenderHeader:null,selectorHeaders:'thead th',debug:false};function benchmark(s,d){log(s+","+(new Date().getTime()-d.getTime())+"ms");}this.benchmark=benchmark;function log(s){if(typeof console!="undefined"&&typeof console.debug!="undefined"){console.log(s);}else{alert(s);}}function buildParserCache(table,$headers){if(table.config.debug){var parsersDebug="";}if(table.tBodies.length==0)return;var rows=table.tBodies[0].rows;if(rows[0]){var list=[],cells=rows[0].cells,l=cells.length;for(var i=0;i<l;i++){var p=false;if($.metadata&&($($headers[i]).metadata()&&$($headers[i]).metadata().sorter)){p=getParserById($($headers[i]).metadata().sorter);}else if((table.config.headers[i]&&table.config.headers[i].sorter)){p=getParserById(table.config.headers[i].sorter);}if(!p){p=detectParserForColumn(table,rows,-1,i);}if(table.config.debug){parsersDebug+="column:"+i+" parser:"+p.id+"\n";}list.push(p);}}if(table.config.debug){log(parsersDebug);}return list;};function detectParserForColumn(table,rows,rowIndex,cellIndex){var l=parsers.length,node=false,nodeValue=false,keepLooking=true;while(nodeValue==''&&keepLooking){rowIndex++;if(rows[rowIndex]){node=getNodeFromRowAndCellIndex(rows,rowIndex,cellIndex);nodeValue=trimAndGetNodeText(table.config,node);if(table.config.debug){log('Checking if value was empty on row:'+rowIndex);}}else{keepLooking=false;}}for(var i=1;i<l;i++){if(parsers[i].is(nodeValue,table,node)){return parsers[i];}}return parsers[0];}function getNodeFromRowAndCellIndex(rows,rowIndex,cellIndex){return rows[rowIndex].cells[cellIndex];}function trimAndGetNodeText(config,node){return $.trim(getElementText(config,node));}function getParserById(name){var l=parsers.length;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==name.toLowerCase()){return parsers[i];}}return false;}function buildCache(table){if(table.config.debug){var cacheTime=new Date();}var totalRows=(table.tBodies[0]&&table.tBodies[0].rows.length)||0,totalCells=(table.tBodies[0].rows[0]&&table.tBodies[0].rows[0].cells.length)||0,parsers=table.config.parsers,cache={row:[],normalized:[]};for(var i=0;i<totalRows;++i){var c=$(table.tBodies[0].rows[i]),cols=[];if(c.hasClass(table.config.cssChildRow)){cache.row[cache.row.length-1]=cache.row[cache.row.length-1].add(c);continue;}cache.row.push(c);for(var j=0;j<totalCells;++j){cols.push(parsers[j].format(getElementText(table.config,c[0].cells[j]),table,c[0].cells[j]));}cols.push(cache.normalized.length);cache.normalized.push(cols);cols=null;};if(table.config.debug){benchmark("Building cache for "+totalRows+" rows:",cacheTime);}return cache;};function getElementText(config,node){var text="";if(!node)return"";if(!config.supportsTextContent)config.supportsTextContent=node.textContent||false;if(config.textExtraction=="simple"){if(config.supportsTextContent){text=node.textContent;}else{if(node.childNodes[0]&&node.childNodes[0].hasChildNodes()){text=node.childNodes[0].innerHTML;}else{text=node.innerHTML;}}}else{if(typeof(config.textExtraction)=="function"){text=config.textExtraction(node);}else{text=$(node).text();}}return text;}function appendToTable(table,cache){if(table.config.debug){var appendTime=new Date()}var c=cache,r=c.row,n=c.normalized,totalRows=n.length,checkCell=(n[0].length-1),tableBody=$(table.tBodies[0]),rows=[];for(var i=0;i<totalRows;i++){var pos=n[i][checkCell];rows.push(r[pos]);if(!table.config.appender){var l=r[pos].length;for(var j=0;j<l;j++){tableBody[0].appendChild(r[pos][j]);}}}if(table.config.appender){table.config.appender(table,rows);}rows=null;if(table.config.debug){benchmark("Rebuilt table:",appendTime);}applyWidget(table);setTimeout(function(){$(table).trigger("sortEnd");},0);};function buildHeaders(table){if(table.config.debug){var time=new Date();}var meta=($.metadata)?true:false;var header_index=computeTableHeaderCellIndexes(table);$tableHeaders=$(table.config.selectorHeaders,table).each(function(index){this.column=header_index[this.parentNode.rowIndex+"-"+this.cellIndex];this.order=formatSortingOrder(table.config.sortInitialOrder);this.count=this.order;if(checkHeaderMetadata(this)||checkHeaderOptions(table,index))this.sortDisabled=true;if(checkHeaderOptionsSortingLocked(table,index))this.order=this.lockedOrder=checkHeaderOptionsSortingLocked(table,index);if(!this.sortDisabled){var $th=$(this).addClass(table.config.cssHeader);if(table.config.onRenderHeader)table.config.onRenderHeader.apply($th);}table.config.headerList[index]=this;});if(table.config.debug){benchmark("Built headers:",time);log($tableHeaders);}return $tableHeaders;};function computeTableHeaderCellIndexes(t){var matrix=[];var lookup={};var thead=t.getElementsByTagName('THEAD')[0];var trs=thead.getElementsByTagName('TR');for(var i=0;i<trs.length;i++){var cells=trs[i].cells;for(var j=0;j<cells.length;j++){var c=cells[j];var rowIndex=c.parentNode.rowIndex;var cellId=rowIndex+"-"+c.cellIndex;var rowSpan=c.rowSpan||1;var colSpan=c.colSpan||1

var firstAvailCol;if(typeof(matrix[rowIndex])=="undefined"){matrix[rowIndex]=[];}for(var k=0;k<matrix[rowIndex].length+1;k++){if(typeof(matrix[rowIndex][k])=="undefined"){firstAvailCol=k;break;}}lookup[cellId]=firstAvailCol;for(var k=rowIndex;k<rowIndex+rowSpan;k++){if(typeof(matrix[k])=="undefined"){matrix[k]=[];}var matrixrow=matrix[k];for(var l=firstAvailCol;l<firstAvailCol+colSpan;l++){matrixrow[l]="x";}}}}return lookup;}function checkCellColSpan(table,rows,row){var arr=[],r=table.tHead.rows,c=r[row].cells;for(var i=0;i<c.length;i++){var cell=c[i];if(cell.colSpan>1){arr=arr.concat(checkCellColSpan(table,headerArr,row++));}else{if(table.tHead.length==1||(cell.rowSpan>1||!r[row+1])){arr.push(cell);}}}return arr;};function checkHeaderMetadata(cell){if(($.metadata)&&($(cell).metadata().sorter===false)){return true;};return false;}function checkHeaderOptions(table,i){if((table.config.headers[i])&&(table.config.headers[i].sorter===false)){return true;};return false;}function checkHeaderOptionsSortingLocked(table,i){if((table.config.headers[i])&&(table.config.headers[i].lockedOrder))return table.config.headers[i].lockedOrder;return false;}function applyWidget(table){var c=table.config.widgets;var l=c.length;for(var i=0;i<l;i++){getWidgetById(c[i]).format(table);}}function getWidgetById(name){var l=widgets.length;for(var i=0;i<l;i++){if(widgets[i].id.toLowerCase()==name.toLowerCase()){return widgets[i];}}};function formatSortingOrder(v){if(typeof(v)!="Number"){return(v.toLowerCase()=="desc")?1:0;}else{return(v==1)?1:0;}}function isValueInArray(v,a){var l=a.length;for(var i=0;i<l;i++){if(a[i][0]==v){return true;}}return false;}function setHeadersCss(table,$headers,list,css){$headers.removeClass(css[0]).removeClass(css[1]);var h=[];$headers.each(function(offset){if(!this.sortDisabled){h[this.column]=$(this);}});var l=list.length;for(var i=0;i<l;i++){h[list[i][0]].addClass(css[list[i][1]]);}}function fixColumnWidth(table,$headers){var c=table.config;if(c.widthFixed){var colgroup=$('<colgroup>');$("tr:first td",table.tBodies[0]).each(function(){colgroup.append($('<col>').css('width',$(this).width()));});$(table).prepend(colgroup);};}function updateHeaderSortCount(table,sortList){var c=table.config,l=sortList.length;for(var i=0;i<l;i++){var s=sortList[i],o=c.headerList[s[0]];o.count=s[1];o.count++;}}function multisort(table,sortList,cache){if(table.config.debug){var sortTime=new Date();}var dynamicExp="var sortWrapper = function(a,b) {",l=sortList.length;for(var i=0;i<l;i++){var c=sortList[i][0];var order=sortList[i][1];var s=(table.config.parsers[c].type=="text")?((order==0)?makeSortFunction("text","asc",c):makeSortFunction("text","desc",c)):((order==0)?makeSortFunction("numeric","asc",c):makeSortFunction("numeric","desc",c));var e="e"+i;dynamicExp+="var "+e+" = "+s;dynamicExp+="if("+e+") { return "+e+"; } ";dynamicExp+="else { ";}var orgOrderCol=cache.normalized[0].length-1;dynamicExp+="return a["+orgOrderCol+"]-b["+orgOrderCol+"];";for(var i=0;i<l;i++){dynamicExp+="}; ";}dynamicExp+="return 0; ";dynamicExp+="}; ";if(table.config.debug){benchmark("Evaling expression:"+dynamicExp,new Date());}eval(dynamicExp);cache.normalized.sort(sortWrapper);if(table.config.debug){benchmark("Sorting on "+sortList.toString()+" and dir "+order+" time:",sortTime);}return cache;};function makeSortFunction(type,direction,index){var a="a["+index+"]",b="b["+index+"]";if(type=='text'&&direction=='asc'){return"("+a+" == "+b+" ? 0 : ("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : ("+a+" < "+b+") ? -1 : 1 )));";}else if(type=='text'&&direction=='desc'){return"("+a+" == "+b+" ? 0 : ("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : ("+b+" < "+a+") ? -1 : 1 )));";}else if(type=='numeric'&&direction=='asc'){return"("+a+" === null && "+b+" === null) ? 0 :("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : "+a+" - "+b+"));";}else if(type=='numeric'&&direction=='desc'){return"("+a+" === null && "+b+" === null) ? 0 :("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : "+b+" - "+a+"));";}};function makeSortText(i){return"((a["+i+"] < b["+i+"]) ? -1 : ((a["+i+"] > b["+i+"]) ? 1 : 0));";};function makeSortTextDesc(i){return"((b["+i+"] < a["+i+"]) ? -1 : ((b["+i+"] > a["+i+"]) ? 1 : 0));";};function makeSortNumeric(i){return"a["+i+"]-b["+i+"];";};function makeSortNumericDesc(i){return"b["+i+"]-a["+i+"];";};function sortText(a,b){if(table.config.sortLocaleCompare)return a.localeCompare(b);return((a<b)?-1:((a>b)?1:0));};function sortTextDesc(a,b){if(table.config.sortLocaleCompare)return b.localeCompare(a);return((b<a)?-1:((b>a)?1:0));};function sortNumeric(a,b){return a-b;};function sortNumericDesc(a,b){return b-a;};function getCachedSortType(parsers,i){return parsers[i].type;};this.construct=function(settings){return this.each(function(){if(!this.tHead||!this.tBodies)return;var $this,$document,$headers,cache,config,shiftDown=0,sortOrder;this.config={};config=$.extend(this.config,$.tablesorter.defaults,settings);$this=$(this);$.data(this,"tablesorter",config);$headers=buildHeaders(this);this.config.parsers=buildParserCache(this,$headers);cache=buildCache(this);var sortCSS=[config.cssDesc,config.cssAsc];fixColumnWidth(this);$headers.click(function(e){var totalRows=($this[0].tBodies[0]&&$this[0].tBodies[0].rows.length)||0;if(!this.sortDisabled&&totalRows>0){$this.trigger("sortStart");var $cell=$(this);var i=this.column;this.order=this.count++%2;if(this.lockedOrder)this.order=this.lockedOrder;if(!e[config.sortMultiSortKey]){config.sortList=[];if(config.sortForce!=null){var a=config.sortForce;for(var j=0;j<a.length;j++){if(a[j][0]!=i){config.sortList.push(a[j]);}}}config.sortList.push([i,this.order]);}else{if(isValueInArray(i,config.sortList)){for(var j=0;j<config.sortList.length;j++){var s=config.sortList[j],o=config.headerList[s[0]];if(s[0]==i){o.count=s[1];o.count++;s[1]=o.count%2;}}}else{config.sortList.push([i,this.order]);}};setTimeout(function(){setHeadersCss($this[0],$headers,config.sortList,sortCSS);appendToTable($this[0],multisort($this[0],config.sortList,cache));},1);return false;}}).mousedown(function(){if(config.cancelSelection){this.onselectstart=function(){return false};return false;}});$this.bind("update",function(){var me=this;setTimeout(function(){me.config.parsers=buildParserCache(me,$headers);cache=buildCache(me);},1);}).bind("updateCell",function(e,cell){var config=this.config;var pos=[(cell.parentNode.rowIndex-1),cell.cellIndex];cache.normalized[pos[0]][pos[1]]=config.parsers[pos[1]].format(getElementText(config,cell),cell);}).bind("sorton",function(e,list){$(this).trigger("sortStart");config.sortList=list;var sortList=config.sortList;updateHeaderSortCount(this,sortList);setHeadersCss(this,$headers,sortList,sortCSS);appendToTable(this,multisort(this,sortList,cache));}).bind("appendCache",function(){appendToTable(this,cache);}).bind("applyWidgetId",function(e,id){getWidgetById(id).format(this);}).bind("applyWidgets",function(){applyWidget(this);});if($.metadata&&($(this).metadata()&&$(this).metadata().sortlist)){config.sortList=$(this).metadata().sortlist;}if(config.sortList.length>0){$this.trigger("sorton",[config.sortList]);}applyWidget(this);});};this.addParser=function(parser){var l=parsers.length,a=true;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==parser.id.toLowerCase()){a=false;}}if(a){parsers.push(parser);};};this.addWidget=function(widget){widgets.push(widget);};this.formatFloat=function(s){var i=parseFloat(s);return(isNaN(i))?0:i;};this.formatInt=function(s){var i=parseInt(s);return(isNaN(i))?0:i;};this.isDigit=function(s,config){return/^[-+]?\d*$/.test($.trim(s.replace(/[,.']/g,'')));};this.clearTableBody=function(table){if($.browser.msie){function empty(){while(this.firstChild)this.removeChild(this.firstChild);}empty.apply(table.tBodies[0]);}else{table.tBodies[0].innerHTML="";}};}});$.fn.extend({tablesorter:$.tablesorter.construct});var ts=$.tablesorter;ts.addParser({id:"text",is:function(s){return true;},format:function(s){return $.trim(s.toLocaleLowerCase());},type:"text"});ts.addParser({id:"digit",is:function(s,table){var c=table.config;return $.tablesorter.isDigit(s,c);},format:function(s){return $.tablesorter.formatFloat(s);},type:"numeric"});ts.addParser({id:"currency",is:function(s){return/^[Â£$â‚¬?.]/.test(s);},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/[Â£$â‚¬]/g),""));},type:"numeric"});ts.addParser({id:"ipAddress",is:function(s){return/^\d{2,3}[\.]\d{2,3}[\.]\d{2,3}[\.]\d{2,3}$/.test(s);},format:function(s){var a=s.split("."),r="",l=a.length;for(var i=0;i<l;i++){var item=a[i];if(item.length==2){r+="0"+item;}else{r+=item;}}return $.tablesorter.formatFloat(r);},type:"numeric"});ts.addParser({id:"url",is:function(s){return/^(https?|ftp|file):\/\/$/.test(s);},format:function(s){return jQuery.trim(s.replace(new RegExp(/(https?|ftp|file):\/\//),''));},type:"text"});ts.addParser({id:"isoDate",is:function(s){return/^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(s);},format:function(s){return $.tablesorter.formatFloat((s!="")?new Date(s.replace(new RegExp(/-/g),"/")).getTime():"0");},type:"numeric"});ts.addParser({id:"percent",is:function(s){return/\%$/.test($.trim(s));},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/%/g),""));},type:"numeric"});ts.addParser({id:"usLongDate",is:function(s){return s.match(new RegExp(/^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/));},format:function(s){return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"shortDate",is:function(s){return/\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}/.test(s);},format:function(s,table){var c=table.config;s=s.replace(/\-/g,"/");if(c.dateFormat=="us"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$1/$2");}else if(c.dateFormat=="uk"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$2/$1");}else if(c.dateFormat=="dd/mm/yy"||c.dateFormat=="dd-mm-yy"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{2})/,"$1/$2/$3");}return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"time",is:function(s){return/^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/.test(s);},format:function(s){return $.tablesorter.formatFloat(new Date("2000/01/01 "+s).getTime());},type:"numeric"});ts.addParser({id:"metadata",is:function(s){return false;},format:function(s,table,cell){var c=table.config,p=(!c.parserMetadataName)?'sortValue':c.parserMetadataName;return $(cell).metadata()[p];},type:"numeric"});ts.addWidget({id:"zebra",format:function(table){if(table.config.debug){var time=new Date();}var $tr,row=-1,odd;$("tr:visible",table.tBodies[0]).each(function(i){$tr=$(this);if(!$tr.hasClass(table.config.cssChildRow))row++;odd=(row%2==0);$tr.removeClass(table.config.widgetZebra.css[odd?0:1]).addClass(table.config.widgetZebra.css[odd?1:0])});if(table.config.debug){$.tablesorter.benchmark("Applying Zebra widget",time);}}});})(jQuery);

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////





////////////////////////////////// METADATA

(function($) {



$.extend({

  metadata : {

    defaults : {

      type: 'class',

      name: 'metadata',

      cre: /({.*})/,

      single: 'metadata'

    },

    setType: function( type, name ){

      this.defaults.type = type;

      this.defaults.name = name;

    },

    get: function( elem, opts ){

      var settings = $.extend({},this.defaults,opts);

      // check for empty string in single property

      if ( !settings.single.length ) settings.single = 'metadata';

      

      var data = $.data(elem, settings.single);

      // returned cached data if it already exists

      if ( data ) return data;

      

      data = "{}";

      

      var getData = function(data) {

        if(typeof data != "string") return data;

        

        if( data.indexOf('{') < 0 ) {

          data = eval("(" + data + ")");

        }

      }

      

      var getObject = function(data) {

        if(typeof data != "string") return data;

        

        data = eval("(" + data + ")");

        return data;

      }

      

      if ( settings.type == "html5" ) {

        var object = {};

        $( elem.attributes ).each(function() {

          var name = this.nodeName;

          if(name.match(/^data-/)) name = name.replace(/^data-/, '');

          else return true;

          object[name] = getObject(this.nodeValue);

        });

      } else {

        if ( settings.type == "class" ) {

          var m = settings.cre.exec( elem.className );

          if ( m )

            data = m[1];

        } else if ( settings.type == "elem" ) {

          if( !elem.getElementsByTagName ) return;

          var e = elem.getElementsByTagName(settings.name);

          if ( e.length )

            data = $.trim(e[0].innerHTML);

        } else if ( elem.getAttribute != undefined ) {

          var attr = elem.getAttribute( settings.name );

          if ( attr )

            data = attr;

        }

        object = getObject(data.indexOf("{") < 0 ? "{" + data + "}" : data);

      }

      

      $.data( elem, settings.single, object );

      return object;

    }

  }

});





$.fn.metadata = function( opts ){

  return $.metadata.get( this[0], opts );

};



})(jQuery);

/////////////////////////////////////////////////////////////////////////////////////////////////





/////////////PAGINATOR





var tablePaginater = (function() {

        /*



        Localise the button titles here...



        %p is replaced with the appropriate page number

        %t is replaced with the total number of pages

        

        */

        var tableInfo = {},

            uniqueID  = 0,

            text      = ["First Page","Previous Page (Page %p)","Next Page (Page %p)","Last Page (Page %t)","Page %p of %t"];

            

        var addClass = function(e,c) {

                if(new RegExp("(^|\\s)" + c + "(\\s|$)").test(e.className)) return;

                e.className += ( e.className ? " " : "" ) + c;

        }; 

        

        /*@cc_on

        /*@if (@_win32)

        var removeClass = function(e,c) {

                e.className = !c ? "" : e.className.replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s*((?:[\S\s]*\S)?)\s*$/, '$1');

        };

        @else @*/

        var removeClass = function(e,c) {                 

                e.className = !c ? "" : (e.className || "").replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s\s*/, '').replace(/\s\s*$/, '');

        };

        /*@end

        @*/  

        

        var addEvent = function(obj, type, fn) {

                if( obj.attachEvent ) {

                        obj["e"+type+fn] = fn;

                        obj[type+fn] = function(){obj["e"+type+fn]( window.event );};

                        obj.attachEvent( "on"+type, obj[type+fn] );

                } else {

                        obj.addEventListener( type, fn, true );

                };

        };

        var removeEvent = function(obj, type, fn) {

                try {

                        if( obj.detachEvent ) {

                                obj.detachEvent( "on"+type, obj[type+fn] );

                                obj[type+fn] = null;

                        } else {

                                obj.removeEventListener( type, fn, true );

                        };

                } catch(err) {};

        };

        var stopEvent = function(e) {

                e = e || window.event;

                if(e.stopPropagation) {

                        e.stopPropagation();

                        e.preventDefault();

                };

                

                /*@cc_on@*/

                /*@if(@_win32)

                e.cancelBubble = true;

                e.returnValue  = false;

                /*@end@*/

                return false;

        }; 

        

        var init = function(tableId) {

                var tables = tableId && typeof(tableId) == "string" ? [document.getElementById(tableId)] : document.getElementsByTagName('table'),

                    hook, maxPages, visibleRows, numPages, cp, cb, rowList;

                

                for(var t = 0, tbl; tbl = tables[t]; t++) {

                        if(tbl.className.search(/paginate-([0-9]+)/) == -1) { continue; };



                        if(!tbl.id) { tbl.id = "fdUniqueTableId_" + uniqueID++; };



                        maxPages = tbl.className.search(/max-pages-([0-9]+)/) == -1 ? null : Number(tbl.className.match(/max-pages-([0-9]+)/)[1]);

                        if(maxPages % 2 == 0 && maxPages > 1) { maxPages--; };

                        

                        hook = tbl.getElementsByTagName('tbody');

                        hook = (hook.length) ? hook[0] : tbl;



                        visibleRows = calculateVisibleRows(hook);

                        

                        if(maxPages > (visibleRows / Number(tbl.className.match(/paginate-([0-9]+)/)[1]))) {

                                maxPages = null;

                        };

                        

                        numPages = Math.ceil(visibleRows / Number(tbl.className.match(/paginate-([0-9]+)/)[1]));

                        

                        if(numPages < 2 && !(tbl.id in tableInfo)) {

                                continue;

                        };

                        

                        cp = (tbl.id in tableInfo) ? Math.min(tableInfo[tbl.id].currentPage, numPages) : 1;

                        

                        tableInfo[tbl.id] = {

                                rowsPerPage:Number(tbl.className.match(/paginate-([0-9]+)/)[1]),

                                currentPage:cp,

                                totalRows:hook.getElementsByTagName('tr').length,

                                hook:hook,

                                maxPages:maxPages,

                                numPages:numPages,

                                rowStyle:tbl.className.search(/rowstyle-([\S]+)/) != -1 ? tbl.className.match(/rowstyle-([\S]+)/)[1] : false,

                                callbacks:parseCallback(/^paginationcallback-/i, /paginationcallback-([\S-]+)/ig, tbl.className)

                        };

                        

                        showPage(tbl.id);

                        hook = null;

                };

        };

        

        var parseCallback = function(head, regExp, cname) {

                var cbs    = [],

                    matchs = cname.match(regExp),

                    parts, obj, func;

                

                if(!matchs) { return []; };

                  

                for(var i = 0, mtch; mtch = matchs[i]; i++) {                         

                        mtch = mtch.replace(head, "").replace(/-/g, ".");

                         

                        try {

                                if(mtch.indexOf(".") != -1) {

                                        parts = mtch.split('.');

                                        obj   = window;

                                        for (var x = 0, part; part = obj[parts[x]]; x++) {

                                                if(part instanceof Function) {

                                                        (function() {

                                                                var method = part;

                                                                func = function (data) { method.apply(obj, [data]) };

                                                        })();

                                                } else {

                                                        obj = part;

                                                };

                                        };

                                } else {

                                        func = window[mtch];

                                };

                            

                                if(!(func instanceof Function)) continue;

                                cbs[cbs.length] = func;                              

                        } catch(err) {};

                };

                

                return cbs;                      

        };

                

        var callback = function(tblId, opts) {                

                if(!(tblId in tableInfo) || !(tableInfo[tblId]["callbacks"].length)) return;                

                for(var i = 0, func; func = tableInfo[tblId]["callbacks"][i]; i++) {

                        func(opts || {});

                };

        };

        

        var calculateVisibleRows = function(hook) {

                var trs = hook.rows,

                    cnt = 0,

                    reg = /(^|\s)invisibleRow(\s|$)/;

                

                for(var i = 0, tr; tr = trs[i]; i++) {

                        if(tr.parentNode != hook || tr.getElementsByTagName("th").length || (tr.parentNode && tr.parentNode.tagName.toLowerCase().search(/thead|tfoot/) != -1)) continue;

                        if(tr.className.search(reg) == -1) { cnt++; };

                };

                

                return cnt;

        };

        

        var createButton = function(details, ul, pseudo) {

                var li   = document.createElement("li"),

                    but  = document.createElement(pseudo ? "div" : "a"),

                    span = document.createElement("span");



                if(!pseudo) { 

                        but.href = "#"; 

                        but.title = details.title; 

                };

                

                but.className = details.className;



                ul.appendChild(li);

                li.appendChild(but);

                but.appendChild(span);

                span.appendChild(document.createTextNode(details.text));



                if(!pseudo) { 

                        li.onclick = but.onclick = buttonClick; 

                        if(details.id) { but.id = details.id; };

                };                 

                

                li = but = span = null;

        };

        var removePagination = function(tableId) {

                var wrapT = document.getElementById(tableId + "-fdtablePaginaterWrapTop"),

                    wrapB = document.getElementById(tableId + "-fdtablePaginaterWrapBottom");

                if(wrapT) { wrapT.parentNode.removeChild(wrapT); };

                if(wrapB) { wrapB.parentNode.removeChild(wrapB); };

        };

        var buildPagination = function(tblId) {

                if(!(tblId in tableInfo)) { return; };



                removePagination(tblId);



                var details = tableInfo[tblId];

                

                if(details.numPages < 2) return;

                

                function resolveText(txt, curr) {

                        curr = curr || details.currentPage;

                        return txt.replace("%p", curr).replace("%t", details.numPages);

                };



                if(details.maxPages) {

                        findex = Math.max(0, Math.floor(Number(details.currentPage - 1) - (Number(details.maxPages - 1) / 2)));

                        lindex = findex + Number(details.maxPages);

                        if(lindex > details.numPages) {

                                lindex = details.numPages;

                                findex = Math.max(0, details.numPages - Number(details.maxPages));

                        };

                } else {

                        findex = 0;

                        lindex = details.numPages;

                };

                



                var wrapT = document.createElement("div");

                wrapT.className = "fdtablePaginaterWrap fdtablePaginatorWrapTop";

                wrapT.id = tblId + "-fdtablePaginaterWrapTop";



                var wrapB = document.createElement("div");

                wrapB.className = "fdtablePaginaterWrap fdtablePaginatorWrapBottom";

                wrapB.id = tblId + "-fdtablePaginaterWrapBottom";



                // Create list scaffold

                var ulT = document.createElement("ul");

                ulT.id  = tblId + "-tablePaginater";



                var ulB = document.createElement("ul");

                ulB.id  = tblId + "-tablePaginaterClone";

                ulT.className = ulB.className = "fdtablePaginater";



                // Add to the wrapper DIVs

                wrapT.appendChild(ulT);

                wrapB.appendChild(ulB);



                // FIRST (only created if maxPages set)

                if(details.maxPages) {

                        createButton({title:text[0], className:"first-page", text:"\u00ab"}, ulT, !findex);

                        createButton({title:text[0], className:"first-page", text:"\u00ab"}, ulB, !findex);

                };

                

                // PREVIOUS (only created if there are more than two pages)

                if(details.numPages > 2) {

                        createButton({title:resolveText(text[1], details.currentPage-1), className:"previous-page", text:"\u2039", id:tblId+"-previousPage"}, ulT, details.currentPage == 1);

                        createButton({title:resolveText(text[1], details.currentPage-1), className:"previous-page", text:"\u2039", id:tblId+"-previousPageC"}, ulB, details.currentPage == 1);

                };

                

                // NUMBERED

                for(var i = findex; i < lindex; i++) {

                        createButton({title:resolveText(text[4], i+1), className:i != (details.currentPage-1) ? "page-"+(i+1) : "currentPage page-"+(i+1), text:(i+1), id:i == (details.currentPage-1) ? tblId + "-currentPage" : ""}, ulT);

                        createButton({title:resolveText(text[4], i+1), className:i != (details.currentPage-1) ? "page-"+(i+1) : "currentPage page-"+(i+1), text:(i+1), id:i == (details.currentPage-1) ? tblId + "-currentPageC" : ""}, ulB);

                };



                // NEXT (only created if there are more than two pages)

                if(details.numPages > 2) {

                        createButton({title:resolveText(text[2], details.currentPage + 1), className:"next-page", text:"\u203a", id:tblId+"-nextPage"}, ulT, details.currentPage == details.numPages);

                        createButton({title:resolveText(text[2], details.currentPage + 1), className:"next-page", text:"\u203a", id:tblId+"-nextPageC"}, ulB, details.currentPage == details.numPages);

                };

                

                // LAST (only created if maxPages set)

                if(details.maxPages) {

                        createButton({title:resolveText(text[3], details.numPages), className:"last-page", text:"\u00bb"}, ulT, lindex == details.numPages);

                        createButton({title:resolveText(text[3], details.numPages), className:"last-page", text:"\u00bb"}, ulB, lindex == details.numPages);

                };

                

                // DOM inject wrapper DIVs (FireFox 2.x Bug: this has to be done here if you use display:table)

                if(document.getElementById(tblId+"-paginationListWrapTop")) {

                        document.getElementById(tblId+"-paginationListWrapTop").appendChild(wrapT);

                } else {

                        document.getElementById(tblId).parentNode.insertBefore(wrapT, document.getElementById(tblId));

                };



                if(document.getElementById(tblId+"-paginationListWrapBottom")) {

                        document.getElementById(tblId+"-paginationListWrapBottom").appendChild(wrapB);

                } else {

                        document.getElementById(tblId).parentNode.insertBefore(wrapB, document.getElementById(tblId).nextSibling);

                };

        };

        

        // The tableSort script uses this function to redraw.

        var tableSortRedraw = function(tableid, identical) {

                if(!tableid || !(tableid in fdTableSort.tableCache) || !(tableid in tableInfo)) { return; };

                

                var dataObj     = fdTableSort.tableCache[tableid],

                    data        = dataObj.data,

                    len1        = data.length,

                    len2        = len1 ? data[0].length - 1 : 0,

                    hook        = dataObj.hook,

                    colStyle    = dataObj.colStyle,

                    rowStyle    = dataObj.rowStyle,

                    colOrder    = dataObj.colOrder,                 

                    page        = tableInfo[tableid].currentPage - 1,

                    d1          = tableInfo[tableid].rowsPerPage * page,

                    d2          = Math.min(tableInfo[tableid].totalRows, d1 + tableInfo[tableid].rowsPerPage), 

                    cnt         = 0,

                    rs          = 0,

                    reg         = /(^|\s)invisibleRow(\s|$)/,                

                    tr, tds, cell, pos;

                

                for(var i = 0; i < len1; i++) {

                        tr = data[i][len2];

                        

                        if(colStyle) {

                                tds = tr.cells;

                                for(thPos in colOrder) {

                                        if(!colOrder[thPos]) removeClass(tds[thPos], colStyle);

                                        else addClass(tds[thPos], colStyle);

                                };

                        };

                        

                        if(tr.className.search(reg) != -1) { continue; };

                        

                        if(!identical) {

                                cnt++;



                                if(cnt > d1 && cnt <= d2) {

                                        if(rowStyle) {

                                                if(rs++ & 1) addClass(tr, rowStyle);

                                                else removeClass(tr, rowStyle);

                                        };

                                        tr.style.display = "";

                                } else {

                                        tr.style.display = "none";

                                };



                                // Netscape 8.1.2 requires the removeChild call or it freaks out, so add the line if you want to support this browser

                                // hook.removeChild(tr);

                                hook.appendChild(tr);

                        };

                };



                tr = tds = hook = null;

        };

        

        var showPage = function(tblId, pageNum) {

                if(!(tblId in tableInfo)) { return; };



                var page = Math.max(0, !pageNum ? tableInfo[tblId].currentPage - 1 : pageNum - 1),

                    d1  = tableInfo[tblId].rowsPerPage * page,

                    d2  = Math.min(tableInfo[tblId].totalRows, d1 + tableInfo[tblId].rowsPerPage),

                    trs = tableInfo[tblId].hook.rows,

                    cnt = 0,

                    rc  = 0,

                    len = trs.length,

                    rs  = tableInfo[tblId].rowStyle,

                    reg = /(^|\s)invisibleRow(\s|$)/,

                    row = [];

                

                for(var i = 0; i < len; i++) {

                        if(trs[i].className.search(reg) != -1 || trs[i].getElementsByTagName("th").length || (trs[i].parentNode && trs[i].parentNode.tagName.toLowerCase().search(/thead|tfoot/) != -1)) { continue; };

                        

                        cnt++;

                        

                        if(cnt > d1 && cnt <= d2) {

                                if(rs) {

                                        if(rc++ & 1) {

                                                addClass(trs[i], rs);

                                        } else {

                                                removeClass(trs[i], rs);

                                        }

                                };

                                trs[i].style.display = "";

                                row[row.length] = trs[i];

                        } else {

                                trs[i].style.display = "none";

                        };

                };



                buildPagination(tblId);

                callback(tblId, {"table":tblId, "totalRows":len, "currentPage":(page+1), "rowsPerPage":tableInfo[tblId].rowsPerPage, "visibleRows":row});

        };

        

        var buttonClick = function(e) {

                e = e || window.event;



                var a = this.tagName.toLowerCase() == "a" ? this : this.getElementsByTagName("a")[0];



                if(a.className.search("currentPage") != -1) return false;



                var ul = this;

                while(ul.tagName.toLowerCase() != "ul") ul = ul.parentNode;



                var tblId = ul.id.replace("-tablePaginaterClone","").replace("-tablePaginater", "");



                tableInfo[tblId].lastPage = tableInfo[tblId].currentPage;

                

                var showPrevNext = 0;

                

                if(a.className.search("previous-page") != -1) {

                        tableInfo[tblId].currentPage = tableInfo[tblId].currentPage > 1 ? tableInfo[tblId].currentPage - 1 : tableInfo[tblId].numPages;

                        showPrevNext = 1;

                } else if(a.className.search("next-page") != -1) {

                        tableInfo[tblId].currentPage = tableInfo[tblId].currentPage < tableInfo[tblId].numPages ? tableInfo[tblId].currentPage + 1 : 1;

                        showPrevNext = 2;

                } else if(a.className.search("first-page") != -1) {

                        tableInfo[tblId].currentPage = 1;

                } else if(a.className.search("last-page") != -1) {

                        tableInfo[tblId].currentPage = tableInfo[tblId].numPages;

                } else {

                        tableInfo[tblId].currentPage = parseInt(a.className.match(/page-([0-9]+)/)[1]) || 1;

                };

			

				$("#"+tblId+"_Content").fadeTo("slow", 0.3, function(){

				showPage(tblId);

				$("#"+tblId+"_Content").fadeTo("slow", 1);	

				});

   			 

                // Focus on the appropriate button (previous, next or the current page)

                // I'm hoping screen readers are savvy enough to indicate the focus event to the user

                if(showPrevNext == 1) {

                        var elem = document.getElementById(ul.id.search("-tablePaginaterClone") != -1 ? tblId + "-previousPageC" : tblId + "-previousPage");

                } else if(showPrevNext == 2) {

                        var elem = document.getElementById(ul.id.search("-tablePaginaterClone") != -1 ? tblId + "-nextPageC" : tblId + "-nextPage");

                } else {

                        var elem = document.getElementById(ul.id.search("-tablePaginaterClone") != -1 ? tblId + "-currentPageC" : tblId + "-currentPage");

                };

                

                if(elem && elem.tagName.toLowerCase() == "a") { elem.focus(); };   

                

                return stopEvent(e);

        };

        

        var onUnLoad = function(e) {

                var tbl, lis, pagination, uls;

                for(tblId in tableInfo) {

                        uls = [tblId + "-tablePaginater", tblId + "-tablePaginaterClone"];

                        for(var z = 0; z < 2; z++) {

                                pagination = document.getElementById(uls[z]);

                                if(!pagination) { continue; };

                                lis = pagination.getElementsByTagName("li");

                                for(var i = 0, li; li = lis[i]; i++) {

                                        li.onclick = null;

                                        if(li.getElementsByTagName("a").length) { li.getElementsByTagName("a")[0].onclick = null; };

                                };

                        };

                };

        };

        

        addEvent(window, "load",   init);

        addEvent(window, "unload", onUnLoad); 

        

        return {                  

                init:                   function(tableId) { init(tableId); },                 

                redraw:                 function(tableid, identical) { tableSortRedraw(tableid, identical); },

                tableIsPaginated:       function(tableId) { return (tableId in tableInfo); },

                changeTranslations:     function(translations) { text = translations; }

        };        

})();



/////////////////////////////////////////////////////////////////////////////////////////





////////////////GET A ELEMENT POSITION

 function getPosition(n,endNode){ 

    var left = 0; 

    var top =0; 

    var node = n; 

    done=false; 

    while(!done){ 

        if(node.offsetLeft!=null) 

                left += node.offsetLeft; 

        if(node.offsetTop!=null) 

                top += node.offsetTop; 

        if(node.offsetParent){ 

                node = node.offsetParent; 

        }else{ 

                done = true; 

        } 

        if(node == endNode) 

                done = true; 

    } 

    done=false; 

    node = n; 

    while(!done){ 

        if(document.all && node.style && parseInt(node.style.borderLeftWidth)){ 

                left += parseInt(node.style.borderLeftWidth); 

        } 

        if(document.all && node.style && parseInt(node.style.borderTopWidth)){ 

                top += parseInt(node.style.borderTopWidth); 

        } 

 

        if(node.scrollLeft){ 

                left -= node.scrollLeft; 

        } 

        if(node.scrollTop) 

                top -= node.scrollTop; 

        if(node.parentNode) 

                node = node.parentNode; 

        else 

                done=true; 

    } 

    return new Array(left, top); 

} 

 ///////////////////////////////////////////////////////////

 

 

 //////////////SEARCH BOX

 jQuery.autocomplete = function(input, options) {

	// Create a link to self

	var me = this;



	// Create jQuery object for input element

	var $input = $(input).attr("autocomplete", "off");



	// Apply inputClass if necessary

	if (options.inputClass) $input.addClass(options.inputClass);



	// Create results

	var results = document.createElement("div");

	// Create jQuery object for results

	var $results = $(results);

	$results.hide().addClass(options.resultsClass).css("position", "absolute");

	if( options.width > 0 ) $results.css("width", options.width);



	// Add to body element

	$("body").append(results);



	input.autocompleter = me;



	var timeout = null;

	var prev = "";

	var active = -1;

	var cache = {};

	var keyb = false;

	var hasFocus = false;

	var lastKeyPressCode = null;



	// flush cache

	function flushCache(){

		cache = {};

		cache.data = {};

		cache.length = 0;

	};



	// flush cache

	flushCache();



	// if there is a data array supplied

	if( options.data != null ){

		var sFirstChar = "", stMatchSets = {}, row = [];



		// no url was specified, we need to adjust the cache length to make sure it fits the local data store

		if( typeof options.url != "string" ) options.cacheLength = 1;



		// loop through the array and create a lookup structure

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

			// if row is a string, make an array otherwise just reference the array

			row = ((typeof options.data[i] == "string") ? [options.data[i]] : options.data[i]);



			// if the length is zero, don't add to list

			if( row[0].length > 0 ){

				// get the first character

				sFirstChar = row[0].substring(0, 1).toLowerCase();

				// if no lookup array for this character exists, look it up now

				if( !stMatchSets[sFirstChar] ) stMatchSets[sFirstChar] = [];

				// if the match is a string

				stMatchSets[sFirstChar].push(row);

			}

		}



		// add the data items to the cache

		for( var k in stMatchSets ){

			// increase the cache size

			options.cacheLength++;

			// add to the cache

			addToCache(k, stMatchSets[k]);

		}

	}



	$input

	.keydown(function(e) {

		// track last key pressed

		lastKeyPressCode = e.keyCode;

		switch(e.keyCode) {

			case 38: // up

				e.preventDefault();

				moveSelect(-1);

				break;

			case 40: // down

				e.preventDefault();

				moveSelect(1);

				break;

			case 9:  // tab

			case 13: // return

				if( selectCurrent() ){

					// make sure to blur off the current field

					$input.get(0).blur();

					e.preventDefault();

				}

				break;

			default:

				active = -1;

				if (timeout) clearTimeout(timeout);

				timeout = setTimeout(function(){onChange();}, options.delay);

				break;

		}

	})

	.focus(function(){

		// track whether the field has focus, we shouldn't process any results if the field no longer has focus

		hasFocus = true;

	})

	.blur(function() {

		// track whether the field has focus

		hasFocus = false;

		hideResults();

	});



	hideResultsNow();



	function onChange() {

		// ignore if the following keys are pressed: [del] [shift] [capslock]

		if( lastKeyPressCode == 46 || (lastKeyPressCode > 8 && lastKeyPressCode < 32) ) return $results.hide();

		var v = $input.val();

		if (v == prev) return;

		prev = v;

		if (v.length >= options.minChars) {

			$input.addClass(options.loadingClass);

			requestData(v);

		} else {

			$input.removeClass(options.loadingClass);

			$results.hide();

		}

	};



 	function moveSelect(step) {



		var lis = $("li", results);

		if (!lis) return;



		active += step;



		if (active < 0) {

			active = 0;

		} else if (active >= lis.size()) {

			active = lis.size() - 1;

		}



		lis.removeClass("ac_over");



		$(lis[active]).addClass("ac_over");



		// Weird behaviour in IE

		// if (lis[active] && lis[active].scrollIntoView) {

		// 	lis[active].scrollIntoView(false);

		// }



	};



	function selectCurrent() {

		var li = $("li.ac_over", results)[0];

		if (!li) {

			var $li = $("li", results);

			if (options.selectOnly) {

				if ($li.length == 1) li = $li[0];



			} else if (options.selectFirst) {

				li = $li[0];

			}

		}

		if (li) {

			selectItem(li);

			return true;

		} else {

			return false;

		}

	};



	function selectItem(li) {

		if (!li) {

			li = document.createElement("li");

			li.extra = [];

			li.selectValue = "";

		}

		var v = $.trim(li.selectValue ? li.selectValue : li.innerHTML);

		input.lastSelected = v;

		prev = v;

		$results.html("");

		$input.val(v);

		hideResultsNow();

		if (options.onItemSelect) setTimeout(function() { options.onItemSelect(li) }, 1);

	};



	// selects a portion of the input string

	function createSelection(start, end){

		// get a reference to the input element

		var field = $input.get(0);

		if( field.createTextRange ){

			var selRange = field.createTextRange();

			selRange.collapse(true);

			selRange.moveStart("character", start);

			selRange.moveEnd("character", end);

			selRange.select();

		} else if( field.setSelectionRange ){

			field.setSelectionRange(start, end);

		} else {

			if( field.selectionStart ){

				field.selectionStart = start;

				field.selectionEnd = end;

			}

		}

		field.focus();

	};



	// fills in the input box w/the first match (assumed to be the best match)

	function autoFill(sValue){

		// if the last user key pressed was backspace, don't autofill

		if( lastKeyPressCode != 8 ){

			// fill in the value (keep the case the user has typed)

			$input.val($input.val() + sValue.substring(prev.length));

			// select the portion of the value not typed by the user (so the next character will erase)

			createSelection(prev.length, sValue.length);

		}

	};



	function showResults() {

		// get the position of the input field right now (in case the DOM is shifted)

		var pos = findPos(input);

		// either use the specified width, or autocalculate based on form element

		var iWidth = (options.width > 0) ? options.width : $input.width();

		// reposition

		$results.css({

			width: parseInt(iWidth) + "px",

			top: (pos.y + input.offsetHeight) + "px",

			left: pos.x + "px"

		}).show();

	};



	function hideResults() {

		if (timeout) clearTimeout(timeout);

		timeout = setTimeout(hideResultsNow, 200);

	};



	function hideResultsNow() {

		if (timeout) clearTimeout(timeout);

		$input.removeClass(options.loadingClass);

		if ($results.is(":visible")) {

			$results.hide();

		}

		if (options.mustMatch) {

			var v = $input.val();

			if (v != input.lastSelected) {

				selectItem(null);

			}

		}

	};



	function receiveData(q, data) {

		if (data) {

			$input.removeClass(options.loadingClass);

			results.innerHTML = "";



			// if the field no longer has focus or if there are no matches, do not display the drop down

			if( !hasFocus || data.length == 0 ) return hideResultsNow();



			if ($.browser.msie) {

				// we put a styled iframe behind the calendar so HTML SELECT elements don't show through

				$results.append(document.createElement('iframe'));

			}

			results.appendChild(dataToDom(data));

			// autofill in the complete box w/the first match as long as the user hasn't entered in more data

			if( options.autoFill && ($input.val().toLowerCase() == q.toLowerCase()) ) autoFill(data[0][0]);

			showResults();

		} else {

			hideResultsNow();

		}

	};



	function parseData(data) {

		if (!data) return null;

		var parsed = [];

		var rows = data.split(options.lineSeparator);

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

			var row = $.trim(rows[i]);

			if (row) {

				parsed[parsed.length] = row.split(options.cellSeparator);

			}

		}

		return parsed;

	};



	function dataToDom(data) {

		var ul = document.createElement("ul");

		var num = data.length;



		// limited results to a max number

		if( (options.maxItemsToShow > 0) && (options.maxItemsToShow < num) ) num = options.maxItemsToShow;



		for (var i=0; i < num; i++) {

			var row = data[i];

			if (!row) continue;

			var li = document.createElement("li");

			if (options.formatItem) {

				li.innerHTML = options.formatItem(row, i, num);

				li.selectValue = row[0];

			} else {

				li.innerHTML = row[0];

				li.selectValue = row[0];

			}

			var extra = null;

			if (row.length > 1) {

				extra = [];

				for (var j=1; j < row.length; j++) {

					extra[extra.length] = row[j];

				}

			}

			li.extra = extra;

			ul.appendChild(li);

			$(li).hover(

				function() { $("li", ul).removeClass("ac_over"); $(this).addClass("ac_over"); active = $("li", ul).indexOf($(this).get(0)); },

				function() { $(this).removeClass("ac_over"); }

			).click(function(e) { e.preventDefault(); e.stopPropagation(); selectItem(this) });

		}

		return ul;

	};



	function requestData(q) {

		if (!options.matchCase) q = q.toLowerCase();

		var data = options.cacheLength ? loadFromCache(q) : null;

		// recieve the cached data

		if (data) {

			receiveData(q, data);

		// if an AJAX url has been supplied, try loading the data now

		} else if( (typeof options.url == "string") && (options.url.length > 0) ){

			$.get(makeUrl(q), function(data) {

				data = parseData(data);

				addToCache(q, data);

				receiveData(q, data);

			});

		// if there's been no data found, remove the loading class

		} else {

			$input.removeClass(options.loadingClass);

		}

	};



	function makeUrl(q) {

		var url = options.url + "?q=" + encodeURI(q);

		for (var i in options.extraParams) {

			url += "&" + i + "=" + encodeURI(options.extraParams[i]);

		}

		return url;

	};



	function loadFromCache(q) {

		if (!q) return null;

		if (cache.data[q]) return cache.data[q];

		if (options.matchSubset) {

			for (var i = q.length - 1; i >= options.minChars; i--) {

				var qs = q.substr(0, i);

				var c = cache.data[qs];

				if (c) {

					var csub = [];

					for (var j = 0; j < c.length; j++) {

						var x = c[j];

						var x0 = x[0];

						if (matchSubset(x0, q)) {

							csub[csub.length] = x;

						}

					}

					return csub;

				}

			}

		}

		return null;

	};



	function matchSubset(s, sub) {

		if (!options.matchCase) s = s.toLowerCase();

		var i = s.indexOf(sub);

		if (i == -1) return false;

		return i == 0 || options.matchContains;

	};



	this.flushCache = function() {

		flushCache();

	};



	this.setExtraParams = function(p) {

		options.extraParams = p;

	};



	this.findValue = function(){

		var q = $input.val();



		if (!options.matchCase) q = q.toLowerCase();

		var data = options.cacheLength ? loadFromCache(q) : null;

		if (data) {

			findValueCallback(q, data);

		} else if( (typeof options.url == "string") && (options.url.length > 0) ){

			$.get(makeUrl(q), function(data) {

				data = parseData(data)

				addToCache(q, data);

				findValueCallback(q, data);

			});

		} else {

			// no matches

			findValueCallback(q, null);

		}

	}



	function findValueCallback(q, data){

		if (data) $input.removeClass(options.loadingClass);



		var num = (data) ? data.length : 0;

		var li = null;



		for (var i=0; i < num; i++) {

			var row = data[i];



			if( row[0].toLowerCase() == q.toLowerCase() ){

				li = document.createElement("li");

				if (options.formatItem) {

					li.innerHTML = options.formatItem(row, i, num);

					li.selectValue = row[0];

				} else {

					li.innerHTML = row[0];

					li.selectValue = row[0];

				}

				var extra = null;

				if( row.length > 1 ){

					extra = [];

					for (var j=1; j < row.length; j++) {

						extra[extra.length] = row[j];

					}

				}

				li.extra = extra;

			}

		}



		if( options.onFindValue ) setTimeout(function() { options.onFindValue(li) }, 1);

	}



	function addToCache(q, data) {

		if (!data || !q || !options.cacheLength) return;

		if (!cache.length || cache.length > options.cacheLength) {

			flushCache();

			cache.length++;

		} else if (!cache[q]) {

			cache.length++;

		}

		cache.data[q] = data;

	};



	function findPos(obj) {

		var curleft = obj.offsetLeft || 0;

		var curtop = obj.offsetTop || 0;

		while (obj = obj.offsetParent) {

			curleft += obj.offsetLeft

			curtop += obj.offsetTop

		}

		return {x:curleft,y:curtop};

	}

}



jQuery.fn.autocomplete = function(url, options, data) {

	// Make sure options exists

	options = options || {};

	// Set url as option

	options.url = url;

	// set some bulk local data

	options.data = ((typeof data == "object") && (data.constructor == Array)) ? data : null;



	// Set default values for required options

	options.inputClass = options.inputClass || "ac_input";

	options.resultsClass = options.resultsClass || "ac_results";

	options.lineSeparator = options.lineSeparator || "\n";

	options.cellSeparator = options.cellSeparator || "|";

	options.minChars = options.minChars || 1;

	options.delay = options.delay || 400;

	options.matchCase = options.matchCase || 0;

	options.matchSubset = options.matchSubset || 1;

	options.matchContains = options.matchContains || 0;

	options.cacheLength = options.cacheLength || 1;

	options.mustMatch = options.mustMatch || 0;

	options.extraParams = options.extraParams || {};

	options.loadingClass = options.loadingClass || "ac_loading";

	options.selectFirst = options.selectFirst || false;

	options.selectOnly = options.selectOnly || false;

	options.maxItemsToShow = options.maxItemsToShow || -1;

	options.autoFill = options.autoFill || false;

	options.width = parseInt(options.width, 10) || 0;



	this.each(function() {

		var input = this;

		new jQuery.autocomplete(input, options);

	});



	// Don't break the chain

	return this;

}



jQuery.fn.autocompleteArray = function(data, options) {

	return this.autocomplete(null, options, data);

}



jQuery.fn.indexOf = function(e){

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

		if( this[i] == e ) return i;

	}

	return -1;

};



//////////////////////////////////////////////////////////



////////////////////// FIELD MASKING

var zChar = new Array(' ', '(', ')', '-', '.');

var maxphonelength = 13;

var phonevalue1;

var phonevalue2;

var cursorposition;



function ParseForNumber1(object){

phonevalue1 = ParseChar(object.value, zChar);

}

function ParseForNumber2(object){

phonevalue2 = ParseChar(object.value, zChar);

}



function backspacerUP(object,e) {

if(e){

e = e

} else {

e = window.event

}

if(e.which){

var keycode = e.which

} else {

var keycode = e.keyCode

}



try{

ParseForNumber1(object)

}catch(e){}



if(keycode >= 48){

ValidatePhone(object)

}

}



function backspacerDOWN(object,e) {

if(e){

e = e

} else {

e = window.event

}

if(e.which){

var keycode = e.which

} else {

var keycode = e.keyCode

}

ParseForNumber2(object)

}



function GetCursorPosition(){



var t1 = phonevalue1;

var t2 = phonevalue2;

var bool = false

for (i=0; i<t1.length; i++)

{

if (t1.substring(i,1) != t2.substring(i,1)) {

if(!bool) {

cursorposition=i

bool=true

}

}

}

}



function ValidatePhone(object){



var p = phonevalue1



p = p.replace(/[^\d]*/gi,"")



if (p.length < 3) {

object.value=p

} else if(p.length==3){

pp=p;

d4=p.indexOf('(')

d5=p.indexOf(')')

if(d4==-1){

pp="("+pp;

}

if(d5==-1){

pp=pp+")";

}

object.value = pp;

} else if(p.length>3 && p.length < 7){

p ="(" + p;

l30=p.length;

p30=p.substring(0,4);

p30=p30+")"



p31=p.substring(4,l30);

pp=p30+p31;



object.value = pp;



} else if(p.length >= 7){

p ="(" + p;

l30=p.length;

p30=p.substring(0,4);

p30=p30+")"



p31=p.substring(4,l30);

pp=p30+p31;



l40 = pp.length;

p40 = pp.substring(0,8);

p40 = p40 + "-"



p41 = pp.substring(8,l40);

ppp = p40 + p41;



object.value = ppp.substring(0, maxphonelength);

}



try{

GetCursorPosition()

}catch(e){}



if(cursorposition >= 0){

if (cursorposition == 0) {

cursorposition = 2

} else if (cursorposition <= 2) {

cursorposition = cursorposition + 1

} else if (cursorposition <= 5) {

cursorposition = cursorposition + 2

} else if (cursorposition == 6) {

cursorposition = cursorposition + 2

} else if (cursorposition == 7) {

cursorposition = cursorposition + 4

e1=object.value.indexOf(')')

e2=object.value.indexOf('-')

if (e1>-1 && e2>-1){

if (e2-e1 == 4) {

cursorposition = cursorposition - 1

}

}

} else if (cursorposition < 11) {

cursorposition = cursorposition + 3

} else if (cursorposition == 11) {

cursorposition = cursorposition + 1

} else if (cursorposition >= 12) {

cursorposition = cursorposition

}



try{

var txtRange = object.createTextRange();

txtRange.moveStart( "character", cursorposition);

txtRange.moveEnd( "character", cursorposition - object.value.length);

txtRange.select();

}catch(e){

	}

}



}



function ParseChar(sStr, sChar)

{

if (sChar.length == null)

{

zChar = new Array(sChar);

}

else zChar = sChar;



for (i=0; i<zChar.length; i++)

{

sNewStr = "";



var iStart = 0;

var iEnd = sStr.indexOf(sChar[i]);



while (iEnd != -1)

{

sNewStr += sStr.substring(iStart, iEnd);

iStart = iEnd + 1;

iEnd = sStr.indexOf(sChar[i], iStart);

}

sNewStr += sStr.substring(sStr.lastIndexOf(sChar[i]) + 1, sStr.length);



sStr = sNewStr;

}



return sNewStr;

}

////////////////////////////////////////////////////////////////



////////////////// COMPARE DATES 25-01-11









 function compare_dates(d1, d2)  

   {  

 var Date1 = new Date(d1);

 var Date2 = new Date(d2);



 if (Date2 > Date1)

 {

  return false;

 }else{

	 return true;

	 }

 }  



/////////////////////////////////////


/*!
 * jQuery blockUI plugin
 * Version 2.39 (23-MAY-2011)
 * @requires jQuery v1.2.3 or later
 *
 * Examples at: http://malsup.com/jquery/block/
 * Copyright (c) 2007-2010 M. Alsup
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 * Thanks to Amir-Hossein Sobhi for some excellent contributions!
 */

;(function($) {

if (/1\.(0|1|2)\.(0|1|2)/.test($.fn.jquery) || /^1.1/.test($.fn.jquery)) {
	alert('blockUI requires jQuery v1.2.3 or later!  You are using v' + $.fn.jquery);
	return;
}

$.fn._fadeIn = $.fn.fadeIn;

var noOp = function() {};

// this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle
// retarded userAgent strings on Vista)
var mode = document.documentMode || 0;
var setExpr = $.browser.msie && (($.browser.version < 8 && !mode) || mode < 8);
var ie6 = $.browser.msie && /MSIE 6.0/.test(navigator.userAgent) && !mode;

// global $ methods for blocking/unblocking the entire page
$.blockUI   = function(opts) { install(window, opts); };
$.unblockUI = function(opts) { remove(window, opts); };

// convenience method for quick growl-like notifications  (http://www.google.com/search?q=growl)
$.growlUI = function(title, message, timeout, onClose) {
	var $m = $('<div class="growlUI"></div>');
	if (title) $m.append('<h1>'+title+'</h1>');
	if (message) $m.append('<h2>'+message+'</h2>');
	if (timeout == undefined) timeout = 3000;
	$.blockUI({
		message: $m, fadeIn: 700, fadeOut: 1000, centerY: false,
		timeout: timeout, showOverlay: false,
		onUnblock: onClose, 
		css: $.blockUI.defaults.growlCSS
	});
};

// plugin method for blocking element content
$.fn.block = function(opts) {
	return this.unblock({ fadeOut: 0 }).each(function() {
		if ($.css(this,'position') == 'static')
			this.style.position = 'relative';
		if ($.browser.msie)
			this.style.zoom = 1; // force 'hasLayout'
		install(this, opts);
	});
};

// plugin method for unblocking element content
$.fn.unblock = function(opts) {
	return this.each(function() {
		remove(this, opts);
	});
};

$.blockUI.version = 2.39; // 2nd generation blocking at no extra cost!

// override these in your code to change the default behavior and style
$.blockUI.defaults = {
	// message displayed when blocking (use null for no message)
	message:  '<h1>Please wait...</h1>',

	title: null,	  // title string; only used when theme == true
	draggable: true,  // only used when theme == true (requires jquery-ui.js to be loaded)
	
	theme: false, // set to true to use with jQuery UI themes
	
	// styles for the message when blocking; if you wish to disable
	// these and use an external stylesheet then do this in your code:
	// $.blockUI.defaults.css = {};
	css: {
		padding:	'10px',
		margin:		0,
		width:		'30%',
		top:		'40%',
		left:		'43%',
		textAlign:	'left',
		color:		'#000',
		
		cursor:		'wait'
	},
	
	// minimal style set used when themes are used
	themedCSS: {
		width:	'30%',
		top:	'40%',
		left:	'35%'
	},

	// styles for the overlay
	overlayCSS:  {
		backgroundColor: '#000',
		opacity:	  	 0.6,
		cursor:		  	 'wait'
	},

	// styles applied when using $.growlUI
	growlCSS: {
		width:  	'auto',
		top:		'auto',
		left:   	'',
		right:  	'10px',
		border: 	'none',
		padding:	'5px',
		opacity:	0.6,
		cursor: 	'default',
		color:		'#fff',
		backgroundColor: '#000',
		'-webkit-border-radius': '10px',
		'-moz-border-radius':	 '10px',
		'border-radius': 		 '10px'
	},
	
	// IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w
	// (hat tip to Jorge H. N. de Vasconcelos)
	iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank',

	// force usage of iframe in non-IE browsers (handy for blocking applets)
	forceIframe: false,

	// z-index for the blocking overlay
	baseZ: 1000,

	// set these to true to have the message automatically centered
	centerX: true, // <-- only effects element blocking (page block controlled via css above)
	centerY: true,

	// allow body element to be stetched in ie6; this makes blocking look better
	// on "short" pages.  disable if you wish to prevent changes to the body height
	allowBodyStretch: true,

	// enable if you want key and mouse events to be disabled for content that is blocked
	bindEvents: true,

	// be default blockUI will supress tab navigation from leaving blocking content
	// (if bindEvents is true)
	constrainTabKey: true,

	// fadeIn time in millis; set to 0 to disable fadeIn on block
	fadeIn:  200,

	// fadeOut time in millis; set to 0 to disable fadeOut on unblock
	fadeOut:  400,

	// time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock
	timeout: 0,

	// disable if you don't want to show the overlay
	showOverlay: true,

	// if true, focus will be placed in the first available input field when
	// page blocking
	focusInput: true,

	// suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity)
	applyPlatformOpacityRules: true,
	
	// callback method invoked when fadeIn has completed and blocking message is visible
	onBlock: null,

	// callback method invoked when unblocking has completed; the callback is
	// passed the element that has been unblocked (which is the window object for page
	// blocks) and the options that were passed to the unblock call:
	//	 onUnblock(element, options)
	onUnblock: null,

	// don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493
	quirksmodeOffsetHack: 4,

	// class name of the message block
	blockMsgClass: 'blockMsg'
};

// private data and functions follow...

var pageBlock = null;
var pageBlockEls = [];

function install(el, opts) {
	var full = (el == window);
	var msg = opts && opts.message !== undefined ? opts.message : undefined;
	opts = $.extend({}, $.blockUI.defaults, opts || {});
	opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {});
	var css = $.extend({}, $.blockUI.defaults.css, opts.css || {});
	var themedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS || {});
	msg = msg === undefined ? opts.message : msg;

	// remove the current block (if there is one)
	if (full && pageBlock)
		remove(window, {fadeOut:0});

	// if an existing element is being used as the blocking content then we capture
	// its current place in the DOM (and current display style) so we can restore
	// it when we unblock
	if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) {
		var node = msg.jquery ? msg[0] : msg;
		var data = {};
		$(el).data('blockUI.history', data);
		data.el = node;
		data.parent = node.parentNode;
		data.display = node.style.display;
		data.position = node.style.position;
		if (data.parent)
			data.parent.removeChild(node);
	}

	$(el).data('blockUI.onUnblock', opts.onUnblock);
	var z = opts.baseZ;

	// blockUI uses 3 layers for blocking, for simplicity they are all used on every platform;
	// layer1 is the iframe layer which is used to supress bleed through of underlying content
	// layer2 is the overlay layer which has opacity and a wait cursor (by default)
	// layer3 is the message content that is displayed while blocking

	var lyr1 = ($.browser.msie || opts.forceIframe) 
		? $('<iframe class="blockUI" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="'+opts.iframeSrc+'"></iframe>')
		: $('<div class="blockUI" style="display:none"></div>');
	
	var lyr2 = opts.theme 
	 	? $('<div class="blockUI blockOverlay ui-widget-overlay" style="z-index:'+ (z++) +';display:none"></div>')
	 	: $('<div class="blockUI blockOverlay" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>');

	var lyr3, s;
	if (opts.theme && full) {
		s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:fixed">' +
				'<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || '&nbsp;')+'</div>' +
				'<div class="ui-widget-content ui-dialog-content"></div>' +
			'</div>';
	}
	else if (opts.theme) {
		s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:absolute">' +
				'<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || '&nbsp;')+'</div>' +
				'<div class="ui-widget-content ui-dialog-content"></div>' +
			'</div>';
	}
	else if (full) {
		s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage" style="z-index:'+(z+10)+';display:none;position:fixed"></div>';
	}			 
	else {
		s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement" style="z-index:'+(z+10)+';display:none;position:absolute"></div>';
	}
	lyr3 = $(s);

	// if we have a message, style it
	if (msg) {
		if (opts.theme) {
			lyr3.css(themedCSS);
			lyr3.addClass('ui-widget-content');
		}
		else 
			lyr3.css(css);
	}

	// style the overlay
	if (!opts.theme && (!opts.applyPlatformOpacityRules || !($.browser.mozilla && /Linux/.test(navigator.platform))))
		lyr2.css(opts.overlayCSS);
	lyr2.css('position', full ? 'fixed' : 'absolute');

	// make iframe layer transparent in IE
	if ($.browser.msie || opts.forceIframe)
		lyr1.css('opacity',0.0);

	//$([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el);
	var layers = [lyr1,lyr2,lyr3], $par = full ? $('body') : $(el);
	$.each(layers, function() {
		this.appendTo($par);
	});
	
	if (opts.theme && opts.draggable && $.fn.draggable) {
		lyr3.draggable({
			handle: '.ui-dialog-titlebar',
			cancel: 'li'
		});
	}

	// ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling)
	var expr = setExpr && (!$.boxModel || $('object,embed', full ? null : el).length > 0);
	if (ie6 || expr) {
		// give body 100% height
		if (full && opts.allowBodyStretch && $.boxModel)
			$('html,body').css('height','100%');

		// fix ie6 issue when blocked element has a border width
		if ((ie6 || !$.boxModel) && !full) {
			var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth');
			var fixT = t ? '(0 - '+t+')' : 0;
			var fixL = l ? '(0 - '+l+')' : 0;
		}

		// simulate fixed position
		$.each([lyr1,lyr2,lyr3], function(i,o) {
			var s = o[0].style;
			s.position = 'absolute';
			if (i < 2) {
				full ? s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"')
					 : s.setExpression('height','this.parentNode.offsetHeight + "px"');
				full ? s.setExpression('width','jQuery.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"')
					 : s.setExpression('width','this.parentNode.offsetWidth + "px"');
				if (fixL) s.setExpression('left', fixL);
				if (fixT) s.setExpression('top', fixT);
			}
			else if (opts.centerY) {
				if (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"');
				s.marginTop = 0;
			}
			else if (!opts.centerY && full) {
				var top = (opts.css && opts.css.top) ? parseInt(opts.css.top) : 0;
				var expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"';
				s.setExpression('top',expression);
			}
		});
	}

	// show the message
	if (msg) {
		if (opts.theme)
			lyr3.find('.ui-widget-content').append(msg);
		else
			lyr3.append(msg);
		if (msg.jquery || msg.nodeType)
			$(msg).show();
	}

	if (($.browser.msie || opts.forceIframe) && opts.showOverlay)
		lyr1.show(); // opacity is zero
	if (opts.fadeIn) {
		var cb = opts.onBlock ? opts.onBlock : noOp;
		var cb1 = (opts.showOverlay && !msg) ? cb : noOp;
		var cb2 = msg ? cb : noOp;
		if (opts.showOverlay)
			lyr2._fadeIn(opts.fadeIn, cb1);
		if (msg)
			lyr3._fadeIn(opts.fadeIn, cb2);
	}
	else {
		if (opts.showOverlay)
			lyr2.show();
		if (msg)
			lyr3.show();
		if (opts.onBlock)
			opts.onBlock();
	}

	// bind key and mouse events
	bind(1, el, opts);

	if (full) {
		pageBlock = lyr3[0];
		pageBlockEls = $(':input:enabled:visible',pageBlock);
		if (opts.focusInput)
			setTimeout(focus, 20);
	}
	else
		center(lyr3[0], opts.centerX, opts.centerY);

	if (opts.timeout) {
		// auto-unblock
		var to = setTimeout(function() {
			full ? $.unblockUI(opts) : $(el).unblock(opts);
		}, opts.timeout);
		$(el).data('blockUI.timeout', to);
	}
};

// remove the block
function remove(el, opts) {
	var full = (el == window);
	var $el = $(el);
	var data = $el.data('blockUI.history');
	var to = $el.data('blockUI.timeout');
	if (to) {
		clearTimeout(to);
		$el.removeData('blockUI.timeout');
	}
	opts = $.extend({}, $.blockUI.defaults, opts || {});
	bind(0, el, opts); // unbind events

	if (opts.onUnblock === null) {
		opts.onUnblock = $el.data('blockUI.onUnblock');
		$el.removeData('blockUI.onUnblock');
	}

	var els;
	if (full) // crazy selector to handle odd field errors in ie6/7
		els = $('body').children().filter('.blockUI').add('body > .blockUI');
	else
		els = $('.blockUI', el);

	if (full)
		pageBlock = pageBlockEls = null;

	if (opts.fadeOut) {
		els.fadeOut(opts.fadeOut);
		setTimeout(function() { reset(els,data,opts,el); }, opts.fadeOut);
	}
	else
		reset(els, data, opts, el);
};

// move blocking element back into the DOM where it started
function reset(els,data,opts,el) {
	els.each(function(i,o) {
		// remove via DOM calls so we don't lose event handlers
		if (this.parentNode)
			this.parentNode.removeChild(this);
	});

	if (data && data.el) {
		data.el.style.display = data.display;
		data.el.style.position = data.position;
		if (data.parent)
			data.parent.appendChild(data.el);
		$(el).removeData('blockUI.history');
	}

	if (typeof opts.onUnblock == 'function')
		opts.onUnblock(el,opts);
};

// bind/unbind the handler
function bind(b, el, opts) {
	var full = el == window, $el = $(el);

	// don't bother unbinding if there is nothing to unbind
	if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked')))
		return;
	if (!full)
		$el.data('blockUI.isBlocked', b);

	// don't bind events when overlay is not in use or if bindEvents is false
	if (!opts.bindEvents || (b && !opts.showOverlay)) 
		return;

	// bind anchors and inputs for mouse and key events
	var events = 'mousedown mouseup keydown keypress';
	b ? $(document).bind(events, opts, handler) : $(document).unbind(events, handler);

// former impl...
//	   var $e = $('a,:input');
//	   b ? $e.bind(events, opts, handler) : $e.unbind(events, handler);
};

// event handler to suppress keyboard/mouse events when blocking
function handler(e) {
	// allow tab navigation (conditionally)
	if (e.keyCode && e.keyCode == 9) {
		if (pageBlock && e.data.constrainTabKey) {
			var els = pageBlockEls;
			var fwd = !e.shiftKey && e.target === els[els.length-1];
			var back = e.shiftKey && e.target === els[0];
			if (fwd || back) {
				setTimeout(function(){focus(back)},10);
				return false;
			}
		}
	}
	var opts = e.data;
	// allow events within the message content
	if ($(e.target).parents('div.' + opts.blockMsgClass).length > 0)
		return true;

	// allow events for content that is not being blocked
	return $(e.target).parents().children().filter('div.blockUI').length == 0;
};

function focus(back) {
	if (!pageBlockEls)
		return;
	var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0];
	if (e)
		e.focus();
};

function center(el, x, y) {
	var p = el.parentNode, s = el.style;
	var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth');
	var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth');
	if (x) s.left = l > 0 ? (l+'px') : '0';
	if (y) s.top  = t > 0 ? (t+'px') : '0';
};

function sz(el, p) {
	return parseInt($.css(el,p))||0;
};


})(jQuery);


jQuery.tableDnD = {
    /** Keep hold of the current table being dragged */
    currentTable : null,
    /** Keep hold of the current drag object if any */
    dragObject: null,
    /** The current mouse offset */
    mouseOffset: null,
    /** Remember the old value of Y so that we don't do too much processing */
    oldY: 0,

    /** Actually build the structure */
    build: function(options) {
        // Set up the defaults if any

        this.each(function() {
            // This is bound to each matching table, set up the defaults and override with user options
            this.tableDnDConfig = jQuery.extend({
                onDragStyle: null,
                onDropStyle: null,
				// Add in the default class for whileDragging
				onDragClass: "tDnD_whileDrag",
                onDrop: null,
                onDragStart: null,
                scrollAmount: 5,
				serializeRegexp: /[^\-]*$/, // The regular expression to use to trim row IDs
				serializeParamName: null, // If you want to specify another parameter name instead of the table ID
                dragHandle: null // If you give the name of a class here, then only Cells with this class will be draggable
            }, options || {});
            // Now make the rows draggable
            jQuery.tableDnD.makeDraggable(this);
        });

        // Now we need to capture the mouse up and mouse move event
        // We can use bind so that we don't interfere with other event handlers
        jQuery(document)
            .bind('mousemove', jQuery.tableDnD.mousemove)
            .bind('mouseup', jQuery.tableDnD.mouseup);

        // Don't break the chain
        return this;
    },

    /** This function makes all the rows on the table draggable apart from those marked as "NoDrag" */
    makeDraggable: function(table) {
        var config = table.tableDnDConfig;
		if (table.tableDnDConfig.dragHandle) {
			// We only need to add the event to the specified cells
			var cells = jQuery("td."+table.tableDnDConfig.dragHandle, table);
			cells.each(function() {
				// The cell is bound to "this"
                jQuery(this).mousedown(function(ev) {
                    jQuery.tableDnD.dragObject = this.parentNode;
                    jQuery.tableDnD.currentTable = table;
                    jQuery.tableDnD.mouseOffset = jQuery.tableDnD.getMouseOffset(this, ev);
                    if (config.onDragStart) {
                        // Call the onDrop method if there is one
                        config.onDragStart(table, this);
                    }
                    return false;
                });
			})
		} else {
			// For backwards compatibility, we add the event to the whole row
	        var rows = jQuery("tr", table); // get all the rows as a wrapped set
	        rows.each(function() {
				// Iterate through each row, the row is bound to "this"
				var row = jQuery(this);
				if (! row.hasClass("nodrag")) {
	                row.mousedown(function(ev) {
	                    if (ev.target.tagName == "TD") {
	                        jQuery.tableDnD.dragObject = this;
	                        jQuery.tableDnD.currentTable = table;
	                        jQuery.tableDnD.mouseOffset = jQuery.tableDnD.getMouseOffset(this, ev);
	                        if (config.onDragStart) {
	                            // Call the onDrop method if there is one
	                            config.onDragStart(table, this);
	                        }
	                        return false;
	                    }
	                }).css("cursor", "move"); // Store the tableDnD object
				}
			});
		}
	},

	updateTables: function() {
		this.each(function() {
			// this is now bound to each matching table
			if (this.tableDnDConfig) {
				jQuery.tableDnD.makeDraggable(this);
			}
		})
	},

    /** Get the mouse coordinates from the event (allowing for browser differences) */
    mouseCoords: function(ev){
        if(ev.pageX || ev.pageY){
            return {x:ev.pageX, y:ev.pageY};
        }
        return {
            x:ev.clientX + document.body.scrollLeft - document.body.clientLeft,
            y:ev.clientY + document.body.scrollTop  - document.body.clientTop
        };
    },

    /** Given a target element and a mouse event, get the mouse offset from that element.
        To do this we need the element's position and the mouse position */
    getMouseOffset: function(target, ev) {
        ev = ev || window.event;

        var docPos    = this.getPosition(target);
        var mousePos  = this.mouseCoords(ev);
        return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y};
    },

    /** Get the position of an element by going up the DOM tree and adding up all the offsets */
    getPosition: function(e){
        var left = 0;
        var top  = 0;
        /** Safari fix -- thanks to Luis Chato for this! */
        if (e.offsetHeight == 0) {
            /** Safari 2 doesn't correctly grab the offsetTop of a table row
            this is detailed here:
            http://jacob.peargrove.com/blog/2006/technical/table-row-offsettop-bug-in-safari/
            the solution is likewise noted there, grab the offset of a table cell in the row - the firstChild.
            note that firefox will return a text node as a first child, so designing a more thorough
            solution may need to take that into account, for now this seems to work in firefox, safari, ie */
            e = e.firstChild; // a table cell
        }

        while (e.offsetParent){
            left += e.offsetLeft;
            top  += e.offsetTop;
            e     = e.offsetParent;
        }

        left += e.offsetLeft;
        top  += e.offsetTop;

        return {x:left, y:top};
    },

    mousemove: function(ev) {
        if (jQuery.tableDnD.dragObject == null) {
            return;
        }

        var dragObj = jQuery(jQuery.tableDnD.dragObject);
        var config = jQuery.tableDnD.currentTable.tableDnDConfig;
        var mousePos = jQuery.tableDnD.mouseCoords(ev);
        var y = mousePos.y - jQuery.tableDnD.mouseOffset.y;
        //auto scroll the window
	    var yOffset = window.pageYOffset;
	 	if (document.all) {
	        // Windows version
	        //yOffset=document.body.scrollTop;
	        if (typeof document.compatMode != 'undefined' &&
	             document.compatMode != 'BackCompat') {
	           yOffset = document.documentElement.scrollTop;
	        }
	        else if (typeof document.body != 'undefined') {
	           yOffset=document.body.scrollTop;
	        }

	    }
		    
		if (mousePos.y-yOffset < config.scrollAmount) {
	    	window.scrollBy(0, -config.scrollAmount);
	    } else {
            var windowHeight = window.innerHeight ? window.innerHeight
                    : document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight;
            if (windowHeight-(mousePos.y-yOffset) < config.scrollAmount) {
                window.scrollBy(0, config.scrollAmount);
            }
        }


        if (y != jQuery.tableDnD.oldY) {
            // work out if we're going up or down...
            var movingDown = y > jQuery.tableDnD.oldY;
            // update the old value
            jQuery.tableDnD.oldY = y;
            // update the style to show we're dragging
			if (config.onDragClass) {
				dragObj.addClass(config.onDragClass);
			} else {
	            dragObj.css(config.onDragStyle);
			}
            // If we're over a row then move the dragged row to there so that the user sees the
            // effect dynamically
            var currentRow = jQuery.tableDnD.findDropTargetRow(dragObj, y);
            if (currentRow) {
                // TODO worry about what happens when there are multiple TBODIES
                if (movingDown && jQuery.tableDnD.dragObject != currentRow) {
                    jQuery.tableDnD.dragObject.parentNode.insertBefore(jQuery.tableDnD.dragObject, currentRow.nextSibling);
                } else if (! movingDown && jQuery.tableDnD.dragObject != currentRow) {
                    jQuery.tableDnD.dragObject.parentNode.insertBefore(jQuery.tableDnD.dragObject, currentRow);
                }
            }
        }

        return false;
    },

    /** We're only worried about the y position really, because we can only move rows up and down */
    findDropTargetRow: function(draggedRow, y) {
        var rows = jQuery.tableDnD.currentTable.rows;
        for (var i=0; i<rows.length; i++) {
            var row = rows[i];
            var rowY    = this.getPosition(row).y;
            var rowHeight = parseInt(row.offsetHeight)/2;
            if (row.offsetHeight == 0) {
                rowY = this.getPosition(row.firstChild).y;
                rowHeight = parseInt(row.firstChild.offsetHeight)/2;
            }
            // Because we always have to insert before, we need to offset the height a bit
            if ((y > rowY - rowHeight) && (y < (rowY + rowHeight))) {
                // that's the row we're over
				// If it's the same as the current row, ignore it
				if (row == draggedRow) {return null;}
                var config = jQuery.tableDnD.currentTable.tableDnDConfig;
                if (config.onAllowDrop) {
                    if (config.onAllowDrop(draggedRow, row)) {
                        return row;
                    } else {
                        return null;
                    }
                } else {
					// If a row has nodrop class, then don't allow dropping (inspired by John Tarr and Famic)
                    var nodrop = jQuery(row).hasClass("nodrop");
                    if (! nodrop) {
                        return row;
                    } else {
                        return null;
                    }
                }
                return row;
            }
        }
        return null;
    },

    mouseup: function(e) {
        if (jQuery.tableDnD.currentTable && jQuery.tableDnD.dragObject) {
            var droppedRow = jQuery.tableDnD.dragObject;
            var config = jQuery.tableDnD.currentTable.tableDnDConfig;
            // If we have a dragObject, then we need to release it,
            // The row will already have been moved to the right place so we just reset stuff
			if (config.onDragClass) {
	            jQuery(droppedRow).removeClass(config.onDragClass);
			} else {
	            jQuery(droppedRow).css(config.onDropStyle);
			}
            jQuery.tableDnD.dragObject   = null;
            if (config.onDrop) {
                // Call the onDrop method if there is one
                config.onDrop(jQuery.tableDnD.currentTable, droppedRow);
            }
            jQuery.tableDnD.currentTable = null; // let go of the table too
        }
    },

    serialize: function() {
        if (jQuery.tableDnD.currentTable) {
            return jQuery.tableDnD.serializeTable(jQuery.tableDnD.currentTable);
        } else {
            return "Error: No Table id set, you need to set an id on your table and every row";
        }
    },

	serializeTable: function(table) {
        var result = "";
        var tableId = table.id;
        var rows = table.rows;
        for (var i=0; i<rows.length; i++) {
            if (result.length > 0) result += "&";
            var rowId = rows[i].id;
            if (rowId && rowId && table.tableDnDConfig && table.tableDnDConfig.serializeRegexp) {
                rowId = rowId.match(table.tableDnDConfig.serializeRegexp)[0];
            }

            result += tableId + '[]=' + rowId;
        }
        return result;
	},

	serializeTables: function() {
        var result = "";
        this.each(function() {
			// this is now bound to each matching table
			result += jQuery.tableDnD.serializeTable(this);
		});
        return result;
    }

}

jQuery.fn.extend(
	{
		tableDnD : jQuery.tableDnD.build,
		tableDnDUpdate : jQuery.tableDnD.updateTables,
		tableDnDSerialize: jQuery.tableDnD.serializeTables
	}
);
