
var Attributes = new Array(); //Loaded by pwPage.ClientSideAttributesAndCategories()
var Alternatives = new Array(); 
var DebugStatus;
var sDecisionTableStartRow = 'pwDecisionStart';
var sDecisionTableEndRow = 'pwDecisionEnd';

//Make innerText work in Mozilla
function GetInnerText(o) {
	return o.innerHTML.replace(/&lt;[^&gt;]+&gt;/g,"");
} //GetInnerText

function SetInnerText(o, s) {
	var parsedText = document.createTextNode(s);
	o.innerHTML = "";
	o.appendChild(parsedText);
} //SetInnerText

function htmlEncode(s) {
    return s.toString().replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;");
} //htmlEncode

function crBr(s) {
	return s.replace(/\n/g, "<br />");
} //crBr

function Attribute(Symbol, Title) {
	this.Symbol = Symbol;
	this.Title = Title;
	this.Categories = new Array();
} //Attribute

function Category(Symbol, Title, Score, ScoreNormalised) {
	this.Symbol = Symbol;
	this.Title = Title;
	this.Score = Score;
	this.ScoreNormalised = ScoreNormalised;
} //Category

function Alternative(Title, ID) {
	this.Title = Title;
	this.ID = ID;
	this.Attributes = new Array();
} //Alternative

function ShowStats(e) {
	StandardiseEvent(e);
	var w = window.open('Stats.aspx?random=' + Math.random(), '_pwStats', 'channelmode=no, directories=no, fullscreen=no, location=no, menubar=no, resizable=yes, scrollbars=yes, status=no, titlebar=yes, tooblar=no');
	w.focus();
	e.preventDefault();
} //ShowStats

function windowPageYOffset() {
    if (typeof(window.pageYOffset) != "undefined") 
        return window.pageYOffset;
    else if (document.documentElement && document.documentElement.scrollTop)
        return document.documentElement.scrollTop;        
    else if (document.body)
        return document.body.scrollTop;
}

function windowWidth() {
    if (typeof(window.innerWidth) != "undefined")
        return window.innerWidth;
    else 
        return document.body.clientWidth;
}

function StandardiseEvent(e) {
//from http://www.mozillazine.org/talkback.html?article=2433
    if (!e.stopPropagation) {
        e.stopPropagation = new Function('this.cancelBubble = true');
    }
    
    // if (!e.pageY) {
	//	e.pageY = new Function('return document.body.scrollTop + this.clientY');
    //}

    //if (!e.pageX) {
	//	e.pageX = new Function('return document.body.scrollLeft + this.clientX');
    //}

    if (!e.preventDefault) {
        e.preventDefault = new Function('this.returnValue = false');
    } 

    if (typeof e.layerX == 'undefined' && typeof e.offsetX == 'number') {
        e.layerX = e.offsetX;
        e.layerY = e.offsetY;
    }

    if (!e.target && e.srcElement) {
        e.target = e.srcElement;
        if (e.type == 'onmouseout') {
            e.relatedTarget = e.toElement;
        } else if (e.type == 'onmouseover') {
            e.relatedTarget = e.fromElement;
        }
    }
} //StandardiseEvent

function FindChildName(parentObject, childName, n, nsofar) {
	//n-1 is how many tags to skip of this name
	//don't pass nsofar

	if (!n) 
		n = 1;

	if (!nsofar) {
		nsofar = new Object();
		nsofar.num = 0;
	}

	var o = parentObject;	
	if (!o) 
		return null;
	
	if (o.name == childName) {
		nsofar.num++;
		if (nsofar.num == n) 
			return o;
	}
	
	for (var i=0; i < parentObject.childNodes.length; i++) {
		o = FindChildName(parentObject.childNodes[i], childName, n, nsofar);
		if (o)
			return o;
	}		

	return null;
} //FindChildName

function FindChildTagName(parentObject, childTagName, n, nsofar) {
	//n-1 is how many tags to skip of this name
	//don't pass nsofar

	if (!n)
		n = 1;

	if (!nsofar) {
		nsofar = new Object();
		nsofar.num = 0;
	}
		
	var o = parentObject;	

	if (!o.tagName) 
		return null;

	if (o.tagName.toUpperCase() == childTagName.toUpperCase()) {
		nsofar.num++;
		if (nsofar.num == n) 
			return o;
	}
	
	for (var i=0; i < parentObject.childNodes.length; i++) {
		o = FindChildTagName(parentObject.childNodes[i], childTagName, n, nsofar);
		if (o)
			return o;
	}		
	return null;
} //FindChildTagName

function FindParentTagName(childObject, parentTagName, n) {
	//n-1 is how many tags to skip of this name, e.g. finding td of outer table containing a toolset

	if (!n) 
		n = 1;
	var nsofar = 0;
	var o = childObject;		

	//if (!o.tagName) 
	//	return null;

	parentTagName = parentTagName.toUpperCase();

	while (true) {
		if (o.tagName) {
			if (o.tagName.toUpperCase() == parentTagName) {
				nsofar++;
				if (nsofar == n) {
					return o;
				}
			}
		}
		if (!o.parentNode) {
			return null;
		}
		o = o.parentNode;		
	}

} //FindParentTagName

function DeleteAllRowsFromTable(tbl) {
	while (tbl.rows.length > 0)
		tbl.deleteRow(0);
} //DeleteAllRowsFromTable

function BoldItalicString(s) {
	var t = s.replace(/\[strong\]/g, "<strong>");
	t = t.replace(/\[em\]/g, "<em>");
	t = t.replace(/\[\/strong\]/g, "</strong>");
	t = t.replace(/\[\/em\]/g, "</em>");
	return t;
} //BoldItalicString

function MakeAlternativeHtml(s) {
	var n = s.length;
	var degree = GetDegreeOfAlternative(s);	
	
	var sh = "";
	var upto = 0; //attribute
	for (var i=0; i<n; i++) {
		if (s.charAt(i) != sEmptyCategory) {
			upto++;

			var jl = s.charCodeAt(i) - '0'.charCodeAt(0);
			
			a = Attributes[i];
			cl = a.Categories[jl];

			var classPrefix;
			if (upto == 1) 
				classPrefix = "Top";
			else if (upto == degree) 
				classPrefix = "Bottom";
			else 
				classPrefix = "Middle";
		
			//attribute text
			sh += "<tr>";
			sh += '<td class="' + classPrefix + '1a">' + a.Symbol;
			if (upto == 1)
				sh += '<span style="display:none">' + sDecisionTableStartRow + "</span>";
			sh += '</td>';
			sh += '<td class="' + classPrefix + '1b">' + BoldItalicString(a.Title) + '</td>';				
			sh += "</tr>";				
					
			//category text
			sh += "<tr>";
			sh += '<td class="' + classPrefix + '2a">&nbsp;</td>';
			sh += '<td class="' + classPrefix + '2b">' + BoldItalicString(cl.Title);
			if (upto == degree)
				sh += '<span style="display:none">' + sDecisionTableEndRow + "</span>";
			sh += '</td>';
			sh += "</tr>";				
		} //if not empty
	} // for i
	return sh;	
} //MakeAlternativeHtml

//returns html of trs to insert into table html - must do this instead of dom for ie5/mac
function MakeDecisionHtml(s, bIncludeCategorySymbols, bIncludePoints, bSuppressAttributeSymbols) {
	var n = Math.floor(s.length/2);
	var left = s.substr(0, n);
	var op = s.charAt(n);
	var right = s.substr(n+1, n);
	var degree = GetDegreeOfAlternative(left);	
	
	//make the operator to go in the middle, i.e. <, >, = or or
	var sOperatorTDHtml = '<td rowspan="' + degree*2 + '"'
	if (op == sVsInternal) {
		sOperatorTDHtml += ' class="VS">' 
			+ sVs;
	}
	else {
		sOperatorTDHtml += ' class="Operator">' 
			+ (op == '<' ? '&lt;' : (op == '>' ? '&gt;' : op));
	}
	sOperatorTDHtml += '</td>'
		
	var sh = "";
	var upto = 0; //attribute
	for (var i=0; i<n; i++) {
		if (left.charAt(i) != sEmptyCategory) {
			upto++;

			var jl = left.charCodeAt(i) - '0'.charCodeAt(0);
			var jr = right.charCodeAt(i) - '0'.charCodeAt(0);
			
			a = Attributes[i];
			cl = a.Categories[jl];
			cr = a.Categories[jr];

			var classPrefix;
			if (upto == 1) 
				classPrefix = "Top";
			else if (upto == degree) 
				classPrefix = "Bottom";
			else 
				classPrefix = "Middle";
		
			//attribute text
			sh += "<tr>";
			sh += '<td class="' + classPrefix + '1a">' + (bSuppressAttributeSymbols ? "&nbsp;&bull;" : a.Symbol);
			if (upto == 1)
				sh += '<span style="display:none">' + sDecisionTableStartRow + "</span>";
			sh += '</td>';
			sh += '<td class="' + classPrefix + '1b">' + BoldItalicString(a.Title) + '</td>';
			if (upto == 1)
				sh += sOperatorTDHtml;
			sh += '<td class="' + classPrefix + '1a">' + (bSuppressAttributeSymbols ? "&nbsp;&bull;" : a.Symbol) + '</td>';
			sh += '<td class="' + classPrefix + '1b">' + BoldItalicString(a.Title) + '</td>';
			sh += "</tr>";		
					
			//category text
			sh += "<tr>";
			//left category
			sh += '<td class="' + classPrefix + '2a">';
			if (!bIncludeCategorySymbols)
				sh += '&nbsp;';
			else
				sh += cl.Symbol;
			sh += '</td>';
			sh += '<td class="' + classPrefix + '2b">';
			if (!bIncludePoints) {
				sh += BoldItalicString(cl.Title);
			}
			else {
				sh += '<table width="100%" cellspacing="0" cellpadding="0" border="0"><tr><td>';
				sh += BoldItalicString(cl.Title);
				sh += '</td><td class="CategoryScore">';
				sh += cl.ScoreNormalised;
				sh += "</td></tr></table>";
			}
			
			//right category
			sh += '<td class="' + classPrefix + '2a">';
			if (!bIncludeCategorySymbols)
				sh += '&nbsp;';
			else
				sh += cr.Symbol;
			sh += '</td>';		
			sh += '<td class="' + classPrefix + '2b">';
			if (!bIncludePoints) {
				sh += BoldItalicString(cr.Title);
			}
			else {
				sh += '<table width="100%" cellspacing="0" cellpadding="0" border="0"><tr><td>';
				sh += BoldItalicString(cr.Title);
				sh += '</td><td class="CategoryScore">';
				sh += cr.ScoreNormalised;
				sh += "</td></tr></table>";
			}
			
			//if (upto == degree)
			//	sh += '<span style="display:none">' + sDecisionTableEndRow + "</span>";
			sh += '</td>';
			sh += "</tr>";				
		} //if not empty
	} // for i
	sh += '<tr class="blankRowForWebKitWorkaround"><td></td><td></td><td></td><td></td><td><span style="display:none">' + sDecisionTableEndRow + '</span></td></tr>';
	return sh;	
} //MakeDecisionHtml

function DisplayDecision(div, s, bSuppressAttributeSymbols) {
	Note('Display decision(' + s + ')');
	var n = Math.floor(s.length/2);
	var left = s.substr(0, n);
	var degree = GetDegreeOfAlternative(left);

	ResetDecisionTable(div, degree, MakeDecisionHtml(s, false, false, bSuppressAttributeSymbols));	
} //DisplayDecision

function ResetDecisionTable(div, degree, sRowsHtml) {
	//this is all rather clumsy compared with using the DOM
	//but it is the only way to make it go with IE/Mac, and 
	//Safari with rowspans.
	
	var s = div.innerHTML;
	var iStartOfStart = s.indexOf(sDecisionTableStartRow);
	iStartOfStart = s.lastIndexOf('<', iStartOfStart-1); //skip two close angle brackets to complete row
	iStartOfStart = s.lastIndexOf('<', iStartOfStart-1); 
	iStartOfStart = s.lastIndexOf('<', iStartOfStart-1); 
	var s2 = s.substring(0, iStartOfStart);

	s2 += sRowsHtml;
	
	var iEndOfEnd = s.indexOf(sDecisionTableEndRow);
	iEndOfEnd = s.indexOf('>', iEndOfEnd+1); //skip two open angle brackets to complete row
	iEndOfEnd = s.indexOf('>', iEndOfEnd+1); 
	iEndOfEnd = s.indexOf('>', iEndOfEnd+1); 

	s2 += s.substr(iEndOfEnd+1);
	
	div.innerHTML = s2;	
} //ResetDecisionTable

function GetDegreeOfAlternative(alt) {
	var degree = 0;
	for (var i=0; i<alt.length; i++) {
		var j = alt.charAt(i);
		if (j != sEmptyCategory) 
			degree++;
	}
	
	return degree;
} //GetDegreeOfAlternative

function DisplayAlternative(div, s) {
	Note('Display decision(' + s + ')');
	var n = Math.floor(s.length/2);
	var left = s.substr(0, n);
	var degree = GetDegreeOfAlternative(left);
		
	ResetDecisionTable(div, degree, MakeAlternativeHtml(s));	
} //DisplayAlternative


function Note(s) {
	if (DebugStatus != null)
		DebugStatus.innerHTML += "<br />" + s;
} //Note

function NoteText(s) {
	if (DebugStatus != null)
		DebugStatus.innerText = s;
} //NoteText

function pwInit() {
	DebugStatus = document.getElementById("DebugStatus");
	Note("pwInit");
} //pwInit

function PressButton(btn) {
	var cssClass = btn.className;
	cssClass = cssClass.replace("Pressed", ""); //so we can't double up
	cssClass += "Pressed";
	btn.className = cssClass;
} //PressButton

function UnpressButton(btn) {
	var cssClass = btn.className;
	cssClass = cssClass.replace("Pressed", "");
	btn.className = cssClass;	
} //UnpressButton

function btnHelpToggle_Click(e) {
	StandardiseEvent(e);
	e.preventDefault(); //placed here so that if Safari error, we don't submit
	
	var tdHelp = document.getElementById("tblBodyHelpTD");		
	var inpHelp = document.getElementsByName("hiddenHelpEnabled")[0];
	var bEnabled = Number(inpHelp.value);
	var btn = e.target;
	
	var className = tdHelp.className.replace("Hidden", "");	
	if (bEnabled == 1) {
		className = className + "Hidden";
		UnpressButton(btn);
		bEnabled = 0;
	}
	else {
		PressButton(btn);
		bEnabled = 1;
	}
	
	tdHelp.className = className;			
	inpHelp.value = bEnabled;		
	setCookie("btnHelpToggle", bEnabled);
	
	e.preventDefault(); 
} //btnHelpToggle_Click()

function getCookie(sName) {
  var aCookie = document.cookie.split("; ");
  for (var i=0; i < aCookie.length; i++) {
    var aCrumb = aCookie[i].split("=");
    if (sName == aCrumb[0]) 
      return unescape(aCrumb[1]);
  }
  return null;  //otherwise
} //getCookie

function delCookie(sName) {
  document.cookie = sName + "=; expires=Fri, 31 Dec 1999 23:59:59 GMT;";
} //delCookie

function setCookie(sName, sValue) {
	expires = new Date();
	expires.setTime(expires.getTime()+(15*24*60*60*1000)); //15 days
	document.cookie = sName + '=' + escape(sValue) + ";expires=" + expires.toUTCString();
} //setCookie

function ButtonMouseOver(e) {
	StandardiseEvent(e);
	var btn = FindParentTagName(e.target, "button"); //may find itself
	if (btn.tagName != "button")	   

	var className = btn.className;
	className = className.replace("Hover", "");
	className += "Hover";
	
	btn.className = className;
	e.stopPropagation();
} //ButtonMouseOver

function ButtonMouseOut(e) {
	StandardiseEvent(e);
	var btn = FindParentTagName(e.target, "button"); //may find itself

	var className = btn.className;
	className = className.replace("Hover", "");
	
	btn.className = className;
	e.stopPropagation();
} //ButtonMouseOut


function CommentExpander_OnClick(e) {
	StandardiseEvent(e);
	var img = e.target;
	var tbl = FindParentTagName(img, "TR");
	var ta = FindChildTagName(tbl, "TEXTAREA");
	
	if (ta.className == "DecisionCommentTextBoxExpanded") 
		ta.className = "DecisionCommentTextBoxCollapsed";
	else
		ta.className = "DecisionCommentTextBoxExpanded";
} //CommentExpander_OnClick

function MenuPopup(e) {
	StandardiseEvent(e);
	var btn = e.target;
	var mnu = document.getElementById("divMenuAccessoriesContainer");
	if (mnu.style.display == 'none') {
		mnu.style.display = 'block';
		btn.className = 'SubPageButtonPressed';
	}
	else {
		mnu.style.display = 'none';
		btn.className = 'SubPageButton';
	}
	mnu.style.marginTop = -(mnu.offsetHeight + 5) + "px";
	e.preventDefault();
} //MenuPopup

function MenuItem_OnMouseOver(e) {
	StandardiseEvent(e);	
	var mi = e.target;
	mi = FindParentTagName(mi, "DIV"); //needed for safari
	
	var className = mi.className;
	className = className.replace("Over", "");
	className += "Over";
	mi.className = className;
	e.stopPropagation();
} //MenuItem_OnMouseOver

function MenuItem_OnMouseOut(e) {
	StandardiseEvent(e);		
	var mi = e.target;
	mi = FindParentTagName(mi, "DIV"); //needed for safari
	
	var className = mi.className;
	className = className.replace("Over", "");
	mi.className = className;
} //MenuItem_OnMouseOut

function MenuItem_OnClick(e, js) {
	StandardiseEvent(e);		
	var mi = e.target;
	mi = FindParentTagName(mi, "DIV"); //needed for safari
	
	mi.className = "MenuItemClick";
	
	var mnu = document.getElementById("divMenuAccessoriesContainer");
	mnu.style.display = 'none';

	e.preventDefault();
	
	eval(js);	
} //MenuItem_OnClick

var isSuppressBusy = false;

function suppressBeeBusy() {
    isSuppressBusy = true;
}

function beebusy() {	
    if (isSuppressBusy) //to avoid spinning for buttons like export
    {
        isSuppressBusy = false;
        return;
    }
    
	var imgLogo = document.getElementById("imgLogoStill");	
	var iframeLogo = document.getElementById("iframeLogo");
	
	if (!imgLogo || !iframeLogo)
	    return;
	    
	imgLogo.style.display = "none";	
	iframeLogo.style.display = "inline";
	iframeLogo.src = "images/logoAnimated.htm";
	
	document.body.style.cursor = "progress !important"; //works in firefox but not ie
	window.status = "Connecting...";			
} //beebusy

function beeunbusy() {	
	var imgLogo = document.getElementById("imgLogoStill");	
	var iframeLogo = document.getElementById("iframeLogo");
	
	if (!imgLogo || !iframeLogo)
	    return;
	    
	imgLogo.style.display = "inline";	
	iframeLogo.style.display = "none";
	iframeLogo.src = "";
	
	document.body.style.cursor = '';
	window.status = "";			
} //beebusy

function HeaderLogoClick() {
	var divTitleBar = document.getElementById("HeaderTitleBar");
	var divWizard = document.getElementById("HeaderWizard");
	divTitleBar.style.display = 'none';
	divWizard.style.display = 'none';
} //HeaderLogoClick

function SortOrderPlay(e, sLstNamePrefix, id, numLsts) {
	StandardiseEvent(e);
	var lst = e.target;
	
	var oldPos = Number(lst.getAttribute('pwOldOrder'));				
	var newPos = Number(lst.value);

	if (oldPos == newPos)
		return;
						
	lst.setAttribute('pwOldOrder', newPos); //set a new old pos!
	
	var maxOptionValue = Number(lst.options[lst.options.length - 1].value);
	var min, max, offset;
	if (oldPos == 0) {
		min = newPos;
		max = maxOptionValue;
		offset = 1;
	}
	else if (newPos == 0) {
		min = oldPos;
		max = maxOptionValue;
		offset = -1;
	}
	else {
		min = Math.min(oldPos, newPos);
		max = Math.max(oldPos, newPos);
		offset = newPos > oldPos ? -1 : 1; //which way to move items in between
	}

	//is the new spot used?  if not, we won't have to change any other values
	var found = false;
	for (var i=0; i<numLsts; i++) {
		var l = document.getElementsByName(sLstNamePrefix + i)[0];
		var v = Number(l.value);
		if (v == newPos && i != id) {
			found = true;
			break;
		}
	}
	if (found || newPos == 0) { //we have to shuffle the others, or it will make it look prettier if we do			
		lastValue = -99;
		for (var i=0; i<numLsts; i++) {
			var l = document.getElementsByName(sLstNamePrefix + i)[0];
			var v = Number(l.value);
			if (v != 0 && v >= min && v <= max && i != id) {
				//if (lastValue != -99 && lastValue + offset != v) {
				//	break; //we've reached a hole in the series so stop
				//} //TBD - depends which way you're going - only affects lists that allow 'unknown' selections
				l.selectedIndex += offset;
				l.setAttribute('pwOldOrder', l.value);
				lastValue = v;
			}
		}
	}

	//before which row should the row be moved?
	var trAfter = null;
	var lowestAfter = 9999999;
	for (var i=0; i<numLsts; i++) {
		var l = document.getElementsByName(sLstNamePrefix + i)[0];
		var v = Number(l.value);
		if (v > newPos && v < lowestAfter) {
			lowestAfter = v;
			trAfter = FindParentTagName(l, "tr");
		}
	}		
	
	//swap the rows 
	var tr = FindParentTagName(lst, "tr");
	var tb = tr.parentNode;
	if (trAfter == null) {
		var trLast = tb.rows[tb.rows.length-1];
		tb.insertBefore(tr, trLast);
		tb.insertBefore(trLast, tr);
	}
	else {
		tb.insertBefore(tr, trAfter); 
	}	
} //SortOrderPlay

function FindChildSortOrderList(o, sLstNamePrefix, numLsts) {
	var l = null;
	for (var i=0; i<numLsts; i++) {
		l = FindChildName(o, sLstNamePrefix + i);
		if (l != null)
			break;
	}
	return l;
} //FindChildSortOrderList

function InvertSortOrder(sLstNamePrefix, numLsts, firstRowIndex) {
	if (numLsts < 2)
		return;
		
	var tbl = FindParentTagName(document.getElementsByName(sLstNamePrefix + '0')[0], "table");
	
	var halfWay = numLsts / 2.0;	
	for (var i=0; i<halfWay; i++) {
		var j = numLsts - i - 1;
		
		var tri = tbl.rows[firstRowIndex + i];
		var trj = tbl.rows[firstRowIndex + j];
		
		var li = FindChildSortOrderList(tri, sLstNamePrefix, numLsts);
		var lj = FindChildSortOrderList(trj, sLstNamePrefix, numLsts);
		
		//swap values
		var oldValueJ = lj.value;		
		lj.setAttribute('pwOldOrder', li.value);
		lj.value = li.value;
		li.setAttribute('pwOldOrder', oldValueJ);
		li.value = oldValueJ;
		
		//swap rows
		var triNext = tbl.rows[tri.rowIndex + 1];	
		var tb = tri.parentNode;	
		if (trj.rowIndex == tri.rowIndex + 1) {
			tb.insertBefore(trj, tri);			
		}
		else {
			tb.insertBefore(tri, trj);
			tb.insertBefore(trj, triNext);
		}
	} //i
} //InvertSortOrder


//functions the alternatives in a dilemma
function dtMouseOver(side) 
{
    dtHighlightAlternative(side, true);
}

function dtMouseOut(side) 
{                   
    dtHighlightAlternative(side, false);
}

function isDtAlternativeClassName(className) {
    var itIs = 
        className == "Top1a"
        || className == "Top1b"
        || className == "Top2a"
        || className == "Top2b"

        || className == "Middle1a"
        || className == "Middle1b"
        || className == "Middle2a"
        || className == "Middle2b"

        || className == "Bottom1a"
        || className == "Bottom1b"
        || className == "Bottom2a"
        || className == "Bottom2b"
        ;
    return itIs;
} //isDtAlternativeClassName

function dtHighlightAlternative(side, isOver) 
{
    var backgroundColour = isOver ? "#fe6" : ""; //background colour for highlighted alternative in a dilemma
    var borderColour = isOver ? "#84A765" : "";
    
    //s is 0 or 2 or 'e' and represents the side, or roughly speaking the column index
    //or 'e' for equal. given rowspans and colspans this is nasty and sneaky code 
    //rather than elegant code
    var increment;
    var s;
    if (side == 'e') 
    {
        s = 0;
        increment = 5; //process all columns
    } 
    else if (side == 'l') {
        s = 0;
        increment = 2; //just the left two
    }
    else {
        s = 2;
        increment = 3; //the right two, but set to 3 so it can handle a missing column due to rowSpan
    }
    
    var tbl = document.getElementById("DecisionTable");
    for (var i = 0; i < tbl.rows.length; i++) 
    {			    
        var tr = tbl.rows[i];
        for (var j = s; j < s + increment && j < tr.cells.length; j++) 
        {			         
	        var td = tr.cells[j];
	        if (isDtAlternativeClassName(td.className))
	        {
	            td.style.backgroundColor = backgroundColour;
	            td.style.borderColor = borderColour;
	            if (borderColour == "") {
    	            td.borderStyle = "solid";
	            }
	            else {
    	            td.borderStyle = "dashed";
	            }
	            td.style.cursor = 'pointer';
	        }
        }
    }    
} //dtHighlightAlternative

function dtMouseMain(e, isOver) {
	StandardiseEvent(e);
	var target = e.target;
    if (target.tagName.toLowerCase() == "td") 
    {
        if (isDtAlternativeClassName(target.className)) 
        {
            var side = target.cellIndex < 2 ? 'l' : 'r';
            dtHighlightAlternative(side, isOver);
        }
        e.stopPropagation();
    }
} //dtMouseMain

function dtMouseOverMain(e) {
    dtMouseMain(e, true);
}

function dtMouseOutMain(e) {
    dtMouseMain(e, false);
}

function dtClickMain(e, leftClick, rightClick) {
   	StandardiseEvent(e);
	var target = e.target;
    if (target.tagName.toLowerCase() == "td") 
    {
        if (isDtAlternativeClassName(target.className)) 
        {
            target.style.cursor = "progress";
            if (target.cellIndex < 2) 
            {   
                leftClick();
            }
            else 
            {
                rightClick();
            }            
        }
        e.stopPropagation();
    } 
} //dtClickMain

function closeMoreInfo() {
    var divMoreInfo = document.getElementById('divMoreInfo');
    divMoreInfo.style.display = 'none';    
}
function showMoreInfo() {
    var divMoreInfo = document.getElementById('divMoreInfo');
    divMoreInfo.style.display = 'block';  
}

function waterMark_OnFocus(e, waterMarkText, normalClassName)
{
    StandardiseEvent(e);
    txt = e.target;
    if (txt.value == waterMarkText)
    {
        txt.value = "";
        txt.className = normalClassName;
    }
}
function waterMark_OnBlur(e, waterMarkText, normalClassName, waterMarkClassName)
{
    StandardiseEvent(e);
    txt = e.target;
    if (txt.value == "") {
        txt.value = waterMarkText;
        txt.className = waterMarkClassName;
    }
    else {
        txt.className = normalClassName;
    }
}

function getAbsolutePosition(obj) 
{
    var pos = { left:0, top:0 };
	if (obj.offsetParent) 
	{
	    pos.left = obj.offsetLeft;
	    pos.top = obj.offsetTop;
		while ((obj = obj.offsetParent) != null) 
		{
		    pos.left += obj.offsetLeft + obj.scrollLeft;
		    pos.top += obj.offsetTop + obj.scrollTop;
		}
	}
	return pos;
}

function preventEnterOnKeyDown(e) 
{
    StandardiseEvent(e);
    if (e.keyCode == 13) 
    {
        e.preventDefault();
        e.stopPropagation();
        return false;
    }
}