// This file temporarily contains all of "qbw.js" to aid in the transition. It's at the bottom and will be coming out shortly.


/****************************************************************\
	All code copyright (c) 2003 Intuit Canada Ltd.
	Any unauthorized duplication or reuse of this code
	is a violation of applicable laws.
	Coded by Peter Harris, June 2003.
   ============================================================
		JavaScript Toolkit for HTML Help
   ------------------------------------------------------------
   This toolkit contains routines for the following features:
	== Environment detection scripts.
		- getTopicFilename()
		- getTopicPath()
		- getTopicCHM()
		- getTopicExternalPath()
		- getTopicSKUs()
		- getQuickBooksSKU()
	== Conditional text & variables.
		- conditionalText()
		- setHTMLvariable( obj )
		- fetchAttributeValue( obj, attName )
		- validateSKUs( str )
		- flattenSKUs( source )
		- addUnique( tArray, tElement )
		- string_caps( str, delim )
		- string_trim( str )
		- convertNumberToText( str )
		- convertThousandsToText( num )
		- convertDecadesToText( num )
		- convertNumberToOrdinal( str )
	== Expando text.
		- makeExpandoLink( linkObj, divID )
		- makeMultiExpandoLink( linkObj, divID )
		- makeExpando_DivPrep( divObj, startOpen )
		- expandoText()
		- multiExpandoText()
		- expandoMouseOver()
		- expandoMouseOut()
		- findExpandoDiv( anchorObj, divID )
		- resizeExpandoFrame( frameName )
		- expandoText_nestedFrames( divObj )
	== Popup windows.
		- MarkPopup()
		- Popup( targetURL )
		- FixURL( targetURL )
		- MakePopup( targetURL )
		- CreatePopup( targetURL )
		- FinishPopup( idx )
		- MovePopup( idx )
		- ResizePopup( idx )
		- qsortShrinkPopup( popupObj, constrainX, constrainY )
		- fixPopupTopicLinks( targetContainer )
		- ClosePopups()
		- ParentClosePopups()
	== User Feedback interface.
		- makeFeedbackAndHelpSupportLink( divObj )
		- feedback_yesno()
		- feedback_submit()
	== Miscellaneous.
		- qbcommand( param )
		- run_qbcommand( param )
		- qbcommand_redirect( param )
		- openURL( param )
		- QBURL( param )
		- displaytopic( param )
	== Internal Help for HTML extensions.
		- displaySKU()
		- displayAllSKUSs()
		- displayAllMods()
		- displayHelp()

   ------------------------------------------------------------
   _____________________ Version History ______________________
	Version 2.10 - August 28, 2003
	 - Create a multi-capacitant environment where the script can link to files whether from Perforce, from CHM, or from /updates.
	Version 2.07 - July 17, 2003
	 - Reformat all links to explicitly include the CHM file, if there is one. Fixes broken expando and popup links.
	Version 2.06 - July 10, 2003
	 - Hide <H?> title and <H4>Related Topics</H4> when in an expando window.
	Version 2.05 - July 9, 2003
	 - Made SKU.js an override to ActiveX detection; added <detectsku> tag for showing detected info.
	Version 2.04 - June 12, 2003
	 - Added automatic lightning bolt to irefs linking to "http://"
	Version 2.03 - June 10, 2003
	 - Added multisectional, radio button based expando tag <a multiexpando="basename">.
	Version 2.02 - June 9, 2003
	 - Extended Strata (and Flavours) handling:
		- All codes now in arrays QUICKBOOKS_ALLSTRATA, QUICKBOOKS_STRATAWITHFLAVOUR and QUICKBOOKS_ALLFLAVOURS
		- Added (+) operator; i.e. PRO+ = PRO, PREMIER, ENTERPRISE
		- Added (-) operator; i.e. PRO- = LITE, BASIC, PRO
		- Added (:) operator; i.e. PREMIER: = PREMIER but only with no Flavour
		- Added NOT() operator; i.e. skus="NOT(ENTERPRISE,CONTRACTOR)" = anything that isn't QBES or CONTRACTOR
	 - Added automatic tooltips for expando sections. Requires <html xmlns:qb> header tag.
	Version 2.01 - June 3, 2003
	 - Added new Flavors: PROFESSIONAL, WHOLESALE, RETAIL.
	 - Added text mods "2TEXT" and "ORDINAL" for working with numbers.
	 - Added rollovers for expando graphic.
	 - Added support for multiple expando graphics (use attribute icon="", e.g. <a expando icon="green">).
	Version 2.0 - June 2003
	 - Taking what we learned in v.1, this is a complete
	   rewrite, with lots of new and wonderful stuff.
	   For information about previous versions, check
	   qbw.js from Gecko/Godzilla.

\****************************************************************/
// The following variable contains the hardcoded date of the build
// of the CHM. The reason for this that the ".lastModified" property
// doesn't work inside HTMLHelp and we need to submit this for VOC data
// from inside HTML Help (embedded browser) for the 'yes'/'no' feedback.
// We should find an automated workaround for this manual fix, to avoid
// constant updating of this value. -MTK 2-20-2003
CHM_DATE	= "3,17,2004";
// ------------------------------------------------------------ \\
// ----- DEFINE ALL TEXT RESOURCES HERE (FOR TRANSLATION) ----- \\
TEXT = new Array();
TEXT["printericontext"] =		"Print Topic";
TEXT["tooltip_expando"] =		"Expand/Collapse Text";
TEXT["tooltip_multiexpando"] =		"Display details";



// Code added by Peter Harris 10/4/2006
//----- Define "apex" to be the topmost frame that doesn't throw a zone error -----\\
//----- Use it to replace "top" everywhere (specifically, Expando global tracking -----\\
var apex = window.self;
var tempObj = window.self;
while (tempObj) {
	apex = tempObj;
	tempObj = tempObj.parent;
	try {
		var tmp = tempObj.name;
	}
	catch (e) {
		tempObj = null;
	}
	if (apex == tempObj) {		// You've reached "top." without a zone crash. Stop looping.
		tempObj = null;
	}
}

// ============================================================ \\
// =====           GLOBAL ENVIRONMENT VARIABLES           ===== \\
// ============================================================ \\
// --  Any variable that is available for all functions, or  -- \\
// --  any function that's executed automatically when this  -- \\
// --  file is loaded, should be put here in this section.   -- \\

QUICKBOOKS_ALLFLAVOURS		= new Array("ACCOUNTANT", "CONTRACTOR", "NONPROFIT", "HEALTHCARE", "PROFESSIONAL", "WHOLESALE", "RETAIL");
QUICKBOOKS_ALLSTRATA		= new Array("LITE", "BASIC", "PRO", "PREMIER", "ENTERPRISE");
QUICKBOOKS_STRATAWITHFLAVOUR	= new Array("", "", "", "PREMIER", "ENTERPRISE");

TOPIC_FILENAME		= getTopicFilename();		// --  topicname.html 
TOPIC_PATH		= getTopicPath();		// --  topicpath/
TOPIC_CHM		= getTopicCHM();		// --  helpfile.chm::/
TOPIC_EXTPATH		= getTopicExternalPath();	// --  C:/Program Files/QuickBooks/
TOPIC_SKUS		= new getTopicSKUs();

// ------------------------------------------------------------ \\
// ---  DEFINE THE FILE-LINK PREFIXES FOR THIS ENVIRONMENT  --- \\

IS_POPUP_FRAME		= ( window.name.indexOf("popup__") > -1 );
IS_EXPANDO_FRAME	= ( window.name.indexOf("_expando_") > -1 );

if ( TOPIC_CHM ) {
	// ----- We are inside a CHM ----- \\
	ENVIRONMENT = "CHM";

	PATH_PREFIX_STYLESHEET = "/";
	PATH_PREFIX_IMAGES = "/";
	PATH_PREFIX_BEHAVIORS = "/";
	PATH_PREFIX_VARIABLES = "file:///" + TOPIC_EXTPATH;
	PATH_PREFIX_HELPDEBUG = "file:///" + TOPIC_EXTPATH;

} else if (	( !IS_POPUP_FRAME && (apex.Hidden) && (apex.Hidden.TOPIC_REVERSEPATH) ) ||
		( IS_POPUP_FRAME && (apex.HiddenPopup) && (apex.HiddenPopup.TOPIC_REVERSEPATH) )
	) {
	// ----- We are an update file ----- \\
	ENVIRONMENT = "UPDATE";

	if (IS_POPUP_FRAME) {
		var tReversePath = apex.HiddenPopup.TOPIC_REVERSEPATH;
	} else {
		var tReversePath = apex.Hidden.TOPIC_REVERSEPATH;
	}

	PATH_PREFIX_STYLESHEET = "ms-its:" + TOPIC_EXTPATH + "core.chm::/";
	PATH_PREFIX_IMAGES = "ms-its:" + TOPIC_EXTPATH + "core.chm::/";
	PATH_PREFIX_BEHAVIORS = "ms-its:" + TOPIC_EXTPATH + "core.chm::/";
	PATH_PREFIX_VARIABLES = tReversePath;
	PATH_PREFIX_HELPDEBUG = tReversePath;

} else {
	// ----- We are in development environment ----- \\
	ENVIRONMENT = "DEVELOPMENT";

	PATH_PREFIX_STYLESHEET = "../../_HeaderFiles/StyleSheet/";
	PATH_PREFIX_IMAGES = "../../_HeaderFiles/Images/";
	PATH_PREFIX_BEHAVIORS = "../../_HeaderFiles/JavaScript/";
	PATH_PREFIX_VARIABLES = "../../_HeaderFiles/JavaScript/";
	PATH_PREFIX_HELPDEBUG = "../../_HeaderFiles/Tools/";
}
// ------------------------------------------------------------ \\

QUICKBOOKS_VERSION	= new getQuickBooksSKU();

// -----  Define the array for variables, and then link   ----- \\
// -----  in the external file for the actual data.       ----- \\
QB_VARS = new Array();
document.writeln("<script language=\"JavaScript\" src=\"" + PATH_PREFIX_VARIABLES + "variables.js\"></script>");

// -----  Set up a link to "helpDebug.js" external file   ----- \\
document.writeln("<script language=\"JavaScript\" src=\"" + PATH_PREFIX_HELPDEBUG + "helpDebug.js\"></script>");

// ---  Define all graphics' paths (or image objects.src)   --- \\

EXPANDO_GRAPHIC = new Array();
EXPANDO_GRAPHIC["default"] = "green";
EXPANDO_GRAPHIC[0] = new Array();
  EXPANDO_GRAPHIC[0]["name"] = "green";
 EXPANDO_GRAPHIC[0]["open"] = new Image();	EXPANDO_GRAPHIC[0]["open"].src = PATH_PREFIX_IMAGES + "button_expand_green_open_lo.gif";
 EXPANDO_GRAPHIC[0]["close"] = new Image();	EXPANDO_GRAPHIC[0]["close"].src = PATH_PREFIX_IMAGES + "button_expand_green_close_lo.gif";
 EXPANDO_GRAPHIC[0]["openover"] = new Image();	EXPANDO_GRAPHIC[0]["openover"].src = PATH_PREFIX_IMAGES + "button_expand_green_open_hi.gif";
 EXPANDO_GRAPHIC[0]["closeover"] = new Image();	EXPANDO_GRAPHIC[0]["closeover"].src = PATH_PREFIX_IMAGES + "button_expand_green_close_hi.gif";
/*
 EXPANDO_GRAPHIC[1] = new Array();
 EXPANDO_GRAPHIC[1]["name"] = "white";
 EXPANDO_GRAPHIC[1]["open"] = new Image();	EXPANDO_GRAPHIC[1]["open"].filename = PATH_PREFIX_IMAGES + "button_expand_white_open_lo.gif";
 EXPANDO_GRAPHIC[1]["close"] = new Image();	EXPANDO_GRAPHIC[1]["close"].filename = PATH_PREFIX_IMAGES + "button_expand_white_close_lo.gif";
 EXPANDO_GRAPHIC[1]["openover"] = new Image();	EXPANDO_GRAPHIC[1]["openover"].filename = PATH_PREFIX_IMAGES + "button_expand_white_open_hi.gif";
 EXPANDO_GRAPHIC[1]["closeover"] = new Image();	EXPANDO_GRAPHIC[1]["closeover"].filename = PATH_PREFIX_IMAGES + "button_expand_white_close_hi.gif";
*/

ICON_PRINTER		= PATH_PREFIX_IMAGES + "icon_printer.gif";
ICON_FEEDBACK		= PATH_PREFIX_IMAGES + "icon_feedback_email.gif";
ICON_LIGHTNING		= PATH_PREFIX_IMAGES + "icon_lightningbolt.gif";
ICON_PDF			= PATH_PREFIX_IMAGES + "icon_pdf.gif";
ICON_HELP_FEEDBACK	= PATH_PREFIX_IMAGES + "icon_help_feedback.gif";
ICON_HELP_SUPPORT	= PATH_PREFIX_IMAGES + "icon_help_support.gif";

var gnScore = 0;
// ------------------------------------------------------------ \\
// ---      DISABLE THE "RIGHT-CLICK" MENU IN THE HELP      --- \\
document.onmousedown = rightclick;
// this only works because it provides an alternate window (the alert box) for the mouseup to trigger in.
// it would be better to intercept and stop the onmouseup event instead, but I can't do it yet.
function rightclick(e) {
  if (event.button == 2) {
//	alert("Right-click disabled");
//	event.returnValue = false;
//	event.cancelBubble = true;
	return false;
  }
}

// ------------------------------------------------------------ \\
// ---  INCLUDE STYLE SHEET BEHAVIORS WITH RELATIVE PATHS   --- \\
var txt = "";
txt += "<style>\n";
txt += "qb\\:tooltip { behavior: url(" + PATH_PREFIX_BEHAVIORS + "tooltip.htc); }\n";
txt += ".stripes { behavior: url(" + PATH_PREFIX_BEHAVIORS + "stripes.htc); margin-bottom: 0em; margin-top: 1em; }\n";
txt += "</style>";
document.writeln(txt);

// ------------------------------------------------------------ \\
// ----- DEFINE ALL TEXT RESOURCES HERE (FOR TRANSLATION) ----- \\
TEXT = new Array();
TEXT["feedback_ratetopic"] =		"Tell us how we can improve QuickBooks.";
TEXT["helpsupport_linktext"] =		"Do you need more information? Try the Support Center.";
TEXT["printericontext"] =		"Print Topic";
TEXT["tooltip_expando"] =		"Expand/Collapse Text";
TEXT["tooltip_multiexpando"] =		"Display details";

// ------------------------------------------------------------ \\
// -----   DISPLAY PRINTER ICON AND ADD ACTIVEX CONTROL   ----- \\
var txt = "";
txt += "<object classid=clsid:596801D8-2C9D-4627-9C67-195CB81B655A id=xobj></object>";
txt += "<object classid=clsid:c1908682-7b2c-4ab0-b98e-183649a0bf84 id=aw></object>";
if ( !IS_EXPANDO_FRAME ) {
	txt += "<a href=\"javascript:print()\"><img src=\"" + ICON_PRINTER + "\" name=\"printicon\" align=\"right\" width=\"18\" height=\"18\" border=\"0\" alt=\"" + TEXT["printericontext"] + "\"></a>";
}
document.writeln(txt);

// ------------------------------------------------------------ \\
// -----   DATA FETCHING ROUTINES FOR GLOBAL VARIABLES    ----- \\

function getTopicFilename() {
	var loci = document.location.toString().match(/[^\/\\]*\.html/);
	return loci;
}

function getTopicPath() {
	var loci = document.location.toString();
	if (getTopicCHM()) {
		// ----- there is a CHM ----- \\
		var Y = loci.lastIndexOf("/");
		var t = loci.substring(0,Y);
		var Y2 = loci.indexOf("::/");
		var t = loci.substring(Y2+3,Y+1);
	} else {
		// ----- there is no CHM ----- \\
		if (window.TOPIC_UPDATEPATH && window.QUICKPATCH_codeVersion) {
			// ----- we're a patched topic ----- \\
			var Y = loci.indexOf(TOPIC_UPDATEPATH) + TOPIC_UPDATEPATH.length;
			var t = loci.substring(Y,loci.length);
			var Y2 = t.lastIndexOf("/");
			var t = t.substring(0,Y2+1);
		} else {
			// ----- development enviroment, or unknown ----- \\
			// ----- just assume one dir up ----- \\
			var Y = loci.lastIndexOf("/");
			var t = loci.substring(0,Y);
			var Y2 = t.lastIndexOf("/");
			var t = loci.substring(Y2+1,Y+1);
		}
	}
	return t;
}

function getTopicCHM() {
	var loci = document.location.toString().match(/[^\/\\]*\.chm\:\:\//i);
	if (loci) {
		return loci;
	} else {
		return "";
	}
}

function getTopicExternalPath() {
	if (window.TOPIC_EXTPATH && window.QUICKPATCH_codeVersion) {
		// ----- "_updated.js" has already calculated TOPIC_EXTPATH; just use it ----- \\
		var tPath = window.TOPIC_EXTPATH;
	} else {
		// ----- figure out path on our own ----- \\
		var tPath = "";
		var loci = document.location.toString().replace(/\\/g, "/");
		switch ( loci.search(":") ) {
			case 2:		// mk:@MSITStore:
				var X = 14;
				break;
			case 6:		// ms-its:
				var X = 7;
				break;
			case 4:		// file:///
				var X = 8;
				break;
		}

		if (X==8) {	// "file:///"
			// ----- C:/Development/QuickBooks/Help/ (Y2) internalpath/ (Y3) topicfile.html (Y4) #bookmarkdata
			var Y4 = loci.indexOf("#");		Y4 = (Y4 < 0) ? loci.length : Y4;
			tPath = loci.substring(X,Y4);
			var Y3 = tPath.lastIndexOf("/")+1;
			tPath = tPath.substring(0,Y3);
			var Y2 = tPath.lastIndexOf("/",tPath.length-2)+1;
			tPath = tPath.substring(0,Y2);
		} else {
			// ----- do the calc ----- \\
			// ----- C:/ProgramFiles/IntuitProgram/ (Y1) help.chm::/ (Y2) internalpath/ (Y3) topicfile.html (Y4) #bookmarkdata
			var Y2 = loci.indexOf("::/");
			tPath = loci.substring(X,Y2);
			var Y1 = tPath.lastIndexOf("/")+1;
			tPath = tPath.substring(0,Y1);
		}
	}
	return tPath;
}

function getTopicSKUs() {
	var tSKU = "";
	if (window.XML) {
		// ----- check XML from topic header ----- \\
		for (var i=0; i < XML.childNodes.length; i++) {
			if (XML.childNodes(i).tagName.toUpperCase() == "SKU")  {
				tSKU = XML.childNodes(i).text;
				i = XML.childNodes.length;
			}
		}
	}

	return new flattenSKUs( tSKU );
}

function getQuickBooksSKU() {
	var tStratum = "";
	var tFlavour = "";
	// ----- Omitted; for use in U.K. ----- \\
	// var tBrand = "";

	var tError = "";

	// ----- For a current list of SKUs that the product reports,   ----- \\
	// ----- check the file FlavorInstaller_common.h. Currently in  ----- \\
	// ----- QB2004Dev/installsource/ishield6/core/script files/    ----- \\

	try {
		var objLocator = new ActiveXObject("QuickBooks.CoLocator");
		var objProfile = objLocator.Create("QBPrefs.AppParameters"); 

		var flavor = objProfile.Flavor;  // a string value; eg. "accountant"

		if (flavor == "lite") {
			tStratum = "LITE";
			tFlavour = "";
		} else if (flavor == "pro") {
			tStratum = "PRO";
			tFlavour = "";
		} else if (flavor == "superpro") {
			tStratum = "PREMIER";
			tFlavour = "";
		} else if (flavor == "accountant") {
			tStratum = "PREMIER";
			tFlavour = "ACCOUNTANT";
		} else if (flavor == "contractor") {
			tStratum = "PREMIER";
			tFlavour = "CONTRACTOR";
		} else if (flavor == "nonprofit") {
			tStratum = "PREMIER";
			tFlavour = "NONPROFIT";
		} else if (flavor == "healthcare") {
			tStratum = "PREMIER";
			tFlavour = "HEALTHCARE";
		} else if (flavor == "professional") {
			tStratum = "PREMIER";
			tFlavour = "PROFESSIONAL";
		} else if (flavor == "wholesale") {
			tStratum = "PREMIER";
			tFlavour = "WHOLESALE";
		} else if (flavor == "retail") {
			tStratum = "PREMIER";
			tFlavour = "RETAIL";
		} else if (flavor == "bel") {
			tStratum = "ENTERPRISE";
			tFlavour = "";
		} else if (flavor == "belacct") {
			tStratum = "ENTERPRISE";
			tFlavour = "ACCOUNTANT";
		} else if (flavor == "belcontractor") {
			tStratum = "ENTERPRISE";
			tFlavour = "CONTRACTOR";
		} else if (flavor == "belnonprofit") {
			tStratum = "ENTERPRISE";
			tFlavour = "NONPROFIT";
		} else if (flavor == "belhealthcare") {
			tStratum = "ENTERPRISE";
			tFlavour = "HEALTHCARE";
		} else if (flavor == "belprofessional") {
			tStratum = "ENTERPRISE";
			tFlavour = "PROFESSIONAL";
		} else if (flavor == "belwholesale") {
			tStratum = "ENTERPRISE";
			tFlavour = "WHOLESALE";
		} else if (flavor == "belretail") {
			tStratum = "ENTERPRISE";
			tFlavour = "RETAIL";
		} else {
			tStratum = "BASIC";
			tFlavour = "";
			tError = "Unrecognized QuickBooks.CoLocator response";
		}
	}
	catch (e) {
		tError = "Couldn't find QuickBooks.ActiveXObject";

		tStratum = "BASIC";
		tFlavour = "";
	}

	if (TOPIC_EXTPATH) {
		// ----- if there's an external path, try linking in the SKU.js override file ----- \\
		document.writeln("<script language=\"JavaScript\" src=\"" + PATH_PREFIX_VARIABLES + "SKU.js\"></script>");

		// ----- Format of SKU.js file: it must contain the following lines: ----- \\
		// -----   window.QUICKBOOKS_VERSION.Stratum = "PRO";                ----- \\
		// -----   window.QUICKBOOKS_VERSION.Flavour = "";                   ----- \\
		// -----   window.QUICKBOOKS_VERSION.Error = "Loaded from SKU.js";   ----- \\
	}

	this.Stratum = tStratum.toUpperCase();
	this.Flavour = tFlavour.toUpperCase();
	this.Error = tError;
}

// ------------------------------------------------------------ \\
// ============================================================ \\
// =====           CONDITIONAL & VARIABLE TEXT            ===== \\
// ============================================================ \\

function conditionalText() {
	// ----- first off, let's find the _expando_ parent frame ----- \\
	// ----- might not be _top, but first above "_expando_"s  ----- \\
	var iTargetObj = self;
	while ( iTargetObj.name.indexOf("_expando_") >= 0 ) {
		iTargetObj = iTargetObj.parent;
	}
	var iTarget = iTargetObj.name;
	if (iTargetObj == top || iTarget == "") {
		iTarget = "_top";
	}
	if (iTargetObj == self) {
		iTarget = "";
	}

	// -----  This function scans through every HTML DOM node in the file.   ----- \\
	// -----  NB: HTML attributes are case-sensitive! 'Name' is not 'name'.  ----- \\

	var at_body = "";
	var at_relatedtopics = "";

	for (var i=0; i<document.all.length; i++) {
		nodeObj = document.all(i);
		tNode = nodeObj.nodeName.toUpperCase();

		if (tNode.substring(0,1) != "#") {
			// ----- Only check if not XML object ----- \\
			tSKUs = "";
			if ( nodeObj.attributes["skus"] ) { tSKUs = nodeObj.attributes["skus"].value; }
			if ( nodeObj.attributes["Skus"] ) { tSKUs = nodeObj.attributes["Skus"].value; }
			if ( nodeObj.attributes["SKUS"] ) { tSKUs = nodeObj.attributes["SKUS"].value; }
			if (tSKUs) {
				// ----- make this item conditional ----- \\
				if ( validateSKUs(tSKUs) ) {
					nodeObj.style.display = (tNode=="SPAN" || tNode=="A") ? "inline" : "block";
				} else {
					nodeObj.style.display = "none";
				}
			}
		}

		if ( tNode == "VAR" ) {
			// ----- evaluate variable ----- \\
			setHTMLvariable( nodeObj );
		}

		if ( tNode == "A" ) {
			linkObj = nodeObj;

			if (iTarget) {
				if ( !(linkObj.target) ) {
					linkObj.target = iTarget;
				}
			}

			// ----- scan links; implement "iref"s ("Intelligent" or "Intuit" References) ----- \\
			// ----- if the target of the link is appropriate for this SKU, turn it on.   ----- \\
			var tIref = "";
			if ( linkObj.attributes["iref"] ) { tIref = linkObj.attributes["iref"].value; }
			if ( linkObj.attributes["iRef"] ) { tIref = linkObj.attributes["iRef"].value; }
			if ( linkObj.attributes["Iref"] ) { tIref = linkObj.attributes["Iref"].value; }
			if ( linkObj.attributes["IREF"] ) { tIref = linkObj.attributes["IREF"].value; }
			if (tIref) {
				var tTargetSKUs = fetchAttributeValue( linkObj, "targetSKUs" );
				if ( !tTargetSKUs ||
				     ( tTargetSKUs && validateSKUs(tTargetSKUs) )
				   ) {
					linkObj.href = tIref;
				}
			}

			// ----- popups are irefs too, just ones that call a popup window. ----- \\
			// ----- much the same code as above.                              ----- \\
			var tPop = "";
			if ( linkObj.attributes["popup"] ) { tPop = linkObj.attributes["popup"].value; }
			if ( linkObj.attributes["Popup"] ) { tPop = linkObj.attributes["Popup"].value; }
			if ( linkObj.attributes["POPUP"] ) { tPop = linkObj.attributes["POPUP"].value; }
			if (tPop) {
				var tTargetSKUs = fetchAttributeValue( linkObj, "targetSKUs" );
				if ( !tTargetSKUs ||
				     ( tTargetSKUs && validateSKUs(tTargetSKUs) )
				   ) {
					linkObj.href = tPop;
					// ----- set up an "onclick" call to get the mouse X+Y ----- \\
					// ----- also, reformat the link to use dotted line.   ----- \\
					linkObj.onclick = MarkPopup;
					linkObj.style.textDecoration = "none";
					// ----- linkObj.style.borderBottom = "1px dotted"; ----- \\
				}
			}

			// ----- it's linking to the outside world; add bolt ----- \\
			if ( linkObj.href.search( /^http:\/\//i ) >= 0 ) {
				linkObj.outerHTML = "<img src=\"" + ICON_LIGHTNING + "\" width=8 height=12>" + linkObj.outerHTML;
				// ----- we've added a new tag, so increment i to skip over the link ----- \\
				i++;
			} else {
				// ----- this is an internal link.                      ----- \\
				// ----- make the link include the CHM name explicitly  ----- \\
				// ----- this fixes broken links in expandos and popups ----- \\
				if ( TOPIC_CHM && linkObj.href
				      && ( linkObj.href.substr(0,11).toLowerCase() != "javascript:" )
				      && ( linkObj.href.indexOf("::") < 0 )
				   ) {
					linkObj.href = TOPIC_CHM + TOPIC_PATH  + linkObj.href;

				}
			}

			// ----- encase popup URL in popup calling code ----- \\
			if (tPop) {
				linkObj.href = "javascript:Popup('" + linkObj.href + "')";
			}

			// ----- implement expando text links here ----- \\
			var tDivID = "";
			if ( linkObj.attributes["expando"] ) { tDivID = linkObj.attributes["expando"].value; }
			if ( linkObj.attributes["Expando"] ) { tDivID = linkObj.attributes["Expando"].value; }
			if ( linkObj.attributes["EXPANDO"] ) { tDivID = linkObj.attributes["EXPANDO"].value; }
			if ( linkObj.attributes["expando"] || linkObj.attributes["Expando"] || linkObj.attributes["EXPANDO"] ) {
				makeExpandoLink( linkObj, tDivID );
			}

			// ----- implement radio button expando text links here ----- \\
			var tDivID = "";
			if ( linkObj.attributes["multiexpando"] ) { tDivID = linkObj.attributes["multiexpando"].value; }
			if ( linkObj.attributes["MULTIEXPANDO"] ) { tDivID = linkObj.attributes["MULTIEXPANDO"].value; }
			if ( tDivID ) {
				makeMultiExpandoLink( linkObj, tDivID );
			}

		}

		if (nodeObj.id.toLowerCase() == "help_feedback_link") {
			// ----- Add the help feedback link to the bottom of the topic ----- \\
			if ( !IS_EXPANDO_FRAME ) {
				makeFeedbackAndHelpSupportLink( nodeObj );
			}
		}

		// -----  Hide certain segments in the case of expando frames  ----- \\
		if (IS_EXPANDO_FRAME) {
			// ----- hide the first content tag after the body if it's an <H#> tag. ----- \\
			if ( at_body == "AT" && nodeObj.innerHTML ) {
				at_body = "PAST";
				if (tNode.substring(0,1) == "H") {
					nodeObj.style.display = "none";
				}
			}

			if ( !at_body && tNode == "BODY" ) {
				at_body = "AT";
			}

			// ----- hide any <h4>Related Topics</h4> blocks along with the following list ----- \\
			if ( !at_relatedtopics && tNode == "H4" ) {
				at_relatedtopics = "AT";
			}

			if ( at_relatedtopics == "AT" ) {
				if ( tNode == "H4" ) {
					nodeObj.style.display = "none";
				}
				if ( tNode == "OL" || tNode == "UL" ) {
					nodeObj.style.display = "none";
				}
				if ( tNode != "H4" && tNode != "OL" && tNode != "UL" ) {
					at_relatedtopics = "";
				}
			}
		}



		// ------------------------------------------------------------ \\
		// ---  Include self-reporting tags for helping developers  --- \\

		if (tNode == "DETECTSKU") {
			nodeObj.outerHTML = displaySKU();
		}

		if (tNode == "LISTALLSKUS") {
			nodeObj.outerHTML = displayAllSKUs();
		}

		if (tNode == "LISTALLMODS") {
			nodeObj.outerHTML = displayAllMods();
		}

		if (tNode == "HELP") {
			nodeObj.outerHTML = displayHelp();
		}
	}

}

function setHTMLvariable ( obj ) {
	// -----  NB: HTML attributes are case-sensitive! 'Name' is not 'name'.  ----- \\

	var tOriginal = obj.innerHTML;
	var tOutput = tOriginal;
	var tOut = "";

	var tName = ""
	if ( obj.attributes["name"] ) { tName = obj.attributes["name"].value; }
	if ( obj.attributes["Name"] ) { tName = obj.attributes["Name"].value; }
	if ( obj.attributes["NAME"] ) { tName = obj.attributes["NAME"].value; }
	if (tName) {
		// ----- search for variable; does it exist? ----- \\
		tOut = QB_VARS[tName.toLowerCase()];
		if ( tOut ) {
			tOutput = tOut["word"];
		} else {
			if (window.HELP_DEBUG) {
				tOutput  = "<font color=\"red\">(" + tOriginal + ") ";
				tOutput += "<span style=\"font-family:Arial;font-size:9pt\">";
				tOutput += "<i>Error!:</i> " + tName + " <i>not found</i></span></font>";
			} else {
				// ----- leaving this "else" clause in for potential action ----- \\
				tOutput  = tOriginal;
			}
		}
	} else {
		// ----- you can apply mods to non-variables if you want ----- \\
		tOut = "OK";
		tOutput = string_trim(tOutput);
	}

	var tMods = "";
	if ( obj.attributes["mods"] ) { tMods = obj.attributes["mods"].value; }
	if ( obj.attributes["Mods"] ) { tMods = obj.attributes["Mods"].value; }
	if ( obj.attributes["MODS"] ) { tMods = obj.attributes["MODS"].value; }
	if (tOut && tMods) {
		var tMarks = tMods.split(",");
		var tAnAdd = "";
		for (var j=0; j < tMarks.length; j++) {
			switch ( string_trim(tMarks[j].toUpperCase()) ) {
			  case "A/N":
				if (tMarks[j] == "a/n") {
					tAnAdd = ("AEIOU".indexOf(tOutput.substring(0,1).toUpperCase())<0) ? "a" : "an";
				}
				if (tMarks[j] == "A/n") {
					tAnAdd = ("AEIOU".indexOf(tOutput.substring(0,1).toUpperCase())<0) ? "A" : "An";
				}
				if (tMarks[j] == "A/N") {
					tAnAdd = ("AEIOU".indexOf(tOutput.substring(0,1).toUpperCase())<0) ? "A" : "AN";
				}
			  break;
			  case "AN":
				tOutput = ("AEIOU".indexOf(tOutput.substring(0,1).toUpperCase())<0) ? "a "+tOutput : "an "+tOutput;
			  break;
			  case "CAPALL":
				tOutput = string_caps(tOutput," ");
			  break;
			  case "CAPFIRST":
				tOutput = tOutput.substring(0,1).toUpperCase() + tOutput.substring(1,tOutput.length);
			  break;
			  case "PLURAL":
				if ( tOut["plural"] ) {
					// ----- use predefined value ----- \\
					tOutput = tOut["plural"];
				} else {
					// ----- calculate it using grammar rule ----- \\
					if ( tOutput.substring(tOutput.length-1,tOutput.length).toUpperCase() ==  "S" ) {
						tOutput = tOutput + "es";
					} else {
						tOutput = tOutput + "s";
					}
				}
			  break;
			  case "POSS":
				if ( tOut["poss"] ) {
					// ----- use predefined value ----- \\
					tOutput = tOut["poss"];
				} else {
					// ----- calculate it using grammar rule ----- \\
					if ( tOutput.substring(tOutput.length-1,tOutput.length).toUpperCase() ==  "S" ) {
						tOutput = tOutput + "'";
					} else {
						tOutput = tOutput + "'s";
					}
				}
			  break;
			  case "LOWER":
				tOutput = tOutput.toLowerCase();
			  break;
			  case "UPPER":
				tOutput = tOutput.toUpperCase();
			  break;
			  case "2TEXT":
				tOutput = convertNumberToText( tOutput );
			  break;
			  case "ORDINAL":
				tOutput = convertNumberToOrdinal( tOutput );
			  break;
			}
		}
		if (tAnAdd) {
			tOutput = tAnAdd + " " + tOutput;
		}
	}

	if (obj.attributes["money"] || obj.attributes["Money"] || obj.attributes["MONEY"]) {
		// -----  display money here.  ----- \\
		// ----- US/Canada:	$1000  ----- \\
		// ----- U.K.:		£1000  ----- \\
		// ----- Québec:	1000 $ ----- \\
		tOutput = "$" + tOutput;
	}

	obj.innerHTML = tOutput;
}

function fetchAttributeValue ( obj, attName ) {
	for (var j=0; j < obj.attributes.length; j++) {
		if (obj.attributes[j].name.toUpperCase() == attName.toUpperCase()) {
			return obj.attributes[j].value;
		}
	}
}

function validateSKUs ( str ) {
	var tLists = new flattenSKUs(tSKUs);
	var tValid = false;
	if (tLists.valid) {
		if (	(tLists.valid.indexOf(","+QUICKBOOKS_VERSION.Stratum+",") >= 0) ||
			(tLists.valid.indexOf(","+QUICKBOOKS_VERSION.Flavour+",") >= 0) ||
			( (tLists.valid.indexOf(","+QUICKBOOKS_VERSION.Stratum+":,") >= 0 ) &&
			  (!QUICKBOOKS_VERSION.Flavour) )
		) {
			tValid = true;
		}
	}
	if (tLists.invalid) {
		if (	(tLists.invalid.indexOf(","+QUICKBOOKS_VERSION.Stratum+",") < 0) &&
			(tLists.invalid.indexOf(","+QUICKBOOKS_VERSION.Flavour+",") < 0) &&
			( (tLists.invalid.indexOf(","+QUICKBOOKS_VERSION.Stratum+":,") < 0) ||
			  (QUICKBOOKS_VERSION.Flavour) )
		) {
			tValid = true;
		}
	}
	return tValid;
}

function flattenSKUs ( source ) {
	// ----- expand expression into two flat, complete lists of SKUs  ----- \\
	// ----- and flavours, separated and bookended by commas; i.e. ----- \\
	// ----- list = ",BASIC,PRO,PREMIER,CONTRACTOR,ACCOUNTANT,".      ----- \\
	// ----- there is a ".valid" list string and an ".invalid" one.   ----- \\

	var tNots = source.match( /NOT\(([\w,]*)\)/i );
	if (tNots) {
		var tTokens = tNots[0].substring(4,tNots[0].length-1).split(",");
	} else {
		var tTokens = source.split(",");
	}

	var tList = new Array();
	for (var j=0; j < tTokens.length; j++) {
		tOut = string_trim(tTokens[j].toUpperCase());

		// ----- convert synonyms to proper code ----- \\
		var tSynOut = tOut.replace( /^(\w*)[+-:]?$/i, "$1" );
		if (tSynOut == "BEL") { tSynOut = "ENTERPRISE"; }
		if (tSynOut == "QBES") { tSynOut = "ENTERPRISE"; }
		if (tSynOut == "ACCT") { tSynOut = "ACCOUNTANT"; }
		tOut = tOut.replace( /^(\w*)([+-:]?)$/, tSynOut+"$2" );

		// -----  search for +/- extensors to STRATUM; i.e. "PRO+" means PRO, PREMIER, etc. ----- \\
		// -----  pointless for top and bottom of list; no "MINIMUM-" or "MAXIMUM+"         ----- \\
		for (var k=1; k < QUICKBOOKS_ALLSTRATA.length-1; k++) {
			if ( tOut == QUICKBOOKS_ALLSTRATA[k] + "+" ) {
				// ----- "STRATUM+"; include this stratum and all above it ----- \\
				for ( var n=k; n < QUICKBOOKS_ALLSTRATA.length; n++ ) {
					var tStrat = QUICKBOOKS_ALLSTRATA[n];
					if ( (tList.toString()+",").indexOf(tStrat+",") < 0 )	{ tList.push( tStrat ); }
				}
				k = QUICKBOOKS_ALLSTRATA.length;
			}
			if ( tOut == QUICKBOOKS_ALLSTRATA[k] + "-" ) {
				// ----- "STRATUM-"; include this stratum and all below it ----- \\
				for ( var n=0; n <= k; n++ ) {
					var tStrat = QUICKBOOKS_ALLSTRATA[n];
					if ( (tList.toString()+",").indexOf(tStrat+",") < 0 )	{ tList.push( tStrat ); }
				}
				k = QUICKBOOKS_ALLSTRATA.length;
			}
		}

		// ----- if all else fails, just add the code you were passed ----- \\
		if ( (tList.toString()+",").indexOf(tOut+",") < 0 )		{ tList.push( tOut ); }
	}

	if (tNots) {
		this.valid = "";
		this.invalid = "," + tList.toString() + ",";
	} else {
		this.valid = "," + tList.toString() + ",";
		this.invalid = "";
	}
}

function addUnique ( tArray, tElement ) {
	for (var j=0; j<tArray.length; j++) {
		if (tArray[j] == tElement) {
			return tArray;
		}
	}
	tArray[tArray.length] = tElement;
	return tArray;
}

function string_caps ( str, delim ) {
	var txt = "";
	var tmp = str.split(delim);
	for (var i=0; i < tmp.length; i++) {
		if (tmp[i]) {
			txt += tmp[i].substring(0,1).toUpperCase();
			txt += tmp[i].substring(1,tmp[i].length);
			txt += delim;
		}
	}

	return txt;
}

function string_trim ( str ) {
	str = str.replace( /^\s*/ , "" );
	str = str.replace( /\s*$/ , "" );
	return str;
}

function convertNumberToText ( str ) {
	var tNum = parseInt(str);

	// ----- if it's not a number, just return the string ----- \\
	if ( isNaN(tNum) ) {
	return str;
	}

	var tOut = "";

	// ----- if it's zero, then return zero ----- \\
	if (tNum == 0) {
		tOut = "zero";
	}

	while ( tNum ) {
		var tNumStartLoop = tNum;

		if ( tNum > 999999999 ) {
			// ----- too big; just return the string ----- \\
			tOut = str;
			tNum = 0;
		}

		if ( tNum > 999999 ) {
			// ----- we're in the millions; find how many ----- \\
			var t1 = Math.floor( tNum / 1000000 );
			var t2 = convertThousandsToText(t1);
			if (tOut) { tOut += ","; }
			tOut += t2 + " million";

			tNum = tNum % 1000000;
		}

		if ( tNum > 999 ) {
			// ----- we're in the thousands; find how many ----- \\
			var t1 = Math.floor( tNum / 1000 );
			var t2 = convertThousandsToText(t1);
			if ( (tOut) && (t2) ) { tOut += ","; }
			tOut += t2 + " thousand";

			tNum = tNum % 1000;
		}

		if ( tNum < 1000 ) {
			// ----- we're under a thousand; finish ----- \\
			var t2 = convertThousandsToText(tNum);
			if ( (tOut) && (t2) ) { tOut += ","; }
			tOut += t2;

			tNum = 0;
		}

		// ----- do a final comparison to prevent infinite looping ----- \\
		if (tNumStartLoop == tNum) {
			// ----- if nothing happened to tNum then we're looping; kill ----- \\
			tNum = 0;
			tOut = str;
		}
	}

	return tOut;
}

function convertThousandsToText ( num ) {
	var tOut = "";
	if ( num > 999 ) {
		num = num % 1000;
	}

	if ( num > 99 ) {
		// ----- we're in the hundreds; find how many ----- \\
		var t1 = Math.floor( num / 100 );
		var t2 = convertDecadesToText(t1);
		tOut += t2 + " hundred";

		num = num % 100;
	}

	if ( num > 0 ) {
		// ----- we're under a hundred; finish ----- \\
		var t2 = convertDecadesToText(num);
		if (tOut) { tOut += " and "; }
		tOut += t2;
	}

	return tOut;
}

function convertDecadesToText ( num ) {
	var numbers = new Array("", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen");
	var decades = new Array("", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety");

	var tOut = "";
	if ( num > 99 ) {
		num = num % 100;
	}

	if ( num > 19 ) {
		// ----- set up the decade ----- \\
		var t1 = Math.floor( num / 10 );
		tOut += decades[t1];

		num = num % 10;
	}

	if ( num > 0 ) {
		// ----- all that remains is teens or singles ----- \\
		if (tOut) { tOut += "-"; }
		tOut += numbers[num];
	}

	return tOut;
}

function convertNumberToOrdinal ( str ) {
	var tNum = parseInt(str);

	if ( isNaN(tNum) ) {
		// ----- number is written as text ----- \\

		if ( str.substr(str.length-3) == "one" ) {
			return str.substring(0,str.length-3) + "first";
		}
		if ( str.substr(str.length-3) == "two" ) {
			return str.substring(0,str.length-3) + "second";
		}
		if ( str.substr(str.length-5) == "three" ) {
			return str.substring(0,str.length-5) + "third";
		}
		if ( str.substr(str.length-2) == "ty" ) {
			return str.substring(0,str.length-2) + "tieth";
		}

		return str + "th";

	} else {
		// ----- number is in numeric form ----- \\
		tLast = tNum % 10;

		if ( tLast == 1 ) {
			return str + "st";
		}
		if ( tLast == 2 ) {
			return str + "nd";
		}
		if ( tLast == 3 ) {
			return str + "rd";
		}

		return str + "th";
	}
}

// ------------------------------------------------------------ \\
// ============================================================ \\
// =====                EXPANDO SECTIONS                  ===== \\
// ============================================================ \\
// ------------------------------------------------------------ \\
// -----     INSERT CODE FOR EXPANDO AND MULTIEXPANDO     ----- \\

if (!(apex.GLOBAL_EXPANDO_FRAMES)) { apex.GLOBAL_EXPANDO_FRAMES = 0; }
if (!(apex.GLOBAL_EXPANDOFRAME_DATA)) { apex.GLOBAL_EXPANDOFRAME_DATA = new Array(); }
if (!(window.GLOBAL_MULTIEXPANDOS)) { GLOBAL_MULTIEXPANDOS = new Array(); }

function makeExpandoLink ( linkObj, divID ) {
	var tDivObj = findExpandoDiv( linkObj, divID );

	// -----  If there's no valid target zone for this link,       ----- \\
	// -----  then we don't activate the href, and it's just text. ----- \\
	if (tDivObj) {
		// ----- is there a specific icon= being asked for? ----- \\
		var myIcon = fetchAttributeValue( linkObj, "icon" );
		if (!myIcon) {
			myIcon = EXPANDO_GRAPHIC["default"];
		}

		// ----- get the index of the chosen expando icon ----- \\
		var iconIndex = 0;
		for (var i=0; i < EXPANDO_GRAPHIC.length; i++) {
			if ( myIcon == EXPANDO_GRAPHIC[i]["name"] ) {
				iconIndex = i;
				i = EXPANDO_GRAPHIC.length;
			}
		}

		// ----- does it default to open or closed? ----- \\
		var tStartOpen = ( linkObj.attributes["open"] || linkObj.attributes["Open"] || linkObj.attributes["OPEN"] ) ? "YES" : "";

		// ----- try to implement the DIV; it may yet be illegal ----- \\
		if ( !makeExpando_DivPrep( tDivObj, tStartOpen ) ) {
			return;
		}

		// ----- add open/close graphic to link ----- \\
		if ( tStartOpen ) {
			linkObj.innerHTML += "<img src=\"" + EXPANDO_GRAPHIC[iconIndex]["close"].src + "\" border=0 style=\"margin-left: 4\">";
		} else {
			linkObj.innerHTML += "<img src=\"" + EXPANDO_GRAPHIC[iconIndex]["open"].src + "\" border=0 style=\"margin-left: 4\">";
		}

		// ----- generate a unique ID if the link doesn't have one ----- \\
		if (!linkObj.id) { linkObj.id = document.uniqueID; }
		// ----- now generate the tooltip for this expando link    ----- \\
		var t = "<qb:tooltip element=\"" + linkObj.id + "\" delay=\"3000\" avoidmouse=\"false\">" + TEXT["tooltip_expando"] + "</qb:tooltip>";
		document.body.insertAdjacentHTML("beforeEnd", t);

		// ----- set custom attributes in the <A> tag ----- \\
		// ----- for the DIV ID and the iconIndex     ----- \\
		linkObj.divID = divID;
		linkObj.iconIndex = iconIndex;

		linkObj.href = "javascript:";
		linkObj.onclick = expandoText;
		linkObj.onmouseover = expandoMouseOver;
		linkObj.onmouseout = expandoMouseOut;
	}
}

function makeMultiExpandoLink ( linkObj, divID ) {
	if (!(GLOBAL_MULTIEXPANDOS[divID])) { GLOBAL_MULTIEXPANDOS[divID] = 0; }
	var tID = GLOBAL_MULTIEXPANDOS[divID] + 1;

	// ----- Div IDs for multi-expandos are made like this: "name(1)" ----- \\
	var uniqueDivID = divID+"("+tID+")";
	var tDivObj = document.all[uniqueDivID];

	// -----  If there's no valid target zone for this link,       ----- \\
	// -----  then we don't activate the href, and it's just text. ----- \\
	if (tDivObj) {
		GLOBAL_MULTIEXPANDOS[divID] = tID;

		var tStartOpen = ( linkObj.attributes["open"] || linkObj.attributes["Open"] || linkObj.attributes["OPEN"] ) ? "YES" : "";

		// ----- try to implement the DIV; it may yet be illegal ----- \\
		if ( !makeExpando_DivPrep( tDivObj, tStartOpen ) ) {
			return;
		}

		// ----- add radio button to link ----- \\
		linkObj.innerHTML = "<input type=\"radio\" name=\"" + divID + "\">" + linkObj.innerHTML;

		// ----- generate a unique ID if the link doesn't have one ----- \\
		if (!linkObj.id) { linkObj.id = document.uniqueID; }
		// ----- now generate the tooltip for this expando link    ----- \\
		var t = "<qb:tooltip element=\"" + linkObj.id + "\" delay=\"3000\" avoidmouse=\"false\">" + TEXT["tooltip_multiexpando"] + "</qb:tooltip>";
		document.body.insertAdjacentHTML("beforeEnd", t);

		// ----- set custom attributes in the <A> tag ----- \\
		// ----- for the base DIV name and # index    ----- \\
		linkObj.DivBase = divID;
		linkObj.DivIndex = tID;

		linkObj.href = "javascript:";
		linkObj.onclick = multiExpandoText;
	}
}

function makeExpando_DivPrep ( divObj, startOpen ) {
	// ----- See if this is a simple DIV or an IFRAME include file ----- \\

	tFile = "";
	if ( divObj.attributes["file"] ) { tFile = divObj.attributes["file"].value; }
	if ( divObj.attributes["File"] ) { tFile = divObj.attributes["File"].value; }
	if ( divObj.attributes["FILE"] ) { tFile = divObj.attributes["FILE"].value; }
		if (tFile) {
		// ----- There's an external file referenced by the DIV.   ----- \\
		// ----- Create and size an IFRAME for the included file.  ----- \\
		tFile = tFile.replace(/\\/g, "/");

		// ----- Convert link to explicit CHM reference.           ----- \\
//		--- Unnecessary; handled later by FixURL(). Leave out.
//		--- Keeping a copy in case problems arise in the cyclical check.
//		if ( tFile.indexOf("::") < 0 ) {
//			var tSub = TOPIC_PATH;
//			while ( tFile.substr(0,3) == "../" ) {
//				tSub = tSub.substring(0,tSub.lastIndexOf("/",tSub.length-2));
//				tFile = tFile.substring(3,tFile.length);
//			}
//			tFile = TOPIC_CHM + tSub + tFile;
//		}


		// ----- Make sure it's not a cyclical reference.          ----- \\
		// ----- walk up the "_expando_" tree and check all src.   ----- \\
		
		// 9-20-2005 mkronber:  modified this code because was not working in some cases.
		// Changed the logic to strip all compares down to the raw file name "xyz.html"
		// e.g. no leading "../" or "directory/" before the topics. This fixed the issue
		// we were seeing, also this should suffice since we have unique topic names.
		
		
		var tMe = self;
		var tLoc = "";
		var tBase = (tFile.indexOf("::/") < 0) ? tFile : tFile.substring(tFile.indexOf("::/")+3,tFile.length);
		// remove the leading "../" if present. mkronber 9-20-2005
		if ( tBase.substr(0,3) == "../" ) {
			tBase = tBase.substring(3,tBase.length);
		}
		// change "\" to "/"		
		tBase = tBase.replace(/\\/g,"/");
		// Remove directory "dir/" from file name for compare, since tBase doesn't have it.
		// mkronber 9-20-2005
		tBase = (tBase.indexOf("/") < 0) ? tBase : tBase.substring(tBase.indexOf("/")+1,tBase.length);


		var cyclical = false;
		while ( tMe.name.indexOf("_expando_") >= 0 ) {
			tLoc = unescape(tMe.location);
			tLoc = (tLoc.indexOf("::/") < 0) ? tLoc : tLoc.substring(tLoc.indexOf("::/")+3,tLoc.length);
			tLoc = tLoc.replace(/\\/g,"/");
			// remove the leading ../ if present MTK
			if ( tLoc.substr(0,3) == "../" ) {
				tLoc = tLoc.substring(3,tLoc.length);
			}
			// Remove directory from file name for compare, since tBase doesn't have it.
			// mkronber 9-20-2005
			tLoc = (tLoc.indexOf("/") < 0) ? tLoc : tLoc.substring(tLoc.indexOf("/")+1,tLoc.length);
			cyclical = cyclical || (tLoc.toLowerCase() == tBase.toLowerCase());
			tMe = tMe.parent;
		}
		// ----- also have to check against ultimate parent.       ----- \\
		tLoc = unescape(tMe.location);
		tLoc = (tLoc.indexOf("::/") < 0) ? tLoc : tLoc.substring(tLoc.indexOf("::/")+3,tLoc.length);
		tLoc = tLoc.replace(/\\/g,"/");
		// Remove directory "dir/" from file name for compare, since tBase doesn't have it.
		// mkronber 9-20-2005
		tLoc = (tLoc.indexOf("/") < 0) ? tLoc : tLoc.substring(tLoc.indexOf("/")+1,tLoc.length);
		cyclical = cyclical || (tLoc.toLowerCase() == tBase.toLowerCase());

		if ( cyclical ) {
			// ----- Cyclical reference!!!, fail and return false. ----- \\
			// If this does not properly catch a circular reference and return false, 		
			// the Javascript will enter an infinite loop!(e.g. QBW036130) mkronber 9-20-2005
			return false;
		}

		// v Celia remove it to make external expando to work Nov 21, 2005
		//tFile = FixURL( tFile );
		// ^ Celia remove it to make external expando to work Nov 21, 2005

		// ----- Note: a link to the <iframe> node is not the same ----- \\
		// ----- as a link to the frame object; which is to say    ----- \\
		// ----- divObj.all(0) != document.frames(tIFName).        ----- \\
		// ----- Which is why the iframe needs a name.             ----- \\

		apex.GLOBAL_EXPANDO_FRAMES++;
		var tIFName = "_expando_" + apex.GLOBAL_EXPANDO_FRAMES;
		var t = "<iframe name=\"" + tIFName + "\" frameborder=\"0\" scrolling=\"auto\"></iframe>";
		divObj.innerHTML = t;

		divObj.style.position = "absolute";
		divObj.style.top = -10000;
		divObj.style.left = -10000;
		divObj.style.display = "block";

		if ( tFile.indexOf("::") > 0 ) {
			tFile = "ms-its:" + TOPIC_EXTPATH + tFile;
		}
		document.frames(tIFName).location = tFile;

		// ----- store info we need later in global variables  ----- \\
		apex.GLOBAL_EXPANDOFRAME_DATA[tIFName] = new Array();
		apex.GLOBAL_EXPANDOFRAME_DATA[tIFName]["startOpen"] = startOpen;
		apex.GLOBAL_EXPANDOFRAME_DATA[tIFName]["outerDiv"] = divObj;

		resizeExpandoFrame( tIFName );

	} else {
		// ----- It's important to explicitly set the .style.display property, ----- \\
		// ----- so that it can be checked later by the show/hide script.      ----- \\

		if ( startOpen ) {
			// ----- Start this expando block open ----- \\
			divObj.style.display = "block";
		} else {
			divObj.style.display = "none";
		}
	}

	return true;
}

// ------------------------------------------------------------ \\
// -----       "ONCLICK" OPERATING CODE FOR EXPANDOS      ----- \\

function expandoText() {
	// ----- the srcElement could be a subtag of <A> (e.g. an image); ----- \\
	// ----- crawl up the DOM until you reach the actual <A> tag.     ----- \\
	var anchor = event.srcElement;
	while ( (anchor != null) && (anchor.tagName != "A") ) {
		anchor = anchor.parentElement;
	}
	if (anchor.tagName != "A") return;

	var divID = anchor.divID;
	var iconIndex = anchor.iconIndex;
	var divTag = findExpandoDiv( anchor, divID );

	if (divTag) {
		// ----- Find the open/close image in the link, if there is one  ----- \\
		// ----- it will be at the end of the <A> tag, so count backward ----- \\
		tPicObj = "";
		for (j=anchor.all.length-1; j >= 0; j-- ) {
			if (anchor.all(j).tagName == "IMG") {
				var tAnchor = unescape(anchor.all(j).src);
				if ( ( tAnchor == unescape(EXPANDO_GRAPHIC[iconIndex]["open"].src) )
				  || ( tAnchor == unescape(EXPANDO_GRAPHIC[iconIndex]["close"].src) )
				  || ( tAnchor == unescape(EXPANDO_GRAPHIC[iconIndex]["openover"].src) )
				  || ( tAnchor == unescape(EXPANDO_GRAPHIC[iconIndex]["closeover"].src) )
				) {
					tPicObj = anchor.all(j);
					j = -1;
				}
			}
		}

		// ----- Use the .style.display property to determine open/closed status    ----- \\
		// ----- It must be set explicitly by the setup code; it defaults to blank. ----- \\
		if (divTag.style.display == "none") {
			divTag.style.display = "block";
			if (tPicObj) {
				tPicObj.src = EXPANDO_GRAPHIC[iconIndex]["close"].src;
			}
		} else if (divTag.style.display == "block") {
			divTag.style.display = "none";
			if (tPicObj) {
				tPicObj.src = EXPANDO_GRAPHIC[iconIndex]["open"].src;
			}
		}

		// ----- need to resize parent frames, if any ----- \\
		//expandoText_nestedFrames( divTag );
		
	}
}

function multiExpandoText() {
	// ----- the srcElement could be a subtag of <A> (e.g. an image); ----- \\
	// ----- crawl up the DOM until you reach the actual <A> tag.     ----- \\
	var anchor = event.srcElement;
	while ( (anchor != null) && (anchor.tagName != "A") ) {
		anchor = anchor.parentElement;
	}
	if (anchor.tagName != "A") return;

	var tDivBase = anchor.DivBase;
	var tDivIndex = anchor.DivIndex;

	// ----- set the radio button to this entry ----- \\
	if ( GLOBAL_MULTIEXPANDOS[tDivBase] > 1 ) {
		document.all[tDivBase][tDivIndex-1].checked = true;
	} else {
		document.all[tDivBase].checked = true;
	}

	for (var i=1; i <= GLOBAL_MULTIEXPANDOS[tDivBase]; i++) {
		var uniqueDivID = tDivBase + "(" + i + ")";
		var tDivObj = document.all[uniqueDivID];

		if (i == tDivIndex) {
			// ----- this is the selected DIV; make visible ----- \\
			tDivObj.style.display = "block";
		} else {
			// ----- turn all others invisible ----- \\
			tDivObj.style.display = "none";
		}

		// ----- need to resize parent frames, if any ----- \\
		expandoText_nestedFrames( tDivObj );
	}
}


function expandoMouseOver() {
	// ----- the srcElement could be a subtag of <A> (e.g. an image); ----- \\
	// ----- crawl up the DOM until you reach the actual <A> tag.     ----- \\
	var anchor = event.srcElement;
	while ( (anchor != null) && (anchor.tagName != "A") ) {
		anchor = anchor.parentElement;
	}
	if (anchor.tagName != "A") return;

	var iconIndex = anchor.iconIndex;

	// ----- Find the open/close image in the link, if there is one  ----- \\
	// ----- it will be at the end of the <A> tag, so count backward ----- \\
	tPicObj = "";
	for (j=anchor.all.length-1; j >= 0; j-- ) {
		var imgObj = anchor.all(j);
		if (imgObj.tagName == "IMG") {
			if ( unescape(imgObj.src) == unescape(EXPANDO_GRAPHIC[iconIndex]["open"].src) ) {
				imgObj.src = EXPANDO_GRAPHIC[iconIndex]["openover"].src;
				j = -1;
			}
			if ( unescape(imgObj.src) == unescape(EXPANDO_GRAPHIC[iconIndex]["close"].src) ) {
				imgObj.src = EXPANDO_GRAPHIC[iconIndex]["closeover"].src;
				j = -1;
			}
		}
	}
}

function expandoMouseOut() {
	// ----- the srcElement could be a subtag of <A> (e.g. an image); ----- \\
	// ----- crawl up the DOM until you reach the actual <A> tag.     ----- \\
	var anchor = event.srcElement;
	while ( (anchor != null) && (anchor.tagName != "A") ) {
		anchor = anchor.parentElement;
	}
	if (anchor.tagName != "A") return;

	var iconIndex = anchor.iconIndex;

	// ----- Find the open/close image in the link, if there is one  ----- \\
	// ----- it will be at the end of the <A> tag, so count backward ----- \\
	tPicObj = "";
	for (j=anchor.all.length-1; j >= 0; j-- ) {
		var imgObj = anchor.all(j);
		if (imgObj.tagName == "IMG") {
			if ( unescape(imgObj.src) == unescape(EXPANDO_GRAPHIC[iconIndex]["openover"].src) ) {
				imgObj.src = EXPANDO_GRAPHIC[iconIndex]["open"].src;
				j = -1;
			}
			if ( unescape(imgObj.src) == unescape(EXPANDO_GRAPHIC[iconIndex]["closeover"].src) ) {
				imgObj.src = EXPANDO_GRAPHIC[iconIndex]["close"].src;
				j = -1;
			}
		}
	}
}

// ------------------------------------------------------------ \\
// -----         SUPPORTING FUNCTIONS FOR EXPANDOS        ----- \\

function findExpandoDiv ( anchorObj, divID ) {
	// ----- If there's a "divID", then find that DIV ID. Otherwise,  ----- \\
	// ----- search forward in the DOM for the next valid target tag. ----- \\
	// ----- Valid:  DIV tag or LI tag with "expando" class           ----- \\
	var divTag = "";
	if (divID) {
		divTag = document.all[divID];
	} else {
		for (var j=anchorObj.sourceIndex+1; j < document.all.length; j++ ) {
			var tg = document.all(j);
			if ( (tg.tagName == "DIV" || tg.tagName == "LI") &&
			      tg.className.toLowerCase() == "expando" ) {
				divTag = tg;
				j = document.all.length;
			}
		}
	}
	return divTag;
}

function resizeExpandoFrame ( frameName ) {
	// ----- Note: passing a string (frameName), rather than a window ----- \\
	// ----- handle, allows us to set a callback with setTimeout().   ----- \\

	var iframeObj = document.frames(frameName);
	if ( (iframeObj.document != null ) &&
	     (iframeObj.document.readyState == "complete") &&
	     (iframeObj.document.body != null) )  {
		// ----- page is finished loading; polish it off ----- \\

		// ----- find top-level frame that's not an "_expando_" frame ----- \\
		var tTop = iframeObj;
		while (tTop.name.indexOf("_expando_") >= 0) {
			tTop = tTop.parent;
		}
		// ----- find the window width less the nested margins ----- \\
		var parentWidth = tTop.document.body.clientWidth;
		var tWin = iframeObj;
		while (tWin != tTop) {
			var scrollbarWidth = tWin.document.body.offsetWidth - tWin.document.body.clientWidth;
			parentWidth = parentWidth - tWin.document.body.leftMargin;
			parentWidth = parentWidth - tWin.document.body.rightMargin;
			parentWidth = parentWidth - scrollbarWidth;
			parentWidth = parentWidth - 3;
			tWin = tWin.parent;
		}
		var parentHeight = apex.document.body.clientHeight;
		var maxWidthRatio = 1.0;
		var maxWidth = parentWidth * maxWidthRatio;

		// ----- (resize once to SET the scrollHeight, once to USE the scrollHeight) ----- \\
		// ----- requires third pass because of in-line rewriting of include topics  ----- \\
		try {		
		    iframeObj.resizeTo(maxWidth, iframeObj.document.body.scrollHeight);
		    iframeObj.resizeTo(maxWidth, iframeObj.document.body.scrollHeight);
		    iframeObj.resizeTo(maxWidth, iframeObj.document.body.scrollHeight);
		}
		catch (e) {
			// produced script error, prevent by using try/catch. taskID:182337 
		}

		// ----- since we know scroll bars are unnecessary, turn them off ----- \\
		iframeObj.document.body.scroll = 'no';

		// ----- this is the final size; now bring DIV back inline ----- \\
		apex.GLOBAL_EXPANDOFRAME_DATA[frameName]["outerDiv"].style.position = "static";
		if ( !(apex.GLOBAL_EXPANDOFRAME_DATA[frameName]["startOpen"]) ) {
			apex.GLOBAL_EXPANDOFRAME_DATA[frameName]["outerDiv"].style.display = "none";
		}
	} else {
		setTimeout("resizeExpandoFrame('" + frameName + "')", 100);
	}
}

function expandoText_nestedFrames ( divObj ) {
	// ----- if this is inside an included frame,     ----- \\
	// ----- keep expanding the parent frames to fit. ----- \\
	var tMe = self;
	while ( tMe.name.indexOf("_expando_") >= 0 ) {
		// -----
		tMe.resizeTo(tMe.document.body.scrollWidth, tMe.document.body.scrollHeight);
		tMe = tMe.parent;
	}
	// ----- if we're expanding, and the bottom will  ----- \\
	// ----- go past the bottom of the window, then   ----- \\
	// ----- scroll it up so it's visible.            ----- \\
	if (divObj.style.display == "block") {
		if (divObj.offsetHeight < document.body.clientHeight) {
			// ----- if the expando section is bigger than the window, don't bother ----- \\
			var tZoneBottom = divObj.offsetTop + divObj.offsetHeight;
			var tZoneY = tZoneBottom - document.body.scrollTop;
			if (tZoneY > document.body.clientHeight) {
				window.scrollTo( 0,document.body.scrollTop + (tZoneY - document.body.clientHeight) );
			}
		}
	}
}

// ------------------------------------------------------------ \\
// ============================================================ \\
// =====                  POPUP WINDOWS                   ===== \\
// ============================================================ \\
// Works with v2.3 of _updated.js.

// ----- set DEPTH_LIMIT to -1 if you want infinite popups;        ----- \\
// ----- otherwise it will be the maximum number of nested popups. ----- \\
DEPTH_LIMIT = -1;

// ----- user numeric array indexes to make array code compatible with earlier browsers. ----- \\
// ----- probably wasted effort, since some part of the DOM is bound to be incompatible. ----- \\
POPUP_OBJ	= 0;
CONTAIN_OBJ	= 1;
SHADOW_OBJ	= 2;
CONTENT_OBJ	= 3;
POPUP_IDX	= 4;
POPUP_VISIBLE	= 5;

if ((window.name.substring(0,7) != "popup__") && (window.name.substring(0,9) != "_expando_") && (window.name != "HiddenPopup")) {
	apex.globalPopupList = null;
}

function MarkPopup () {
	apex.globalMouseX = event.x;
	apex.globalMouseY = event.y;
}

function Popup ( targetURL ) {

// celia - remove Nov 21, 2005
//	var fixedURL = FixURL(targetURL);
//	if (fixedURL) { MakePopup(fixedURL); }

	MakePopup(targetURL);  // celia added
}

function FixURL( targetURL ) {
	myloc = self.location.toString();
	if (myloc.indexOf("::")>=0) {
	// ----- This is a CHM file ----- \\
		if (targetURL.indexOf("::")>=0) {
		// ----- You are calling a popup in a CHM file ----- \\
			t1 = myloc.substring(0,myloc.indexOf("::"));
			t2 = t1.substring(0,t1.lastIndexOf("\\")+1);
			newURL = t2 + targetURL;
		} else {
		// ----- Just a regular popup call ----- \\
			newURL = targetURL;
		}
	} else {
		// ----- this is a file on the hard drive ----- \\
		if (window.TOPIC_EXTPATH) {
			// ----- This is a patched file ----- \\
			TOPIC_EXTPATH = TOPIC_EXTPATH.replace(/\//g,"\\");
			if (targetURL.indexOf("::")>=0) {
				// ----- You already know the name of the CHM file ----- \\
				newURL = ("ms-its:" + TOPIC_EXTPATH + targetURL);
			} else {
				// ----- find the subfolder and make sure that "chmFile" is defined ----- \\
				try {
					t = myloc.substr(myloc.indexOf(TOPIC_UPDATEPATH)+TOPIC_UPDATEPATH.length,myloc.length);
					t = t.substr(0,t.lastIndexOf("/")+1);
					newURL = ("ms-its:" + TOPIC_EXTPATH + chmFile + t + targetURL);
				}
				catch (e) {
					newURL = "";
				}
			}
		} else {
			// ----- don't know anything about the environment ----- \\
			newURL = targetURL;
		}
	}
	return newURL;
}

function MakePopup ( targetURL ) {
	if (DEPTH_LIMIT == 0) {	open(targetURL,"_self"); return; }
	if (apex.globalPopupList == null) { apex.globalPopupList = new Array(); }

	var hPopup = null;
	var tLen = apex.globalPopupList.length;
	if (DEPTH_LIMIT == tLen) {
		apex.globalPopupList[tLen-1][POPUP_OBJ].location = targetURL;
		hPopup = apex.globalPopupList[tLen-1][POPUP_OBJ];
		FinishPopup(tLen-1);
	} else {
		for (var i=0; i<apex.globalPopupList.length; i++) {
			// ----- the window is already defined; maybe it's empty ----- \\
			if (!apex.globalPopupList[i][POPUP_VISIBLE]) {
				apex.globalPopupList[i][POPUP_OBJ].location = targetURL;
				hPopup = apex.globalPopupList[i][POPUP_OBJ];
				FinishPopup(i);
				i = apex.globalPopupList.length+1;
			}
		}
	}
	if (hPopup == null) {
		if (apex.globalPopupList.length == 0) {
			document.body.onclick = ParentClosePopups;
//			PETE:	Why is this code even here? If there's no "globalPopupList",
//				then there are no _expando_ frames. Seems simple. Test.
//			for (var j=1; j <= apex.GLOBAL_EXPANDO_FRAMES; j++) {
//				document.frames["_expando_"+j].document.body.onclick = ParentClosePopups;
//			}
		}
		hPopup = CreatePopup(targetURL);
	}
}

function CreatePopup ( targetURL ) {
	// ----- Need to create a new Popup Window ------ \\

	var idx = apex.globalPopupList.length;

	var t = "";
	t += "<div id=\"contain"+idx+"\" style=\"visibility:hidden;\">";
	t += "<div id=\"shadow_"+idx+"\" style=";
	t +=   "\"position:absolute; top:4; left:4; background-color:#C0C0C0;\"></div>";
	t += "<div id=\"content"+idx+"\" style=";
	t +=   "\"position:absolute; top:0; left:0; background-color:#FFFFFF;";
	t +=   " border:1px #000000 outset;\">";
	t += "<iframe name=\"popup__"+idx+"\" src=\"" + targetURL + "\" frameborder=\"0\" scrolling=\"auto\"></iframe>";
	t += "</div></div>";
	document.body.insertAdjacentHTML("beforeEnd", t);

	var popupObjArray = new Array();
	popupObjArray[POPUP_OBJ] = eval("popup__"+idx);
	popupObjArray[CONTAIN_OBJ] = eval("contain"+idx);
	popupObjArray[SHADOW_OBJ] = eval("shadow_"+idx);
	popupObjArray[CONTENT_OBJ] = eval("content"+idx);
	popupObjArray[POPUP_IDX] = idx;
	popupObjArray[POPUP_VISIBLE] = false;

	apex.globalPopupList[idx] = popupObjArray;

	popupObjArray[POPUP_OBJ].document.location = targetURL;
	FinishPopup(idx);

	return popupObjArray[POPUP_OBJ];
}

function FinishPopup ( idx ) {
	popupObj = apex.globalPopupList[idx][POPUP_OBJ];
	if ( (popupObj.document.readyState == "complete") &&
	     (popupObj.document.body != null) )  {
		// ----- page is finished loading; polish it off ----- \\

		fixPopupTopicLinks(popupObj.document);
		popupObj.document.body.onclick = ClosePopups;

		ResizePopup(idx);

		apex.globalPopupList[idx][CONTAIN_OBJ].style.visibility = "visible";
		apex.globalPopupList[idx][POPUP_VISIBLE] = true;

		MovePopup(idx);

	} else {
		setTimeout("FinishPopup("+idx+")", 1000);
	}
}

function MovePopup ( idx ) {
	popupObj = apex.globalPopupList[idx][POPUP_OBJ];
	contentObj = apex.globalPopupList[idx][CONTENT_OBJ];
	shadowObj = apex.globalPopupList[idx][SHADOW_OBJ];

	var nWidth = popupObj.document.body.offsetWidth;
	var nHeight = popupObj.document.body.offsetHeight;
	var parentWidth = document.body.clientWidth - 6;
	var parentHeight = document.body.clientHeight - 16;

	// ----- where would we like the popup? Centered beneath the mouse ----- \\
	var nLeft = apex.globalMouseX - (nWidth/2);
	var nTop = apex.globalMouseY + document.body.scrollTop;

	// ----- now bring it in to fit in the parent window properly ----- \\
	if ( (apex.globalMouseX + (nWidth/2)) > parentWidth ) {
		nLeft = parentWidth - nWidth;
	}
	if ( apex.globalMouseX < (nWidth/2) ) {
		nLeft = 2;
	}
	if ( (apex.globalMouseY + nHeight ) > parentHeight ) {
		nTop = parentHeight - nHeight + document.body.scrollTop;
	}

	contentObj.style.left = nLeft;
	contentObj.style.top = nTop;

	// ----- update shadow info ----- \\
	shadowObj.style.width = contentObj.style.width;
	shadowObj.style.height = contentObj.style.height;
	shadowObj.style.left = nLeft + 6;
	shadowObj.style.top = nTop + 6;

}

function ResizePopup ( idx ) {
	popupObj = apex.globalPopupList[idx][POPUP_OBJ];

	parentWidth = document.body.clientWidth;
	parentHeight = document.body.clientHeight;
	maxWidthRatio = 0.8;
	maxHeightRatio = 0.8;
	maxWidth = parentWidth * maxWidthRatio;
	maxHeight = parentHeight * maxHeightRatio;
	parentSlope = parentHeight/parentWidth;
	idealSlope = 0.65;

	// ----- start popup size at the max size, constrained by the ideal ratio ----- \\
	var popX = maxWidth;
	var popY = maxHeight;
	if (parentSlope > idealSlope) {
		popY = popX * idealSlope;
	} else {
		popX = popY / idealSlope;
	}

	// ----- test shrinking the Y to the minimum and see where that gets us ----- \\
	// ----- (resize once to SET the scrollHeight, once to USE the scrollHeight) ----- \\
	popupObj.resizeTo(popX, popupObj.document.body.scrollHeight);
	popupObj.resizeTo(popX, popupObj.document.body.scrollHeight);
	var minY = popupObj.document.body.scrollHeight;

	if (minY > popY) {
		// ----- content doesn't fit the maximum "ideal ratio" window, ----- \\
		// ----- so let's dissolve ideal ratio constraint and try again ----- \\
		popupObj.resizeTo(maxWidth, popupObj.document.body.scrollHeight);
		popupObj.resizeTo(maxWidth, popupObj.document.body.scrollHeight);
		var minY = popupObj.document.body.scrollHeight;

		if (maxHeight > minY) {
			// ----- there's still room to maneuver; ----- \\
			// ----- let's try the parent ratio ----- \\
			popupObj.resizeTo(maxWidth, maxHeight);
			qsortShrinkPopup( popupObj, 0, 0 );

			// ----- since we know scroll bars are unnecessary, turn them off ----- \\
			// ----- in case another popup DIV is added to the bottom of it ----- \\
			popupObj.document.body.scroll = 'no';
		} else {
			// ----- scroll bars are inevitable; make the window fit ----- \\
			popupObj.resizeTo(maxWidth, maxHeight);
		}
	} else {
		// ----- content does fit within the "ideal ratio", ----- \\
		// ----- now how small can we make it before scroll bars appear ----- \\
		// ----- first, reset it to fit the ideal ratio once again ----- \\
		popupObj.resizeTo(popX,popY);
		qsortShrinkPopup ( popupObj, 0, 0 );

		// ----- since we know scroll bars are unnecessary, turn them off ----- \\
		// ----- in case another popup DIV is added to the bottom of it ----- \\
		popupObj.document.body.scroll = 'no';
	}

}

function qsortShrinkPopup ( popupObj, constrainX, constrainY ) {
	// ----- this function will shrink the popupObj window towards ----- \\
	// ----- (constrainX, constrainY) using a binary qsort search ----- \\
	// ----- if called initially with 0,0 as the constraint, then ----- \\
	// ----- the aspect ratio of the window will be preserved. ----- \\

	var nowX = popupObj.document.body.clientWidth;
	var nowY = popupObj.document.body.clientHeight;

	var tryX = nowX - ((nowX - constrainX) / 2);
	var tryY = nowY - ((nowY - constrainY) / 2);
	if ( (Math.abs(nowX - constrainX) < 16) || (Math.abs(nowY - constrainY) < 16) ) {
		// ----- too small a difference; time to escape ----- \\
		return;
	}

	popupObj.resizeTo(tryX, tryY);

	if (popupObj.document.body.scrollHeight > popupObj.document.body.clientHeight) {
		// ----- (tryX,tryY) is too small; reset window and make "tryX/Y" the constraint ----- \\
		popupObj.resizeTo(nowX, nowY);
		qsortShrinkPopup( popupObj, tryX, tryY );
	} else {
		// ----- (tryX, tryY) is still legal; keep going ----- \\
		qsortShrinkPopup( popupObj, constrainX, constrainY );
	}
}


function fixPopupTopicLinks ( targetContainer ) {
	var anchors = targetContainer.all.tags("A");
	for (var i=0; i<anchors.length; i++) {
		var t = anchors[i].href.toLowerCase();
		if (t.indexOf("javascript:") == -1) {
			if (anchors[i].target == "") {
				anchors[i].target = "_parent";
			}
		}
	}
}

function ClosePopups() {
	subPops = apex.globalPopupList.length + 1;
	for (var i=0; i<apex.globalPopupList.length; i++) {
		var hPopup = apex.globalPopupList[i][POPUP_OBJ];
		if ((hPopup.event != null) && (hPopup.event.type == "click")) {
			// ----- Found the popup with the event in it ----- \\

			var myElement = hPopup.event.srcElement;
			while ((myElement.tagName != "BODY") && (myElement.tagName != "A")) {
				myElement = myElement.parentElement;
			}

			if (myElement.tagName != "A") {
				// ----- If it's not a link, vanish the current window ----- \\
				apex.globalPopupList[i][CONTAIN_OBJ].style.visibility = "hidden";
				apex.globalPopupList[i][POPUP_VISIBLE] = false;
				subPops = i+1;
			} else {
				// ----- Otherwise, vanish a subwindow ----- \\
				if (i+1 < apex.globalPopupList.length) {
					apex.globalPopupList[i+1][CONTAIN_OBJ].style.visibility = "hidden";
					apex.globalPopupList[i+1][POPUP_VISIBLE] = false;
					subPops = i+2;
				}
			}
			// ----- any sub-(sub-)popups can be eliminated; their objects will die ----- \\

			if (subPops<apex.globalPopupList.length) {
				apex.globalPopupList.length = subPops;
			}

			// ----- end loop early ----- \\
			i = apex.globalPopupList.length;
		}
	}
}

function ParentClosePopups() {
	if ( apex.globalPopupList.length > 0 ) {
		// ----- Vanish the primary popup window and truncate popup object list ----- \\
		apex.globalPopupList[0][CONTAIN_OBJ].style.visibility = "hidden";
		apex.globalPopupList[0][POPUP_VISIBLE] = false;
		apex.globalPopupList.length = 1;
	}
}


// ------------------------------------------------------------ \\
// ============================================================ \\
// =====             "RATE THIS TOPIC" CODE               ===== \\
// ============================================================ \\

/*--------------------------------------------------------
 * function fnLoadAndRunFeedbackInfo
 *
 * Description
	Called to start loading the ACE file - ACE will read 
	it as XML.  The function fnLoadStateChange() called
	as the load status changes.  When the status is 4, the
	XML file has been loaded and is ready for reading
 *
**-------------------------------------------------------*/
function fnLoadAndRunFeedbackInfo(nScore) {
	gnScore = nScore;
	FeedbackInfo.load("qbx://ACEAccess/GetObject.xml?Type=URL&ID=FeedbackURL");
}

/*--------------------------------------------------------
 * function fnLoadStateChange
 *
 * Description
	Called for each ace xml file load status change.
	When status is 4 load is done.
 *
**-------------------------------------------------------*/
function fnLoadStateChange() {
	if (FeedbackInfo.XMLDocument.readyState == 4) {
		fnRunFB(gnScore);
	}
}

/*--------------------------------------------------------
 * function fnRunFB
 *
 * Description
	Called After the ACE file is done loading, submits
	feedback.
	
	using the form field values not the QBCommand values
	refer the the feedback EDD for details.
 *
**-------------------------------------------------------*/
function fnRunFB(nScore) {

	/////////////////////////////////////////////////
	//
	// Get Submit URL from ACE
	//
	/////////////////////////////////////////////////
	var currNode;
	currNode = 
		FeedbackInfo.XMLDocument.selectSingleNode("URL[@ID='FeedbackURL']/@Address");

	if (!currNode) {
		return;
	}

	document.yesno_feedback_form.action = currNode.text;

	////////////////////////////////////////////////////////////
	//
	// populate all the inputs for the form, then submit
	// start w/telling the server not to return with a 
	// UI (html), Yes votes display our own thank you
	// access point, feedback type
	//
	// refer to feedback EDD for values
    // http://qube.intuit.com/library/docs/Reported%20Feedback%20Collection%20FastTrack%20EDD.doc 
	////////////////////////////////////////////////////////////
	var sUI = "<input type=hidden name=ui value=false>";
	sUI += "<input type=hidden name=submit.x value=1>";
	var sAP = "<input type=hidden name=access_point value=help>";
	var sFB = "<input type=hidden name=feedback_type value=help_suggestion>";
	ui_div.innerHTML =  sUI;
	access_point_div.innerHTML = sAP;
	feedback_type_div.innerHTML = sFB;

	////////////////////////////////////////////////////////////
	//
	// get the CHM name and topic name
	//
	////////////////////////////////////////////////////////////
	var doc = unescape(document.URL);
	var cut_start = doc.lastIndexOf("\\") + 1;
	var to_colon = doc.lastIndexOf("::");
	var from_colon = doc.lastIndexOf("::") + 2;
	var to_end = doc.lastIndexOf(".html");
	var chm_file = doc.substring(cut_start,to_colon);
	var file_name = doc.substring(from_colon,to_end);
	var chmText =	
		"<input type=hidden name=hlp_doc_chm value=" + chm_file + ">";
	var topicText =	
		"<input type=hidden name=hlp_doc_name value=" + file_name + ">";
	doc_chm.innerHTML =  chmText;
	doc_name.innerHTML =  topicText;

	////////////////////////////////////////////////////////////
	//
	// get the SKU/flavor/subproduct
	//
	////////////////////////////////////////////////////////////
	var objLocator	= new ActiveXObject("QuickBooks.CoLocator");
	var objProfile	= objLocator.Create("QBPrefs.AppParameters"); 
	var skuText		= "<input type=hidden name=subproduct value=" 
						+ objProfile.Flavor + ">";
	sku.innerHTML	= skuText;

	////////////////////////////////////////////////////////////
	//
	// get Product, Version and Release
	//
	////////////////////////////////////////////////////////////
	var ver = objProfile.ProductVersion;  
	var rel = objProfile.Release; 
	var sProductText =	"<input type=hidden name=product value=quickbooks>";
	var sVersionText =	"<input type=hidden name=version value=" + 
				ver + ">";
	var sReleaseText =	"<input type=hidden name=release value=" + 
				rel + ">";

	product_div.innerHTML =	sProductText;
	version_div.innerHTML = sVersionText;
	release_div.innerHTML = sReleaseText;

	////////////////////////////////////////////////////////////
	//
	// add rating to form... always 1, since 'yes' was clicked, 
	// also add novote/yesvote label to name
	//
	////////////////////////////////////////////////////////////
	var ratingText =  "<input type=hidden name=hlp_score value='" + gnScore + "'>";

	ratingText += "<input type=hidden name='hlp_name' value='";
	if (gnScore == 1) {
		ratingText +=  "yesvote'>";
	} else {
		ratingText +=  "novote'>";
	}
	rating.innerHTML =  ratingText;

	////////////////////////////////////////////////////////////
	//
	// get document date, get from document object.
	//
	////////////////////////////////////////////////////////////
	var filedate = 	CHM_DATE;	
	var docdateText =	"<input type=hidden name=hlp_doc_date value=" + filedate + ">";
	doc_date.innerHTML =  docdateText;

	////////////////////////////////////////////////////////////
	//
	// get last search
	//
	////////////////////////////////////////////////////////////
	var chmname;
	var awHelpSystem;
	var flavor = objProfile.Flavor;
	 if ( flavor.search(/atom/) >= 0  ) { 
		chmname = "atomcore.chm"
	 } else {
		chmname = "core.chm"
	 }
	 
	awHelpSystem =  TOPIC_EXTPATH + chmname;
	 
	var sSeedQuestion = aw.GetSeedQuery (awHelpSystem);
	var lastsearchText =	
		"<input type=hidden name=hlp_last_search value='" + 
		sSeedQuestion + "'>";
	last_search.innerHTML =  lastsearchText;
   
	////////////////////////////////////////////////////////////
	//
	// submit the form to hidden frame, remove the buttons, and 
	// replace with the "thank you" message
	//
	////////////////////////////////////////////////////////////
	document.yesno_feedback_form.submit(); 

	fnHideVoteButtons();


	////////////////////////////////////////////////////////////
	//
	// If no vote then allow user to enter suggestion, along
	// with the novote we just entered
	//
	////////////////////////////////////////////////////////////
	if (nScore == 0) {
		fnRunNoFB();
	}

} // fnRunFB()

function fnHideVoteButtons() {
	var t = "";
	t+= "<table class='feedback'><tr><td width='15'><img src='" + ICON_HELP_FEEDBACK + "' border='0' align='left'>"
	t+= "<td><b>Thanks for your feedback!</table>";
	yes_no_feedback.innerHTML = t;
}


function makeFeedbackAndHelpSupportLink( divObj ) {
	var t = "";
	t += "<br><br><table class='feedback'>";
	t += "<tr><td width='30' align='right'><a href='javascript:run_qbcommand(\"qbw:informationandsupport\");' align='right'><img src='" + ICON_HELP_SUPPORT + "' border='0' align='right'></a>";
	t += "<td><a href='javascript:run_qbcommand(\"qbw:informationandsupport\");'>" + TEXT["helpsupport_linktext"] + "</a><br></table>";
	t += "<IFRAME STYLE='border-width:0px; margin:0px; padding:0px; visibility:hidden; width:1px; height:1px;' name='submitTarget' ></IFRAME>";
    t +="<div id=\"yes_no_feedback\"></div>";
	t += "<form name='yesno_feedback_form' method='POST' enctype='text/html' target='submitTarget'>";
	t += "<div id='ui_div'></div>";
	t += "<div id='access_point_div'></div>";
	t += "<div id='feedback_type_div'></div>";
	t += "<div id='product_div'></div>";
	t += "<div id='version_div'></div>";
	t += "<div id='release_div'></div>"
	t += "<div id='sku'></div>";
	t += "<div id='doc_name'></div>";
	t += "<div id='doc_chm'></div>"	;
	t += "<div id='doc_date'></div>";
	t += "<div id='rating'></div>";
	t += "<div id='last_search'></div>";
	t += "</form>";
	divObj.innerHTML = t;

	var s = "";


	s += "<xml 	id='FeedbackInfo' onreadystatechange='fnLoadStateChange()'></xml>";
	s += "<table class='feedback'>";
	s += "<tr><td width='30'><img src='" + ICON_HELP_FEEDBACK + "' border='0' align='right'>";
	s += "<td align='left' border='0'><b>Did this Help topic provide you with the information you needed?</b>";
	s += "</table>";
	s += "<table class='feedback'><tr><td width='30'><td>";
	
	// get CHM name, need to treat FAQHelp.CHM different for yes/no buttons because the layout
	// of the dir structure in source control is different. (should fix this) MTK 10-4-1004
	var doc = unescape(document.URL);
	var cut_start = doc.lastIndexOf("\\") + 1;
	var to_colon = doc.lastIndexOf("::");
	var from_colon = doc.lastIndexOf("::") + 2;
	var to_end = doc.lastIndexOf(".html");
	var chm_file = doc.substring(cut_start,to_colon);

	if ( chm_file.toUpperCase() == "FAQHELP.CHM" ) {
		s += "<a href='javascript:click_yes();'><img src='/feedback_yes.gif' border='0'></a>&nbsp;&nbsp;";
		s += "<a href='javascript:click_no();'><img src='/feedback_no.gif' border='0'></a>";
	} else {
		s += "<a href='javascript:click_yes();'><img src='../feedback_yes.gif' border='0'></a>&nbsp;&nbsp;";
		s += "<a href='javascript:click_no();'><img src='../feedback_no.gif' border='0'></a>";
	}

	s += "<tr><td width='30'>";
	s += "<td align='left' valign='top' border='0'><font size=-4>Requires an Internet connection.</font>";	
	s += "</table><br><br>";
	yes_no_feedback.innerHTML = s;

} // makeFeedbackAndHelpSupportLink()

function click_yes (){
	fnLoadAndRunFeedbackInfo(1);
}

function click_no (){
	fnLoadAndRunFeedbackInfo(0);
} // click_no

function fnRunNoFB() {

	// Just launch the ratetopic feedback form.
	var doc = unescape(document.URL);
	var cut_start = doc.lastIndexOf("\\") + 1;
	var to_colon = doc.lastIndexOf("::");
	var from_colon = doc.lastIndexOf("::") + 2;
	var to_end = doc.lastIndexOf(".html");
	var chm_file = doc.substring(cut_start,to_colon);
	var file_name = doc.substring(from_colon,to_end);

	////////////////////////////////////////////////////////////
	//
	// Call the QBCommand for feedback - note the parameters
	// passed match the QBCommand params and not the forms params
	// as in click_yes().
	//
	////////////////////////////////////////////////////////////
	var sQbwCommand="qbw:helpfeedback?fb=help_suggestion&tv=0&hn=novote_followup&chm=" + 
			chm_file + "&dn="+ file_name;

	run_qbcommand(sQbwCommand); 
	
	// remove the buttons, and replace with the "thank you" message
	fnHideVoteButtons();
} // fnRunNoFB()

// ------------------------------------------------------------ \\
// ============================================================ \\
// =====           ACTIVEX QUICKBOOKS COMMANDS            ===== \\
// ============================================================ \\

function qbcommand ( param ) {
	var current_url = document.URL;
	var cut_start = 0;
	var cut_end = current_url.lastIndexOf("::");
	var curpath = current_url.substring(cut_start,cut_end);
	var window_path = curpath + "::/qbcommand_msg.html";
	var w = window.open(window_path,"temp_window","width=4,height=1 top=10000 left=10000");
	w.close();
	var ret = xobj.RunQBCommand(param);
}

function qbcommand2 ( param ) {
	var current_url = document.URL;
	var cut_start = 0;
	var cut_end = current_url.lastIndexOf("::");
	var curpath = current_url.substring(cut_start,cut_end);
	var window_path = curpath + "::/qbcommand_msg.html";
	var w = window.open(window_path,"temp_window","width=4,height=1 top=10000 left=10000");
	w.close();
	var ret = xobj.RunQBCommand2(param);
}


function run_qbcommand ( param )	{ var ret = xobj.RunQBCommand(param); }
function qbcommand_redirect ( param )	{ var ret = xobj.RunQBCommand(param); }
function openURL ( param )		{ var ret = xobj.OpenURL(param); }
function QBURL ( param )		{ var ret = xobj.OpenURL(param); }
function displaytopic ( param )		{ var ret = xobj.DisplayHTMLHelpTopic(param); }


// ------------------------------------------------------------ \\
// ============================================================ \\
// =====         GENERATE HELP FOR THIS TOOLKIT           ===== \\
// ============================================================ \\

function displaySKU() {
	var t = "";
	t += "<div style=\"font-family: 'MS Sans Serif'; font-size: 10pt; font-weight: bold;\"><hr>";
	t += "<font color='darkred'>SHOW THE DETECTED SKU INFORMATION</font> <br>";
	t += "Stratum: '" + QUICKBOOKS_VERSION.Stratum + "' <br>";
	t += "Flavor: '" + QUICKBOOKS_VERSION.Flavour + "' <br>";
	if (QUICKBOOKS_VERSION.Error) {
		t += "Error: " + QUICKBOOKS_VERSION.Error + " <br>";
	}
	t += "<hr></div>";
	return t;
}

function displayAllSKUs() {
	var t = "";
	t += "<div style=\"font-family: 'MS Sans Serif'; font-size: 10pt; font-weight: bold;\"><hr>";
	t += "<font color='darkred'>LIST ALL SKU TAGS</font> <br>";
	t += "<font color='darkred'>(\"Strata\")</font> <br>";
	for (var i=0; i < QUICKBOOKS_ALLSTRATA.length; i++ ) {
		t += QUICKBOOKS_ALLSTRATA[i];
		if (QUICKBOOKS_ALLSTRATA[i] == "PREMIER" || QUICKBOOKS_ALLSTRATA[i] == "ENTERPRISE") {
			t += " (includes flavors)";
		}
		t += " <br>";
	}
	t += "<br>";
	t += "BEL (synonym for ENTERPRISE) <br>";
	t += "QBES (synonym for ENTERPRISE) <br>";
	t += "<br>";
	for (var i=1; i < QUICKBOOKS_ALLSTRATA.length; i++ ) {
		t += QUICKBOOKS_ALLSTRATA[i] + "+ = ";
		for (var j=i; j < QUICKBOOKS_ALLSTRATA.length; j++) {
			t += QUICKBOOKS_ALLSTRATA[j];
			if ( j < QUICKBOOKS_ALLSTRATA.length-1 ) { t += ", "; }
		}
		t += " <br>";
	}
	t += "<br>";
	for (var i=0; i < QUICKBOOKS_ALLSTRATA.length-1; i++ ) {
		t += QUICKBOOKS_ALLSTRATA[i] + "- = ";
		for (var j=0; j <= i ; j++) {
			t += QUICKBOOKS_ALLSTRATA[j];
			if ( j < i ) { t += ", "; }
		}
		t += " <br>";
	}
	t += "<br>";
	t += "PREMIER: = PREMIER without any flavor <br>";
	t += "ENTERPRISE: = ENTERPRISE without any flavor <br>";
	t += "<br>";

	t += "<font color='darkred'>(\"Flavors\")</font> <br>";
	for (var i=0; i < QUICKBOOKS_ALLFLAVOURS.length; i++ ) {
		t += QUICKBOOKS_ALLFLAVOURS[i] + " <br>";
	}
	t += "<hr></div>";
	return t;
}

function displayAllMods() {
	var t = "";
	t += "<div style=\"font-family: 'MS Sans Serif'; font-size: 10pt; font-weight: bold;\"><hr>";
	t += "<font color='darkred'>LIST ALL TEXT 'MODS'</font> <br>";
	t += "<font color='blue'>AN</font> - add 'a' or 'an' prefix <br>";
	t += " &nbsp; Special case-sensitive versions: <br>";
	t += " &nbsp; <font color='blue'>a/n</font> - add 'a' or 'an' prefix <br>";
	t += " &nbsp; <font color='blue'>A/n</font> - add 'A' or 'An' prefix <br>";
	t += " &nbsp; <font color='blue'>A/N</font> - add 'A' or 'AN' prefix <br>";
	t += "<font color='blue'>CAPALL</font> - capitalize first letter of every word <br>";
	t += "<font color='blue'>CAPFIRST</font> - capitalize first letter of phrase <br>";
	t += "<font color='blue'>PLURAL</font> - make variable plural <br>";
	t += "<font color='blue'>POSS</font> - make variable possessive <br>";
	t += "<font color='blue'>UPPER</font> - make text upper case <br>";
	t += "<font color='blue'>LOWER</font> - make text lower case <br>";
	t += "<font color='blue'>2TEXT</font> - convert a number (15) to text (fifteen) <br>";
	t += "<font color='blue'>ORDINAL</font> - make number ordinal (15th or fifteenth) <br>";
	t += "<hr></div>";
	return t;
}

function displayHelp() {
	var t = "";
	t += "<div style=\"font-family: 'Arial'; font-size: 10pt;\"><hr>";
	t += "<b><font color='darkred'>INTUIT'S HTML TOOLKIT HELP</font></b> <br>";
	t += "<b><font color='blue'>&lt;listallskus&gt;</font></b> - display a report of all SKU codes available. <br>";
	t += "<b><font color='blue'>&lt;listallmods&gt;</font></b> - display a report of all text mods for variables. <br>\n";

	t += "<p><b><u> Conditional text syntax: </u></b><br>";
	t += "<b>&lt;p <font color='green'>skus=\"PRO,PREMIER\"</font>&gt;</b><br>";
	t += "- this paragraph will only appear in Pro or Premier. <br>";
	t += "<b>&lt;p <font color='green'>skus=\"PRO+\"</font>&gt;</b><br>";
	t += " - this paragraph will appear in Pro or higher (Pro, Premier, Enterprise). <br>";
	t += "<b>&lt;p <font color='green'>skus=\"PRO-\"</font>&gt;</b><br>";
	t += " - this paragraph will only appear Pro or lower (Atom, Basic, Pro). <br>";
	t += "<b>&lt;p <font color='green'>skus=\"PREMIER:\"</font>&gt;</b><br>";
	t += " - this paragraph will only appear Premier without a flavor. <br>";
	t += "<b>&lt;p <font color='green'>skus=\"NOT(PREMIER,CONTRACTOR)\"</font>&gt;</b><br>";
	t += " - this paragraph will only appear if the build is not Premier and not Contractor. <br>";
	t += "</p>\n";

	t += "<p><b><u> Variable syntax: </u></b><br>";
	t += "<b>&lt;var <font color='green'>name=\"CustomerTerm\"</font>&gt; client &lt;/var&gt;</b><br>";
	t += "- the word <i>client</i> will be replaced with whatever $CustomerTerm is set to at runtime. <br>";
	t += "<b>&lt;var name=\"CustomerTerm\" <font color='green'>mods=\"AN,CAPALL\"</font>&gt; client &lt;/var&gt;</b><br>";
	t += "- the $CustomerTerm (<i>customer</i>, for example) will be displayed as \"<i>A Customer</i>\". <br>";
	t += "<b>&lt;var <font color='green'>mods=\"AN,CAPALL\"</font>&gt; client &lt;/var&gt;</b><br>";
	t += "- without a variable, the mods will be applied to the text: \"<i>A Client</i>\". <br>";
	t += "<b>&lt;var <font color='green'>money</font>&gt; 10,000 &lt;/var&gt;</b><br>";
	t += "- a special mod, <b>money</b>, will place the appropriate currency mark in the right location. <br>";
	t += "- it can be used in conjunction with all the others. <br>";
	t += "</p>\n";

	t += "<p><b><u> IREFs: \"Intelligent\" References </u></b><br>";
	t += "<b>&lt;a <font color='green'>iref=\"other_topic.html\"</font>&gt;click here&lt;/a&gt;</b><br>";
	t += "- an IREF can be used just like a normal HREF. <br>";
	t += "<b>&lt;a iref=\"other_topic.html\" <font color='green'>targetskus=\"PREMIER\"</font>&gt;click here&lt;/a&gt;</b><br>";
	t += "- you can specify a list of valid SKUs for the target. <br>";
	t += "- if the current SKU is valid, the link will work normally. If not, it appears as plain text. <br>";
	t += "<b>&lt;a <font color='green'>popup=\"other_topic.html\"</font> targetskus=\"PREMIER\"&gt;click here&lt;/a&gt;</b><br>";
	t += "- if you use <b>popup</b> in place of <b>iref</b>, the target will appear in a popup window. <br>";
	t += "</p>\n";

	t += "<p><b><u> \"Expando\" Text and Files </u></b><br>";
	t += "<b>&lt;a <font color='green'>expando</font>&gt;click here&lt;/a&gt;</b><br>";
	t += "<b>&lt;<font color='green'>div class=\"expando\"</font>&gt; Show or hide this text &lt;/div&gt;</b><br>";
	t += "- an open/close graphic (<img src=\"" + EXPANDO_GRAPHIC[0]["open"].src + "\">) ";
	t += "is inserted into the &lt;a expando&gt; tag automatically. <br>";
	t += "- the expando link will apply to the next DIV tag with the class set to \"expando\". <br>";
	t += "<b>&lt;a expando <font color='green'>open</font>&gt;click here&lt;/a&gt;</b><br>";
	t += "- you can specify that the DIV will start shown as opposed to hidden (the default). <br>";
	t += "<b>&lt;a expando <font color='green'>icon=\"white\"</font>&gt;click here&lt;/a&gt;</b><br>";
	t += "- you can specify which expando icons you want to use. Here's the current supported list: <br>";
	for (var k=0; k < EXPANDO_GRAPHIC.length; k++) {
		t += "&nbsp; &nbsp; \"" + EXPANDO_GRAPHIC[k]["name"] + "\" <br>";
	}
	t += "<b>&lt;a expando&gt;click here&lt;/a&gt;</b><br>";
	t += "<b>&lt;div class=\"expando\" <font color='green'>file=\"external_file.html\"</font>&gt; This will be erased &lt;/div&gt;</b><br>";
	t += "- you can link in the contents of an external file into the DIV. This will overwrite any text in the DIV. <br>";
	t += "<b>&lt;div class=\"expando\" <font color='purple'>id=\"somedivid\"</font>&gt; Show or hide this text &lt;/div&gt;</b><br>";
	t += "<b>&lt;p&gt; Some intervening HTML, it doesn't matter &lt;/p&gt;</b><br>";
	t += "<b>&lt;a <font color='purple'>expando=\"somedivid\"</font>&gt;click here&lt;/a&gt;</b><br>";
	t += "- you can specify a DIV ID if you want to affect a DIV that's located elsewhere in your HTML. <br>";
	t += "</p>\n";

	t += "<p><b><u> Notes: </u></b><br>";
	t += "<li>Custom HTML tags are case-sensitive: <i>name</i> is not the same as <i>Name</i>. The scripts have been written to recognize either full uppercase (<i>IREF</i>) or full lowercase (<i>iref</i>), but be careful of irregular capitalization.</li>";
	t += "</p>";
	t += "<hr></div>";
	return t;
}

// ------------------------------------------------------------ \\






//
// Old "QBW.JS" file, to aid in transition. Take this out when conversion is complete.
//

// Javascript for QB commands.  Created by Ione Pang on 5/15/02

// All code copyright (c) 2001-2002 Intuit Canada Ltd.
// Any unauthorized duplication or reuse of this code
// is a violation of applicable laws.
// Coded by Peter Harris.
// Version 1.41 - Feb. 24, 2003 - Added "SlectSKUversion2" for more granular calls.
// Version 1.4 - Feb 14, 2003 - Added Nonprofit and Medical Flavors - Jeff Taggart
//  - Currently the script is treating the Lightning flavors for Premier and Enterprise as one SKU (Healthcare, for example). (i.e. it is not making a distinction betweeen Prem Healtcare and Ent Healthcare, even though they are technically different SKUs.)
// Version 1.35 - Dec 31, 2002
//	- fixed bug in popup code for patched popup topics regarding top.globalPopupList existing.
//	- fixed popup calls from patched files in FixURL(). Again; was done previously and lost.
// Version 1.2 -- Added by Brenda Bowden on Sept. 17, 2002
//  - Added JavaScript from Jeff Taggert for additional SKU management functions.
// Version 1.1b - Sep 16, 2002
//	- added FixURL() function to allow for cross-CHM and patched popup links.
//	- made SKU detect fault-tolerant to allow CHM to be opened without the product running.
// Version 1.1a - Aug 1, 2002
//	- modified Popup Code: checks Click event srcElement for parental <A>; allows tags within links.
// Version 1.1 - Jul 11, 2002
//	- added Popup code
// Version 1.0 - Mar 20, 2002

// ----------------------------------------------------------------- \\
// ================================================================= \\
// =====     SKU MANAGEMENT FUNCTIONS FROM JEFF TAGGART        ===== \\
// ================================================================= \\

var BASIC = 1;
var PRO = 2;
var PREMIER = 3;
var ACCOUNTANT = 4;
var BEL = 5;
var CONT = 6;
var BELAE = 7;
var NONPROFIT = 8;
var HEALTHCARE = 9;
var SKUversion;

function selectSKUVersion () {

		var objLocator = new ActiveXObject("QuickBooks.CoLocator");
		var objProfile = objLocator.Create("QBPrefs.AppParameters"); 

		flavor = objProfile.Flavor;  // a string value; eg. "accountant"

		if (flavor == "pro") {
			SKUversion = PRO;
		} else if (flavor == "superpro") {
			SKUversion = PREMIER;	
		} else if (flavor == "accountant") {
			SKUversion = ACCOUNTANT; 
		} else if (flavor == "bel") {
			SKUversion = BEL;
		} else if (flavor == "contractor") {
			SKUversion = CONT; 
		} else if (flavor == "belcontractor") {
			SKUversion = CONT; 
		} else if (flavor == "belacct") {
			SKUversion = BELAE; 
		} else if (flavor == "nonprofit") {
			SKUversion = NONPROFIT; 
		} else if (flavor == "belnonprofit") {
			SKUversion = NONPROFIT; 
		} else if (flavor == "healthcare") {
			SKUversion = HEALTHCARE; 
		} else if (flavor == "belhealthcare") {
			SKUversion = HEALTHCARE; 
		} else {
			SKUversion = BASIC; 
		}

}

function showSKUcontent(n,display,SKU1,SKU2,SKU3,SKU4,SKU5,SKU6,SKU7,SKU8,SKU9) {
	selectSKUVersion();
    eval('thisItem=n');
	var displayType=display;
	// for debugging
	// document.write(SKUversion, n, display, SKU1, SKU2, SKU3, SKU4, SKU5, SKU6, SKU7, SKU8, SKU9);
	if (SKUversion==SKU1 || SKUversion==SKU2 || SKUversion==SKU3 || SKUversion==SKU4 || SKUversion==SKU5 || SKUversion==SKU6 || SKUversion==SKU7 || SKUversion==SKU8 || SKUversion==SKU9)
		{thisItem.style.display = displayType;}
	else 
	{thisItem.style.display = "none";}
}

function switchSKUimage(imgID,BASICsrc,PROsrc,PREMIERsrc,ACCOUNTANTsrc,BELsrc,CONTsrc,BELAEsrc,NONPROFITsrc,HEALTHCAREsrc) {
	selectSKUVersion();
	var dir = "images/"
    eval('thisItem=imgID');
	// document.write(version);
	if (SKUversion==BASIC)
	{thisItem.src = dir + eval('BASICsrc');}
	if (SKUversion==PRO)
	{thisItem.src = dir + eval('PROsrc');}
	if (SKUversion==PREMIER)
	{thisItem.src = dir + eval('PREMIERsrc');}
	if (SKUversion==ACCOUNTANT)
	{thisItem.src = dir + eval('ACCOUNTANTsrc');}
	if (SKUversion==BEL)
	{thisItem.src = dir + eval('BELsrc');}
	if (SKUversion==CONT)
	{thisItem.src = dir + eval('CONTsrc');}
	if (SKUversion==BELAE)
	{thisItem.src = dir + eval('BELAEsrc');}
	if (SKUversion==NONPROFIT)
	{thisItem.src = dir + eval('NONPROFITsrc');}
	if (SKUversion==HEALTHCARE)
	{thisItem.src = dir + eval('HEALTHCAREsrc');}
}

var BASIC2 = 1;
var PRO2 = 2;
var PREMIER2 = 3;
var ACCOUNTANT2 = 4;
var BEL2 = 5;
var CONT2 = 6;
var BELAE2 = 7;
var NONPROFIT2 = 8;
var HEALTHCARE2 = 9;
var BELNONPROFIT2 = 10;
var BELHEALTHCARE2 = 11;
var BELCONT2 = 12;
var SKUversion2;

function selectSKUVersion2 () {
    var obj = new ActiveXObject("QuickBooks.CoLocator");
    var myQBPrefs = obj.Create("QBPrefs.Preferences");

	if (myQBPrefs.ProductIsPRO)
	{
		SKUversion2 = PRO2;
		if (myQBPrefs.QBOL("Application.SKU='superpro'"))
		SKUversion2 = PREMIER2;	
		if (myQBPrefs.QBOL("Application.SKU='accountant'"))
		SKUversion2 = ACCOUNTANT2; 
		if (myQBPrefs.QBOL("Application.SKU='bel'"))
		SKUversion2 = BEL2;
		if (myQBPrefs.QBOL("Application.SKU='contractor'"))
		SKUversion2 = CONT2; 
		if (myQBPrefs.QBOL("Application.SKU='belcontractor'"))
		SKUversion2 = BELCONT2; 
		if (myQBPrefs.QBOL("Application.SKU='belacct'"))
		SKUversion2 = BELAE2; 
		if (myQBPrefs.QBOL("Application.SKU='nonprofit'"))
		SKUversion2 = NONPROFIT2; 
		if (myQBPrefs.QBOL("Application.SKU='belnonprofit'"))
		SKUversion2 = BELNONPROFIT2; 
		if (myQBPrefs.QBOL("Application.SKU='healthcare'"))
		SKUversion2 = HEALTHCARE2; 
		if (myQBPrefs.QBOL("Application.SKU='belhealthcare'"))
		SKUversion2 = BELHEALTHCARE2; 
	}
	else
	{ 
		SKUversion2 = BASIC2; 
	}
}

function showSKUcontent2(n,display,SKU1,SKU2,SKU3,SKU4,SKU5,SKU6,SKU7,SKU8,SKU9,SKU10,SKU11,SKU12) {
	selectSKUVersion2();
    eval('thisItem=n');
	var displayType=display;
	// for debugging
	// document.write(SKUversion, n, display, SKU1, SKU2, SKU3, SKU4, SKU5, SKU6, SKU7, SKU8, SKU9);
	if (SKUversion2==SKU1 || SKUversion2==SKU2 || SKUversion2==SKU3 || SKUversion2==SKU4 || SKUversion2==SKU5 || SKUversion2==SKU6 || SKUversion2==SKU7 || SKUversion2==SKU8 || SKUversion2==SKU9 || SKUversion2==SKU10 || SKUversion2==SKU11 || SKUversion2==SKU12)
		{thisItem.style.display = displayType;}
	else 
	{thisItem.style.display = "none";}
}
