var gVars;
var gVarCount;

var gFileVersion = "6.72";
var gFetchedPkgs;
var g_serverURL = "http://wncache.travelscream.com";
var g_WXFetchVersion = "5";
var g_IsDebug = false;
var g_LoadViaHeadTag = true;
var g_ExecuteWithOnLoadEvent = true;

var g_TSPackageWidget = "tsjs";
var g_TSContentWidget = "cont";

var g_PkgDispList = '';
var g_LookedUpLocations = [];
var g_LookedUpChildren = [];
var g_LookedUpImplied = [];
var g_MasterLocList;

var gStmtCount = 0;
var gStmtCount2 = 0;


// GLOBAL VARIABLES
//varCurPos
//varCurPageSize
//varResultArray
//fSetCaption
//fSetImage
//pkg1,2,3

// INBOUND VARIABLES
//pURL							the URL that will be used to lookup the XML data on the server
//pAbbr[0-2]
//pAbbrType[0-2]
//tswLoc1,2,3
//pAbbrList = 'US-CI';
//pAbbrListType = '2';
//pAbbrPosStart = 2;
//pLocNames



// ****************************
// PARAMETER FUNCTIONS
// ****************************

function IsLocalTSWTest()
{
	g_serverURL = "http://localhost";
}

function tswDontUseOnloadEvent()
{
	g_ExecuteWithOnLoadEvent = false;
}

function tswOSU(u)
{
    g_serverURL = u;
}


// inURL = URL of TS "blog" from which to fetch data
// inLinkURL = URL of TS "blog" to direct links to
// inWidgetSize = number of rows in widget
// inTag = "tag" (stored in gVars[x].varTag of the current widget information
function tswSetWDURL(inURL,inLinkURL,inWidgetSize,inTag)
{
	var myVar = FindGVar(inTag);
	gVars[myVar].pURL = inURL.toLowerCase();
	if (inLinkURL.indexOf("%s") >= 0) {
		gVars[myVar].pLinkURL = inLinkURL;
		gVars[myVar].pUsingCustomLinkURL = true;
		gVars[myVar].pCustomLinkURL = "http://"+inURL+"/a%s.htm";
		
	}
	else {
		gVars[myVar].pLinkURL = "http://"+inLinkURL+"/a%s.htm";
		gVars[myVar].pCustomLinkURL = false;
	}
	gVars[myVar].varCurPageSize = inWidgetSize;
}

// inAbbr = actual value of abbreviation.  For example, "CO" or "US"
// inAbbrType = type code for Abbreviation.  0= airport city code, other values reference "alternate location" table in TS
// inAbbrFieldNum = which of the location fields (1,2,3) should this abbreviation apply to
// inTag = "tag" (stored in gVars[x].varTag of the current widget information
function tswSetAbbreviation(inAbbr,inAbbrType,inAbbrFieldNum,inTag)
{
	var myVar = FindGVar(inTag);
	gVars[myVar].pAbbr[inAbbrFieldNum] = inAbbr.toUpperCase();
	gVars[myVar].pAbbrType[inAbbrFieldNum] = inAbbrType;
}

// inList = list of abbreviations, for example "US-CO"
// inAbbrType = type code for Abbreviation.  0= airport city code, other values reference "alternate location" table in TS
// inAbbrPosStart = which of the location fields (1,2,3) is the first to get an abbreviation.  the assignments continue from there until 3 is reached or abbreviations run out
// inTag = "tag" (stored in gVars[x].varTag of the current widget information
function tswSetAbbreviationList(inList,inAbbrType,inAbbrPosStart,inTag)
{
	var myVar = FindGVar(inTag);
	gVars[myVar].pAbbrList = inList.toUpperCase();
	gVars[myVar].pAbbrListType = inAbbrType;
	gVars[myVar].pAbbrPosStart = inAbbrPosStart;
}

// inLocNames = list of location names, for example   "unitedstates.nevada.lasvegas"
// inMaxLocName = assignment to loc fields starts at 1, and continues to this value
// inTag = "tag" (stored in gVars[x].varTag of the current widget information
function tswSetLocName(inLocNames,inMaxLocName,inTag)
{
	var myVar = FindGVar(inTag);
	gVars[myVar].pLocNames = inLocNames;
	gVars[myVar].pMaxLocName = inMaxLocName;
}

// inLocID = actual locationID to set
// inLocPos = which location field (1,2,3) to set the value to
// inTag = "tag" (stored in gVars[x].varTag of the current widget information
// inReset = should a complete reset of location params be done before setting the location passed?
function tswSetLocID(inLocID,inLocPos,inTag,inReset)
{
	var myVar = FindGVar(inTag);
	try { if (inReset) privateDoLocationDataReset(FindGVar(inTag)); } catch (e) {}
	var workLocID = ''+inLocID;
	var locArray = workLocID.split("-");
	for (var i = 0; i < locArray.length; i++) {
		AddLocIDToArray(myVar,inLocPos,locArray[i]);
	}
}

function ConvertFlagListToObject(inFlagList)
{
	if (typeof (inFlagList) == "object") return inFlagList;

	var workFlagList = '' + inFlagList;
	workFlagList = workFlagList.replace(/-/g, ",");
	var workArray = workFlagList.split(",");

	var resultFlags = {};
	resultFlags["default"] = [];
	var loopMax = workArray.length;
	for (var loopIter = 0; loopIter < loopMax; loopIter++) {
		if (workArray[loopIter].length > 0) {
			resultFlags["default"].push(workArray[loopIter]);
		}
	}
	return resultFlags;
}

function tswSetIncludeOnlyFlags(inFlagList,inTag)
{
	var workFlagList = ConvertFlagListToObject(inFlagList);
	workFlagList.initialized = true;
	gVars[FindGVar(inTag)].pLimitFlags = workFlagList;
}

function tswClickSwitchFlag(flagID, inTag)
{
	tswResetTagFilters(inTag);
	if (flagID > 0) {
		tswSetIncludeOnlyFlags(flagID,inTag);
	} 
	tswRedisplayWidget(inTag);
}

function tswTreatAllLocSelectionsEqual(inTag)
{
	gVars[FindGVar(inTag)].pTreatAllLocSelectionsEqual = true;
}

function tswResetTagFilters(inTag)
{
	privateDoLocationDataReset(FindGVar(inTag));
}

function tswRedisplayWidget(inTag)
{
	var myVar = FindGVar(inTag);
	if (gVars[myVar].pObj != undefined)
		ProcessJSON(myVar);
}

function privateDoLocationDataReset(inVar)
{
	gVars[inVar].pLimitFlags = {};
	gVars[inVar].pAbbr = new Array();
	gVars[inVar].pAbbrType = new Array();
	gVars[inVar].workLocArray = new Array();
	gVars[inVar].locMax = new Array();
	gVars[inVar].pAbbrList = undefined;
	gVars[inVar].pAbbrListType = undefined;
	gVars[inVar].pAbbrPosStart = undefined;
	gVars[inVar].pLocNames = undefined;
	gVars[inVar].pMaxLocName = undefined;
	gVars[inVar].pMaxPerBlogArray = [];
	if (gVars[inVar].pObj != undefined) {
		for (var i = 0; i < gVars[inVar].pObj.pl.p.length; i ++) {
			gVars[inVar].pObj.pl.p[i].z = undefined;
		}
	}
}

// this can ONLY be called after the package data loads
function tswSetTopDealsOnly(inTag)
{
	g_LoadViaHeadTag = true;
	var myVar = FindGVar(inTag);
	privateDoLocationDataReset(myVar);
	if (gVars[myVar].pObj != undefined)
		ProcessJSON(myVar);
}

function tswSetContentProvider(inProviderCode,inTag)
{
	var myVar = FindGVar(inTag);
	gVars[myVar].pContentProvider = inProviderCode;
	if (gVars[myVar].pObj != undefined) {
		ProcessJSON(myVar);
	}
}

function tswSetContentType(inTypeCode,inTag)
{
	var myVar = FindGVar(inTag);
	gVars[myVar].pContentType = inTypeCode;
	if (gVars[myVar].pObj != undefined)
		ProcessJSON(myVar);
}

function tswResetLocations(inLocID,inTag)
{
	g_LoadViaHeadTag = true;
	var myVar = FindGVar(inTag);
	privateDoLocationDataReset(myVar);
	tswSetLocID(inLocID,1,inTag);
	ProcessJSON(myVar);
}

function tswParseTitleForLocationNames(inTag,inIncludeMeta,inForceUseIFrameTitle)
{
	gVars[FindGVar(inTag)].pParseTitleForLocationNames = true;
	if (inIncludeMeta != undefined)
		gVars[FindGVar(inTag)].pParseMetaForLocationNames = inIncludeMeta;
	if (inForceUseIFrameTitle != undefined)
		gVars[FindGVar(inTag)].pParseForceUseIFrame = inForceUseIFrameTitle;
}

function tswLimitDefaultToTopPackages(inTag)
{
	gVars[FindGVar(inTag)].pLimitDefaultToTop = true;
}

function tswShowDividerLabel(inTag)
{
	gVars[FindGVar(inTag)].pUseExtraPackageDividerLabel = true;
}

function tswDefaultShowsAllPackages(inTag)
{
	gVars[FindGVar(inTag)].pLimitDefaultToTop = false;
}


// inTrackClick = URL for Doubleclick or other "click tracking" entity, to prepend to string
// inTrackUC = Omniture tracking code, formatted as "/uc/INSERTCODE" to append to string
// inTag = "tag" (stored in gVars[x].varTag of the current widget information
function tswSetTracking(inTrackClick,inTrackUC,inTag)
{
	gVars[FindGVar(inTag)].pTrackClick = inTrackClick;
	gVars[FindGVar(inTag)].pTrackUC = inTrackUC;
}

// inLinkTarget = Defaults to _blank but will accept an IFRAME name, or _self or other value
// inTag = "tag" (stored in gVars[x].varTag of the current widget information
function tswSetLinkTarget(inLinkTarget,inTag)
{
	gVars[FindGVar(inTag)].pLinkTarget = inLinkTarget;
}



// ****************************
// DISPLAY SETUP FUNCTIONS
// ****************************


// inTag = "tag" (stored in gVars[x].varTag of the current widget information
function tswHideImages(inTag)
{
	gVars[FindGVar(inTag)].pShowImages = false;
}

// inTag = "tag" (stored in gVars[x].varTag of the current widget information
function tswDisableRandomize(inTag)
{
	gVars[FindGVar(inTag)].pDoRandomize = false;
}

// inTag = "tag" (stored in gVars[x].varTag of the current widget information
function tswEnableRandomize(inTag)
{
	gVars[FindGVar(inTag)].pDoRandomize = true;
}

// always descending for now...
function tswSortByCreateTime(inTag)
{
	tswDisableRandomize(inTag);
	gVars[FindGVar(inTag)].pSortByCreateTime = true;
}

// inTag = "tag" (stored in gVars[x].varTag of the current widget information
function tswShowPrice(inTag)
{
	gVars[FindGVar(inTag)].pShowPrice = true;
}
// inTag = "tag" (stored in gVars[x].varTag of the current widget information
function tswShowDesc(inTag)
{
	gVars[FindGVar(inTag)].pShowDesc = true;
}

// inTag = "tag" (stored in gVars[x].varTag of the current widget information
function tswShowSource(inTag)
{
	gVars[FindGVar(inTag)].pShowSource = true;
}
// inLength = max caption length to show
// inTruncText = if the caption is truncated, this is the actual text to display that means "more..."
// inTag = "tag" (stored in gVars[x].varTag of the current widget information
function tswTruncateCaption(inLength,inTruncText,inTag)
{
	var myVar = FindGVar(inTag);
	gVars[myVar].pTruncateCaption = inLength;
	gVars[myVar].pTruncateText = inTruncText;
}

function tswUseAltCaption(inTag)
{
	gVars[FindGVar(inTag)].pUseAltCaption = true;
}
// inLength = max description length to show
// inTag = "tag" (stored in gVars[x].varTag of the current widget information
function tswTruncateDesc(inLength,inTruncTextDesc,inTag)
{
	var myVar = FindGVar(inTag);
	gVars[myVar].pTruncateDesc = inLength;
	gVars[myVar].pTruncateTextDesc = inTruncTextDesc;
}

function tswSetMaxFromUnselectedLocations(inMax,inTag)
{
	gVars[FindGVar(inTag)].pMaxFromUnselectedLocations = inMax;
}

function tswSetMaxFromLocation(inMax,inLocPos,inTag)
{
	gVars[FindGVar(inTag)].locMax[inLocPos] = inMax;
}

function tswSetNoResultsString(inString,inTag)
{
	gVars[FindGVar(inTag)].pNoResultsString = inString;
}

// inCustomTitle = Custom Title for the full widget, defaults to nothing. Will not be used unless called
// inTag = "tag" (stored in gVars[x].varTag of the current widget information
function tswSetCustomTitle(inCustomTitle,inTag)
{
	gVars[FindGVar(inTag)].pCustomTitle = inCustomTitle;
}

// inCustomFooter = Custom Footer for the full widget, defaults to nothing. Will not be used unless called
// inTag = "tag" (stored in gVars[x].varTag of the current widget information
function tswSetCustomFooter(inCustomFooter,inTag)
{
	gVars[FindGVar(inTag)].pCustomFooter = inCustomFooter;
}

// inCustomNoMatchSeparator = Custom Footer for the full widget, defaults to nothing. Will not be used unless called
// inTag = "tag" (stored in gVars[x].varTag of the current widget information
function tswSetCustomNoMatchSeparator(inCustomNoMatchSeparator,inTag)
{
	gVars[FindGVar(inTag)].pCustomNoMatchSeparator = inCustomNoMatchSeparator;
}

// inViewInfo = View More Info text for each deal
// inTag = "tag" (stored in gVars[x].varTag of the current widget information
function tswSetViewInfo(inViewInfo,inTag)
{
	gVars[FindGVar(inTag)].pViewInfo = inViewInfo;
}

function tswSetIncludeDirectLinks(inInclude,inTag)
{
	if (inInclude)
		gVars[FindGVar(inTag)].pIncludeDirectLinks = 1;
	else
		gVars[FindGVar(inTag)].pIncludeDirectLinks = -1;
}

function tswSetContentWidget(inTag, inLoadFromHTML)
{
	var myVar = FindGVar(inTag);
	gVars[myVar].mWidgetType = g_TSContentWidget;
	gVars[myVar].fSetCaption = cwSetCaption;
	gVars[myVar].fSetDesc = cwSetDesc;
	gVars[myVar].fSetImage = cwSetImage;
	gVars[myVar].pFillDisplayWithNonLoc = false;
	if (inLoadFromHTML != undefined) {
		gVars[myVar].pLoadContentFromHTML = inLoadFromHTML;
	}
}

function tswSetupDefaultFunctions(inListItem)
{
	if (gVars[inListItem].mWidgetType == g_TSPackageWidget) {
		gVars[inListItem].fSetCaption = DefaultSetCaption;
		gVars[inListItem].fSetFacebook = DefaultSetFBLike;
		gVars[inListItem].fSetDesc = DefaultSetDesc;
		gVars[inListItem].fSetSource = DefaultSetSource;
		gVars[inListItem].fSetPostDate = DefaultSetPostDate;
		gVars[inListItem].fSetPostUser = DefaultSetPostUser;
		gVars[inListItem].fSetImage = DefaultSetImage;
		gVars[inListItem].fSetPrice = DefaultSetPrice;
		gVars[inListItem].fSetViewInfo = DefaultSetViewInfo;
	}
}

function tswSetBlogMaxReassign(inFrom,inTo,inTag)
{
	gVars[FindGVar(inTag)].pMaxReassignArray[inFrom] = inTo;
}

function tswSetMaxPerBlog(inMax,inTag)
{
	gVars[FindGVar(inTag)].pMaxPerBlog = inMax;
}

function tswSetStrictLocationProcessing(inTag)
{
	gVars[FindGVar(inTag)].strictLocationProcessing = true;
}

// this function is the FIRST function that should be called for a widget.  it creates the appropriate structures
// and tags them in the array
// inTag = "tag" (stored in gVars[x].varTag of the current widget information
function SetupGlobals(inTag)
{
	if (gVars == undefined) {
		gVars = new Array();
		gVarCount = 0;
		gFetchedPkgs = new Array();
	}
	gVars[gVarCount] = {};
	gVars[gVarCount].varTag = inTag;
	gVars[gVarCount].mWidgetType = g_TSPackageWidget;
	gVars[gVarCount].pLoadContentFromHTML = false;
	gVars[gVarCount].pAbbr = new Array();
	gVars[gVarCount].pAbbrType = new Array();
	gVars[gVarCount].workLocArray = new Array();
	gVars[gVarCount].defaultLocations = new Array();
	gVars[gVarCount].pUseDefaultLocationsForBackup = false;
	gVars[gVarCount].strictLocationProcessing = false;
	gVars[gVarCount].locMax = new Array();
	gVars[gVarCount].pContentProvider = "";
	gVars[gVarCount].pContentType = "";
	gVars[gVarCount].pDoRandomize = true;
	gVars[gVarCount].pSortByCreateTime = false;
	gVars[gVarCount].pNoResultsString = "No results found!";
	gVars[gVarCount].pIncludeDirectLinks = 0;
	gVars[gVarCount].pLimitDefaultToTop = true;
	gVars[gVarCount].pUseExtraPackageDividerLabel = false;
	gVars[gVarCount].pMaxFromUnselectedLocations = 2;
	gVars[gVarCount].pParseTitleForLocationNames = false;
	gVars[gVarCount].pParseMetaForLocationNames = false;
	gVars[gVarCount].pParseForceUseIFrame = false;
	gVars[gVarCount].pTreatAllLocSelectionsEqual = false;
	gVars[gVarCount].pLimitFlags = {};
	gVars[gVarCount].pMaxPerBlog = 1;
	gVars[gVarCount].pMaxPerBlogArray = [];
	gVars[gVarCount].pMaxReassignArray = [];

	gVars[gVarCount].pCapturedInPlace = false;
	gVars[gVarCount].pCapturedInitialDisplayComplete = false;

	gVars[gVarCount].pFillDisplayWithNonLoc = true;
	gVars[gVarCount].pShowImages = true;
	gVars[gVarCount].pShowPrice = false;
	gVars[gVarCount].pShowViewInfo = true;
	gVars[gVarCount].pUseAltCaption = false;
	gVars[gVarCount].pTruncateCaption = 1000;
	gVars[gVarCount].pTruncateText = "";
	gVars[gVarCount].pTruncateDesc = 1000;
	gVars[gVarCount].pTruncateTextDesc = "";
	gVars[gVarCount].pShowDesc = false;
	gVars[gVarCount].pShowSource = false;
	gVars[gVarCount].pTrackClick = "";
	gVars[gVarCount].pTrackUC = "";
	gVars[gVarCount].pLinkTarget = "_blank";
	gVars[gVarCount].pCustomTitle = "";
	gVars[gVarCount].pCustomFooter = "";
	gVars[gVarCount].pCustomNoMatchSeparator = "Additional results:<hr/>";
	gVars[gVarCount].pViewInfo = "";
	gVars[gVarCount].pFacebookLikeDomain = "";
	var varPos = gVarCount;
	gVarCount ++;
	return varPos;
}

function tswSetDefaultLocations(inTag, inDefaultLocList, inUseDefaultForBackup)
{
	var defaultLocList = gVars[FindGVar(inTag)].defaultLocations;
	var locArray = inDefaultLocList.split("-");
	for (var i = 0; i < locArray.length; i++) {
		if (locArray[i].length > 0)
			defaultLocList[defaultLocList.length] = locArray[i];
	}
	gVars[FindGVar(inTag)].pUseDefaultLocationsForBackup = inUseDefaultForBackup;
}

function CaptureInPlaceLayout(inURL, inLinkURL, inTag, inDefaultLocList, inFBLikeDomain)
{
    if (inTag == undefined)
        inTag = "tslv";
    SetupGlobals(inTag);

	if (inDefaultLocList != undefined) tswSetDefaultLocations(inTag, inDefaultLocList, false);
	tswSetStrictLocationProcessing(inTag);
	tswShowDividerLabel(inTag);
    tswSetWDURL(inURL, inLinkURL, 20, inTag);
    tswShowDesc(inTag);
    gVars[FindGVar(inTag)].pCapturedInPlace = true;
	if (inFBLikeDomain != undefined)
		gVars[FindGVar(inTag)].pFacebookLikeDomain = inFBLikeDomain;
    FetchXML(inTag,true);
}

function GetTagPrefix(inTag)
{
	return GetIdxPrefix(FindGVar(inTag));
}
function GetIdxPrefix(inIdx)
{
	if (gVars[inIdx].mWidgetType == g_TSPackageWidget) 
		return "wx"; 
	else 
		return "cx";
}
function GetTagValidateURL(inTag)
{
	return GetTagPrefix(inTag) + gVars[FindGVar(inTag)].pURL;
}
function GetIdxValidateURL(inIdx)
{
	return GetIdxPrefix(inIdx) + gVars[inIdx].pURL;
}
function GetObjPrefix(inObj)
{
	try {
		if (inObj.pl.p[0].u == undefined)
			return "wx";
		return "cx";
	}
	catch(e) {
	}
	return "wx";
}
function GetObjValidateURL(inObj)
{
	return GetObjPrefix(inObj) + inObj.pl.url;
}

// make a copy of some pertinent global variables, because content widgets have the ability to override these things...
function DoAdditionalContentWidgetSetup(inTag)
{
	var gPos = FindGVar(inTag);
	if (gVars[gPos].mWidgetType != g_TSContentWidget) return;

	gVars[gPos].pCWSaveDoRandomize = gVars[gPos].pDoRandomize;
	gVars[gPos].pCWSaveTruncateDesc = gVars[gPos].pTruncateDesc;
}

function tswContentWidgetSetWorkParamsForItems(inContentItem, inGVar)
{
	try {
		switch (inContentItem.doRand) {
			case 1:
				tswEnableRandomize(gVars[inGVar].varTag);
				break;
			case -1:
				tswDisableRandomize(gVars[inGVar].varTag);
				break;
			case 0:
			default:
				if (gVars[inGVar].pCWSaveDoRandomize)
					tswEnableRandomize(gVars[inGVar].varTag);
				else
					tswDisableRandomize(gVars[inGVar].varTag);
				break;
		}
		if (inContentItem.descTrunc >= 0) {
			gVars[inGVar].pTruncateDesc = inContentItem.descTrunc;
		}
		else {
			gVars[inGVar].pTruncateDesc = gVars[inGVar].pCWSaveTruncateDesc;
		}
	}
	catch (e) { }
}

// this function extracts a value from an HTML attribute.  if the value is explicitly "true" or "false" or some 
// equivalent, assign 1 or -1, respectively.  otherwise assign 0 - which will be taken to mean "do the default"
function LoadHTMLAttributeTriState(inElement, inAttrib, inDefault)
{
	var resultVal;
	try {
		resultVal = inElement.getAttribute(inAttrib);
		switch (resultVal.toLowerCase()) {
			case 't':
			case 'true':
			case '1':
				resultVal = 1;
				break;
			case 'f':
			case 'false':
			case '0':
			case '-1':
				resultVal = -1;
				break;
			default:
				resultVal = inDefault;
				break;
		}
	}
	catch (e) {
		resultVal = inDefault;
	}
	return resultVal;
}

function LoadHTMLAttributeInt(inElement, inAttrib, inDefault)
{
	var resultVal;
	try {
		resultVal = parseInt(inElement.getAttribute(inAttrib));
	}
	catch (e) {
		resultVal = inDefault;
	}
	return resultVal;
}

function LoadHTMLAsContent(inTag)
{
	var contentArray = [];
	var myImgArray = document.getElementsByName('contentItem');
	if (myImgArray.length < 1) {
		tswSetActiveGuideTab();
		return;
	}
	for (var i = 0; i < myImgArray.length; i++) {
		var cID = myImgArray[i].id.replace("cImg_", "");
		var myCP = myImgArray[i].getAttribute('cp').toLowerCase();
		contentArray.push(
			{
				i: cID,
				m: myImgArray[i].getAttribute('src'),
				ct: myImgArray[i].getAttribute('ct'),
				cp: myCP,
				doRand: LoadHTMLAttributeTriState(myImgArray[i], 'doRand', 0),
				descTrunc: LoadHTMLAttributeInt(myImgArray[i], 'truncLen', -1),
				ld: myImgArray[i].getAttribute('cl').split('-'),
				u: document.getElementById('cA_' + cID).getAttribute('href'),
				c: document.getElementById('cA_' + cID).innerHTML,
				ds: document.getElementById('cDesc_' + cID).innerHTML
			}
		);
		try { document.getElementById('contentTab_li_' + myCP).style.display = 'block'; } catch (e) { }
	}
	var myObj = {
		pl: {
			url:"content.travelscream.com",
			p: contentArray,
			ln: TS_autoContentLocData.ln,
			cc: TS_autoContentLocData.cc,
			la: TS_autoContentLocData.la
		}
	};
	var tabArray = jQuery("li[name='contentTab_li']");
	for (var jqIter = tabArray.length - 1; jqIter >= 0; jqIter--) {
		if (tabArray[jqIter].style.display != "none") {
			var firstCode = tabArray[jqIter].id.replace('contentTab_li_', '');
			gVars[FindGVar(inTag)].pContentProvider = firstCode;
			tswDrawActiveContentTab(firstCode);
			break;
		}
	}
	gVars[FindGVar(inTag)].pObj = myObj;
	ProcessJSON(FindGVar(inTag));
}

function tswDisplayContentTab()
{
	// use a separate TRY block here so that we don't lose this function if the last one fails...
	try {
		document.getElementById("tswWidgetContent").style.display = "block";
		document.getElementById("tswDestGuideDiv").style.display = "none";
	}
	catch (e) { }
}

function tswDisplayGuideTab()
{
	// use a separate TRY block here so that we don't lose this function if the last one fails...
	try {
		document.getElementById("tswDestGuideDiv").innerHTML = document.getElementById("tswDestGuideInner").innerHTML;
		document.getElementById("tswWidgetContent").style.display = "none";
		document.getElementById("tswDestGuideDiv").style.display = "block";
	}
	catch (e) { }
}

function tswDrawActiveContentTab(inTab)
{
	jQuery("a[name='contentTab_a']").removeClass('active');
	jQuery("a[name='contentTab_a']").addClass('inactive');
	try { document.getElementById("contentTab_a_" + inTab).className = "active"; } catch (e) { }
}

function tswSetActiveGuideTab()
{
	tswDisplayGuideTab();
	tswDrawActiveContentTab('dest');
}

function tswSetActiveContentTab(activeTab, inTag)
{
	tswDisplayContentTab();
	tswDrawActiveContentTab(activeTab);
	tswSetContentProvider(activeTab, inTag);
}


// this function is used to send the actual request for data to the server
// it first checks to see if the data being requested has already been fetched - if not, it gets it
// if it HAS been fetched, it simply dispatches to the widget processing call
// inTag = "tag" (stored in gVars[x].varTag of the current widget information
function DispatchListRequest(inTag)
{
	var myPos = FindGVar(inTag);

	if (gVars[myPos].mWidgetType == g_TSContentWidget && gVars[myPos].pLoadContentFromHTML) {
		LoadHTMLAsContent(inTag);
		return;
	}
	var myURL = gVars[myPos].pURL;
	var mainValidateURL = GetTagValidateURL(inTag);
	gVars[myPos].pSent = false;

	var i;
	for (i = 0; i < gVars.length; i++) {
		if (i != myPos && gVars[i].pSent == true) {
			if (GetIdxValidateURL(i) == mainValidateURL) {
				if (typeof gVars[i].pObj != "undefined") {
					gVars[myPos].pSent = true;
					gVars[myPos].pObj = gVars[i].pObj;
					ProcessJSON(myPos);
				}
				return;
			}
		}
	}
	var dispatchURL = "";
	if (gVars[myPos].mWidgetType == g_TSPackageWidget)
		dispatchURL = g_serverURL+"/wx/"+myURL+"/"+g_WXFetchVersion;
	else
		dispatchURL = g_serverURL+"/cx/"+myURL;

	tsw_loadjscssfile(dispatchURL);
	//document.write('<script type="text/javascript" src="'+dispatchURL+'"></script>');
}

// this is the function that gets called by the script when it has been fetched from the server with a list of packages
// inObj is the actual JSON object that contains the package list data
function tswPackageListCallback(inObj)
{
	var i;
	var objValidateURL = GetObjValidateURL(inObj);
	for (i = 0; i < gVars.length; i++) {
		if (GetIdxValidateURL(i) == objValidateURL) {
			if (gVars[i].pSent == false) {
				gVars[i].pSent = true;
				gVars[i].pObj = inObj;
				ProcessJSON(i);
			}
		}
	}
}

// process 1 widget
// inTag = "tag" (stored in gVars[x].varTag of the current widget information
function FetchXML(inTag, inForceUseImmediate)
{
	DoAdditionalContentWidgetSetup(inTag);
	if (g_ExecuteWithOnLoadEvent && inForceUseImmediate != true) {
		var oldFunc = window.onload;
		if (oldFunc == undefined)
			window.onload = function() { DispatchListRequest(inTag); };
		else
			window.onload = function() { try { oldFunc(); } catch(err){} DispatchListRequest(inTag); };
	}
	else {
		DispatchListRequest(inTag);
	}
}

function ShowAllPackages(inListItem)
{
	var i, message='', myCnt = 0;
	for (i = 0; i < gVars[inListItem].pObj.pl.p.length; i ++) {
		message += gVars[inListItem].pObj.pl.p[i].i + "/" + gVars[inListItem].pObj.pl.p[i].z + "\r\n";
		myCnt ++;
		if (myCnt > 60) {
			alert(message);
			myCnt = 0;
			message = '';
		}
	}
	alert(message);
}

function ResetPackageData(inListItem)
{
	for (var i = 0; i < gVars[inListItem].pObj.pl.p.length; i ++) {
		gVars[inListItem].pObj.pl.p[i].z = undefined;
	}
}

// inListItem = array element of gVars that's getting processed
function ProcessJSON(inListItem)
{
	var testStr = ''+window.location;
	if (testStr.indexOf("xyzzy1991", 0) >= 0 || document.getElementById('roboDebug') != null) {
		g_IsDebug = true;
		gVars[inListItem].varDebug = '';
		AddToDebug(inListItem,'tag:'+gVars[inListItem].varTag);
	}
	ResetPackageData(inListItem);

	PreSetupLocations(inListItem);
	ParseDocument(inListItem);
	ParseLocNames(inListItem);
	ParseLocAbbrLists(inListItem);
	ParseLocAbbreviations(inListItem);

	DoDirectLinks(inListItem);
	DoLocations(inListItem);
	BuildBackupList(inListItem);
	ProcessFlags(inListItem);
	ProcessContentFlags(inListItem);
	MergeLists(inListItem);
	if (document.getElementById("roboDebug") != null)
		document.getElementById("roboDebug").value = gVars[inListItem].varDebug;

	tswSetupDefaultFunctions(inListItem);
	
	gVars[inListItem].varCurPos = 1;
	SetWidgetHeadFoot(inListItem);
	if (gVars[inListItem].pCapturedInitialDisplayComplete == true || gVars[inListItem].pCapturedInPlace == false) {
	    PopulateDisplay(inListItem);
	}
	else {
	    gVars[inListItem].pCapturedInitialDisplayComplete = true;
	}
}

function ShowPkgInfo(inListItem, inPkg)
{
	var maxIter = gVars[inListItem].pObj.pl.p.length;
	for (var i = 0; i < maxIter; i++) {
		if (gVars[inListItem].pObj.pl.p[i].i == inPkg) {
			alert(gVars[inListItem].pObj.pl.p[i].z);
			return;
		}
	}
}


function ProcessContentFlags(inVar)
{
	if (gVars[inVar].mWidgetType != g_TSContentWidget) return;
	
	var testProv = false;
	if (gVars[inVar].pContentProvider.length > 0) testProv = true;
	var testType = false;
	if (gVars[inVar].pContentType.length > 0) testType = true;
	if (testProv == false && testType == false) return;

	var contentList = gVars[inVar].pObj.pl.p;
	var maxIter = contentList.length;
	for (var i = 0; i < maxIter; i++) {
		if (testProv) {
			if (contentList[i].cp.toLowerCase() != gVars[inVar].pContentProvider.toLowerCase()) {
				contentList[i].z = undefined;
			}
			else {
				// here we check to see if the content item we're working on has a doRand value.  if it's false, turn off randomization, otherwise turn it on
				// the catch here is that if different items in the same provider have different values, you'll get weird results.  so make sure
				// you keep that in mind.
				tswContentWidgetSetWorkParamsForItems(contentList[i], inVar);
			}
		}
		if (testType) {
			if (contentList[i].ct != gVars[inVar].pContentType)
				contentList[i].z = undefined;
		}
	}	
}

function ParseDocument(inVar)
{
	ParseTitle(inVar);
	ParseMeta(inVar);
	ConvertPointsToLocations(inVar);
}

function ConvertPointsToLocations(inVar)
{
	gVars[inVar].pObj.pl.ln.sort(PointCompareDesc);
	var lastPoints = 99999, curLocArray = 0;
	var maxIter = gVars[inVar].pObj.pl.ln.length;
	var i;
	for (i = 0; i < maxIter; i++) {
		if (gVars[inVar].pObj.pl.ln[i].x > 0) {
			if (gVars[inVar].pObj.pl.ln[i].x != lastPoints) {
				lastPoints = gVars[inVar].pObj.pl.ln[i].x;
				curLocArray ++;
			}
			AddLocIDToArray(inVar,curLocArray,gVars[inVar].pObj.pl.ln[i].i);
			AddToDebug(inVar,"loc " + curLocArray + ":"+gVars[inVar].pObj.pl.ln[i].i + ":"+gVars[inVar].pObj.pl.ln[i].s + ":"+gVars[inVar].pObj.pl.ln[i].x);
		}
	}
}

function FetchPageTitle(inVar)
{
	var tempTitle = '';
	if (gVars[inVar].pParseForceUseIFrame == false) {
		tempTitle = document.title;
		if (tempTitle.length > 0) return tempTitle;
	}
	try { tempTitle = window.parent.document.title; } catch (e) { }
	return tempTitle;
}

function ParseTitle(inVar)
{
	if (! gVars[inVar].pParseTitleForLocationNames) return;

	var myRE = new RegExp("[^a-z ]", "ig");
	var myTitle = FetchPageTitle(inVar);
	var fixedTitle = myTitle.replace(myRE, " ");
	AddToDebug(inVar,"title search:"+fixedTitle);
	LookupLocNameMulti(fixedTitle,inVar);
}

function ParseMeta(inVar)
{
	if (! gVars[inVar].pParseMetaForLocationNames) return;
	
	var myRE = new RegExp("[^a-z ]","ig");
	var metaArray = document.getElementsByName('Keywords');
	if (metaArray.length < 1) return;
	
	var fixedTitle = metaArray[0].content;
	var fixedTitle = fixedTitle.replace(myRE," ");

	AddToDebug(inVar,"meta search:"+fixedTitle);
	LookupLocNameMulti(fixedTitle,inVar);
}

function PreSetupLocations(inVar)
{
	var maxIter = gVars[inVar].pObj.pl.ln.length;
	var workLocList = gVars[inVar].pObj.pl.ln;
	
	var doMasterWork = false;
	if (g_MasterLocList == undefined) {
		g_MasterLocList = [];
		doMasterWork = true;
	}
		
	var i;
	for (idx = 0; idx < maxIter; idx++) {
		workLocList[idx].x = 0;
		if (doMasterWork) {
			g_MasterLocList.push( 
				{ 
					i:workLocList[idx].i, 
					p:workLocList[idx].p, 
					n:workLocList[idx].s.replace(' ','','g'),
					s:workLocList[idx].s
				} 
			);
			
			var curLoc = workLocList[idx];
			g_LookedUpLocations[curLoc.i] = idx;
			if (g_LookedUpChildren[curLoc.p] == undefined)
				g_LookedUpChildren[curLoc.p] = [];
			g_LookedUpChildren[curLoc.p].push(curLoc.i);
		}
	}
}

function LookupLocNameMulti(inLocName,inVar)
{
	if (inLocName.length < 1) return;
	workLocName = inLocName.toLowerCase();
	var nameArray = workLocName.split(' ');

	var maxIter = gVars[inVar].pObj.pl.ln.length;										// maxIter = number of location names - iterate over them
	for (var i = 0; i < maxIter; i++) {
		var lnSSplit = gVars[inVar].pObj.pl.ln[i].s.split(' ');							// split current loc name into array
		var matchAll = true;															// so we can test if the paramName matches the WHOLE loc name
		for (var x = 0; x < lnSSplit.length; x ++) {									// iterate over each piece of loc name
			if (lnSSplit[x].length > 0) {												// only test non-zero length chunks
				var y;
				for (y = 0; y < nameArray.length; y ++) {
					if (nameArray[y].length > 3) {										// non-zero length chunks
						if (lnSSplit[x] == nameArray[y]) {								// does this chunk match that chunk
							gVars[inVar].pObj.pl.ln[i].x += nameArray[y].length;		// set the points
							break;
						}
					}
				}
				if (y >= nameArray.length) matchAll = false;
			}
		}
		if (matchAll) {
			gVars[inVar].pObj.pl.ln[i].x += 100;								// over weight a complete match
		}
	}
	return 0;
}

// take a loc name string (na.us.nevada.lasvegas) and turn it into locIDs
// it starts with 1 and goes to maxLocName with location values, as found based on the text names
// inVar = array element in gVars to process
function ParseLocNames(inVar)
{
	if (typeof gVars[inVar].pLocNames != "undefined") {
		var nameArray = gVars[inVar].pLocNames.split(".");
		var i, curIDArray = 1;
		for (i = nameArray.length - 1; i >= 0; i --) {
			var thisID = LookupLocName(nameArray[i].toLowerCase(), inVar);
			if (thisID.length > 0 || thisID > 0) {
				AddLocIDToArray(inVar,curIDArray ++,thisID);
			}
			if (curIDArray > gVars[inVar].pMaxLocName) break;
		}
	}
}

// lookup a location name and get one or more loc IDs
// inLocName = actual text of location name
// inVar = array element in gVars to process
function LookupLocName(inLocName,inVar)
{
	var resultList='';
	var maxIter = g_MasterLocList.length;
	var i;
	for (i = 0; i < maxIter; i++) {
		if (g_MasterLocList[i].n == inLocName) {
			return (g_MasterLocList[i].i);
		}
	}
	return 0;
}

// process abbreviation list into loc IDs...
// this function takes the AbbrList variable, splits it by  "-"  and then puts the split value into the appropriate slot
// for later processing it processes the lookup values starting with the AbbrPosStart and goes until it runs out of abbreviations
// inVar = array element in gVars to process
function ParseLocAbbrLists(inVar)
{
	if (typeof gVars[inVar].pAbbrList != "undefined") {
		var abbrArray = gVars[inVar].pAbbrList.split("-");
		var i;
		var abbrPosStart = gVars[inVar].pAbbrPosStart;
		for (i = abbrArray.length - 1; i >= 0; i --, abbrPosStart ++) {
			gVars[inVar].pAbbr[abbrPosStart] = abbrArray[i];
			gVars[inVar].pAbbrType[abbrPosStart] = gVars[inVar].pAbbrListType;
		}
	}
}

// go through all 3 copies of locAbbr variable and get loc codes out
// this function actually goes through each actual abbreviation (1,2,3), looks up the value and assigns the
// found value into the appropriate workLocArray slot (1,2,3)
// inVar = array element in gVars to process
function ParseLocAbbreviations(inVar)
{
	var i;
	for (i = 1; i <= 3; i ++) {
		if (typeof gVars[inVar].pAbbr[i] != "undefined") {
			if (gVars[inVar].pAbbrType[i] == 0) {
				Parse1LocCode(gVars[inVar].pAbbr[i],gVars[inVar].pObj.pl.cc,i,inVar);
			}
			else {
				Parse1LocCode(gVars[inVar].pAbbr[i],gVars[inVar].pObj.pl.la,i,inVar);
			}
		}
	}
}

// turn a "locCode" (like 'US' or 'CO') into a loc ID
// inCode = location abbreviation
// inCodeArray = which array to search for the value
function Parse1LocCode(inCode,inCodeArray,inLocPos,inVar)
{
	if (inCode.length < 1) return;
	var i;
	for (i = 0; i < inCodeArray.length; i ++) {
		if (inCodeArray[i].n == inCode) {
			AddLocIDToArray(inVar,inLocPos,inCodeArray[i].i);
		}
	}
}

function BuildBackupList(inVar)
{
	if (gVars[inVar].mWidgetType != g_TSPackageWidget) return;

	var mainArray = [];
	var impliedArray = [];
	var useDefaultLocsForBackup = gVars[inVar].pUseDefaultLocationsForBackup;
	AddToDebug(inVar, "doing backup list: useDefaultLocsForBackup=" + useDefaultLocsForBackup);
	if (useDefaultLocsForBackup) {
		PrepLocationListsForSearch(gVars[inVar].defaultLocations, inVar, mainArray, impliedArray);
	}
	var i;
	for (i = 0; i < gVars[inVar].pObj.pl.p.length; i ++) {
		if (gVars[inVar].pObj.pl.p[i].z == undefined) {
			if (useDefaultLocsForBackup) {
				FindPackageArrayAttribute(gVars[inVar].pObj.pl.p[i], inVar, 'd', 97, 97, mainArray, impliedArray);
			}
			else {
				if (gVars[inVar].pLimitDefaultToTop == false || gVars[inVar].pObj.pl.p[i].t == 1) {
					gVars[inVar].pObj.pl.p[i].z = 97;
				}
			}
		}
	}
}

function ObjectToString(inObject)
{
	var resultString = "";
	for (var propertyName in inObject) {
		if (typeof (inObject[propertyName]) != 'function') {
			resultString += propertyName + "=";
			resultString += inObject[propertyName];
			resultString += ";"
		}
	}
	return resultString;
}

function AddToDebug(inVar,inVal)
{
	if (g_IsDebug) {
		gVars[inVar].varDebug += inVal + "\n";
	}
}

// here we go through all of the packages
// for each package, we send it off to see if it has at least one of our "limit flags" checked
// if so, move on
// if not, anything >= 97 gets dumped to the "end" (list 99) -- unless it's > 200 (300 == excluded via strict processing of locations)
// anything < 97 gets dumped to its "alt" list (+100)
function ProcessFlags(inVar)
{
	if (gVars[inVar].mWidgetType != g_TSPackageWidget) return;
	if (gVars[inVar].pLimitFlags.initialized != true) return;

	for (var i = 0; i < gVars[inVar].pObj.pl.p.length; i++) {
		if (PkgHasOneOfEachLimitFlag(gVars[inVar].pObj.pl.p[i], inVar)) {
			if (gVars[inVar].pObj.pl.p[i].z == undefined) gVars[inVar].pObj.pl.p[i].z = 101;
		}
		else {
			if ((gVars[inVar].pObj.pl.p[i].z != undefined) && (gVars[inVar].pObj.pl.p[i].z != 300)) {
				if (gVars[inVar].pObj.pl.p[i].z >= 97)
					gVars[inVar].pObj.pl.p[i].z = 99;
				else
					gVars[inVar].pObj.pl.p[i].z += 100;
			}
		}
	}
}

// go through all of the flag arrays in the flag object
// this function checks to make sure the package in question has one of EACH array
function PkgHasOneOfEachLimitFlag(inPkg,inVar)
{
	var flagObj = gVars[inVar].pLimitFlags;
	for (var propertyName in flagObj) {
		if (typeof (flagObj[propertyName]) == 'object') {
			var hasOneOfThis = false;
			var curFlagArray = flagObj[propertyName];
			for (var limitFlagIter = 0; limitFlagIter < curFlagArray.length; limitFlagIter++) {
				if (PkgHasFlag(inPkg, curFlagArray[limitFlagIter])) {
					hasOneOfThis = true;
					break;
				}
			}
			if (hasOneOfThis == false) {
				return false;
			}
		}
	}
	return true;
}

// check the package for THIS flag
function PkgHasFlag(inPkg,inFlagID)
{
	for (var pkgFlagIter = 0; pkgFlagIter < inPkg.f.length; pkgFlagIter ++) {
		if (inPkg.f[pkgFlagIter] == inFlagID)
			return true;
	}
	return false;
}

// notes on merging:
//		list #96:  "overflow" packages from the "main" locations, if we want to limit the # from any given blog.  196 - overflow from +100 lists.
//		list #97:  "default" packages, in general "top deals"
//		list #98:  "leftover" main packages.  e.g. if 'orlando' is a location, but we say only 2 from orlando, leftover orlandos go here
//		list #99:  "leftover" alt packages.   e.g. if 'orlando' is a location, and a deal is nationwide, and we say a max of 2 nationwide, leftovers go here
// merge pkg ID lists into a single array for global processing
// inVar = array element in gVars to process
function MergeLists(inVar)
{
	AddToDebug(inVar, "inVar=" + inVar);
	AddToDebug(inVar, "gVars[inVar].varCurPageSize=" + gVars[inVar].varCurPageSize);
	AddToDebug(inVar, "gVars[inVar].pIncludeDirectLinks=" + gVars[inVar].pIncludeDirectLinks);
	AddToDebug(inVar, "gVars[inVar].pLimitDefaultToTop=" + gVars[inVar].pLimitDefaultToTop);
	AddToDebug(inVar, "gVars[inVar].pMaxFromUnselectedLocations=" + gVars[inVar].pMaxFromUnselectedLocations);
	AddToDebug(inVar, "gVars[inVar].pLimitFlags=" + ObjectToString(gVars[inVar].pLimitFlags));
	AddToDebug(inVar, "gVars[inVar].pSortByCreateTime=" + gVars[inVar].pSortByCreateTime);

	var numArrays = gVars[inVar].workLocArray.length;
	if (numArrays < 2) {
		gVars[inVar].workLocArray[1] = [];
		numArrays = 2;
	}
	var i;
	var resultArray = [];

	// create the empty arrays to hold assignments from the master package list
	for (i = 0; i < numArrays; i ++) {
		if (gVars[inVar].workLocArray[i] != undefined) {
			resultArray[i] = [];
			resultArray[i+100] = [];
		}
	}
	resultArray[96] = [];
	resultArray[97] = [];
	resultArray[98] = [];
	resultArray[99] = [];
	resultArray[196] = [];
	resultArray[200] = [];
	
	// go through the master pkg list, find the "z" variable, which indicates which array things should be assigned to
	// assign to that array no questions
	for (i = 0; i < gVars[inVar].pObj.pl.p.length; i ++) {
		if (gVars[inVar].pObj.pl.p[i].z == undefined) gVars[inVar].pObj.pl.p[i].z = 200;
		if (gVars[inVar].pObj.pl.p[i].z >= 0) {
			var useArray = gVars[inVar].pObj.pl.p[i].z;
			if (useArray <= 200)
				resultArray[useArray][resultArray[useArray].length] = gVars[inVar].pObj.pl.p[i];
		}
	}

	// shuffle all arrays if necessary
	if (gVars[inVar].pDoRandomize) {
		for (i = 0; i < numArrays; i ++) {
			if (gVars[inVar].workLocArray[i] != undefined) {
				fisherYates(resultArray[i]);
				fisherYates(resultArray[i+100]);
			}
		}
		fisherYates(resultArray[96]);
		fisherYates(resultArray[97]);
		fisherYates(resultArray[98]);
		fisherYates(resultArray[99]);
		fisherYates(resultArray[196]);
		fisherYates(resultArray[200]);
	}
	
	// now go through all of the "regular" arrays and reduce them to the requested size.
	// extra packages that are "top deals" go to array 97, extra packages of "i" go to 98, and extra packages of i+100 go to 99
	for (i = 0; i < numArrays; i ++) {
		if (gVars[inVar].workLocArray[i] != undefined) {
			ReduceResultArray(resultArray[i],resultArray[98],resultArray[97],gVars[inVar].locMax[i]);
			ReduceResultArray(resultArray[i+100],resultArray[99],resultArray[97],gVars[inVar].pMaxFromUnselectedLocations);
			ProcessArrayForBlogIDs(resultArray[i],resultArray[96],inVar);
			ProcessArrayForBlogIDs(resultArray[i+100],resultArray[196],inVar);
		}
	}
	
	// since these were filled further by the reduce logic, shuffle them again
	if (gVars[inVar].pDoRandomize) {
		fisherYates(resultArray[96]);
		fisherYates(resultArray[97]);
		fisherYates(resultArray[98]);
		fisherYates(resultArray[99]);
		fisherYates(resultArray[196]);
		fisherYates(resultArray[200]);
	}

	// put all of the arrays together in the correct order
	gVars[inVar].varResultArray = [];
	for (i = 0; i < numArrays; i ++) {
		if (gVars[inVar].workLocArray[i] != undefined) {
			DebugArray(inVar,resultArray[i],i);
			gVars[inVar].varResultArray = gVars[inVar].varResultArray.concat(resultArray[i]);
			DebugArray(inVar,resultArray[i+100],i+100);
			gVars[inVar].varResultArray = gVars[inVar].varResultArray.concat(resultArray[i+100]);
		}
	}
	if (gVars[inVar].pFillDisplayWithNonLoc) {
		AddResultArray(inVar,resultArray[96],96);
		AddResultArray(inVar,resultArray[97],97);
		AddResultArray(inVar,resultArray[98],98);
		AddResultArray(inVar,resultArray[99],99);
		AddResultArray(inVar,resultArray[196],196);
		AddResultArray(inVar,resultArray[200],200);
	}
	// gotta apply the final sort down here...  hopefully we don't make a mess - really this sort should ONLY apply on blog
	// widgets, not pkg widgets.
	if (gVars[inVar].pSortByCreateTime) {
		gVars[inVar].varResultArray.sort(CreateTimeCompareDesc);
	}
	if (g_IsDebug) {
		AddToDebug(inVar,'all packages:');
		DebugArray(inVar,gVars[inVar].pObj.pl.p);
	}
}

function CreateTimeCompareDesc(a, b)
{
	if (a.y > b.y) return -1;
	return 1;
}


function AddResultArray(inVar,inSrcArray,inArrayNum)
{
	DebugArray(inVar,inSrcArray,inArrayNum);
	gVars[inVar].varResultArray = gVars[inVar].varResultArray.concat(inSrcArray);
}

// go through an array of packages and spit out debugging information
function DebugArray(inVar,inArray,arrayNum)
{
	if (g_IsDebug) {
		AddToDebug(inVar,"output:"+arrayNum);
		for (i = 0; i < inArray.length; i ++) {
			var debugStr = '';
			var curPkg = inArray[i];
			debugStr += curPkg.i;
			debugStr += "("+curPkg.z+")/";
			debugStr += "(t:"+curPkg.t+",d:"+curPkg.d+",b:"+curPkg.b+")=,";
			debugStr += "[ld-,";
				for (var x = 0; x < curPkg.ld.length; x ++) {
					debugStr += curPkg.ld[x] + ',';
				}
			debugStr += "]";
			debugStr += "[,";
				for (var flagIter = 0; flagIter < curPkg.f.length; flagIter ++) {
					debugStr += 'f:' + curPkg.f[flagIter] + ',';
				}
			debugStr += "]";
			AddToDebug(inVar,debugStr);
		}
	}
}

function ProcessArrayForBlogIDs(inArray,dumpArray,inVar)
{
	if (gVars[inVar].mWidgetType == g_TSContentWidget) return;
	var maxArray = gVars[inVar].pMaxPerBlogArray;
	var maxPerBlog = gVars[inVar].pMaxPerBlog;
	for (var i = 0; i < inArray.length; i ++) {
		var useMaxArray = inArray[i].b;
		if (gVars[inVar].pMaxReassignArray[useMaxArray] != undefined) useMaxArray = gVars[inVar].pMaxReassignArray[useMaxArray];
		if (maxArray[useMaxArray] == undefined) maxArray[useMaxArray] = maxPerBlog;
		if (--maxArray[useMaxArray] < 0) {
			dumpArray.push(inArray[i]);
			inArray.splice(i,1);
			i--;
		}
	}
}

function ReduceResultArray(sourceArray,destArray,topArray,maxInArray)
{
	if (maxInArray < 0) return;									// everything in source can stay, so just return
	for (var i = maxInArray; i < sourceArray.length; i ++) {
		if (sourceArray[i].t == 1) {
			topArray[topArray.length] = sourceArray[i];
		}
		else {
			destArray[destArray.length] = sourceArray[i];
		}
	}
	if (sourceArray.length >= maxInArray)
		sourceArray.length = maxInArray;
}


// precreate the right array variables for holding the package IDs
// inVar = array element in gVars to process
function SetupLists(inVar)
{
	gVars[inVar].pkg1 = '';
	gVars[inVar].pkg2 = '';
	gVars[inVar].pkg3 = '';
}

// given gVars[inVar].workLocArray[1-3] populated with location IDs, lookup the right package IDs
// and return them in a string, formatted as "123,456,789"
// inVar = array element in gVars to process
function DoLocations(inVar)
{
	var did1Location = false;
	AddToDebug(inVar, "DoLocations:");
	AddToDebug(inVar, "---gVars[inVar].workLocArray.length=" + gVars[inVar].workLocArray.length);
	AddToDebug(inVar, "---gVars[inVar].defaultLocations.length=" + gVars[inVar].defaultLocations.length);
	if (gVars[inVar].workLocArray.length > 0) {
		var i;
		gVars[inVar].pkgLists = [];
		for (i = 0; i < gVars[inVar].workLocArray.length; i++) {
			if ((typeof gVars[inVar].workLocArray[i]) != "undefined") {
				if (gVars[inVar].workLocArray[i].length > 0) {
					did1Location = true;
					FindLocations(gVars[inVar].workLocArray[i], 'd', inVar, i, i + 100);
				}
			}
			if (g_IsDebug)
				AddToDebug(inVar, 'loc:' + i + ' = ' + gVars[inVar].workLocArray[i] + '(max:' + gVars[inVar].locMax[i] + ')');
		}
	}
	else if (gVars[inVar].defaultLocations.length > 0) {
		did1Location = true;
		FindLocations(gVars[inVar].defaultLocations, 'd', inVar, 1, 101);
	}
	// this sets all pacakges to array 1, as long as we're not doing "top deals only"
	if (did1Location == false && (gVars[inVar].pLimitDefaultToTop == false || gVars[inVar].mWidgetType == g_TSContentWidget)) {
		AddToDebug(inVar, "Did no locations!");
		var pArray = gVars[inVar].pObj.pl.p;
		for (var pi = 0; pi < pArray.length; pi++) {
			pArray[pi].z = 1;
		}
	}
}


// display an array element (package) in a row
// if this pkg has already been fetched, it uses that cached info
// otherwise it goes and gets it and then displays
// row = the row # in the widget to populate
// arrayPos = the array element in the final array of pkgIDs that we're working on
// gVar = array element in gVars to process
	// this function just stores the information regarding the package we're currently working on in the gFetchedPkgs array
	// so the appropriate widget, row in the widget, where it was found in the result array, etc, are stored in the global array
	// we don't ever check to see if it's already been fetched (the caching gets WAY too messy), so if the user has caching, we'll
	// get the benefit of that.  if not, all of this data is really small anyway.
	// then when the callback happens in the JSON, the code just looks for the package ID it's interested in and populates the
	// correct row.  then it "destroys" itself by setting its pkgID to 0.  
	// the reason we do that is because we might have 2 widgets looking for the same package.  if we don't set the ID we're after
	// to 0, the first will populate our row - and the 2nd fetch will populate our row too.  so the first request to come
	// back populates the first row requested in the global array
	// then the 2nd to return populates the 2nd row requested in the global array.
function PopulateRow(row,arrayPos,gVar)
{
	tswShowRow(row, true, gVar);

	var requestType = "";
	if (gVars[gVar].mWidgetType == g_TSContentWidget) {
		DoActualRowPopulate(row, gVar, gVars[gVar].varResultArray[arrayPos]);
	}
	else if (gVars[gVar].mWidgetType == g_TSPackageWidget) {
		requestType = "px";

		var myID = gVars[gVar].varResultArray[arrayPos].i;
		var myPkgPos = gFetchedPkgs.length;
		gFetchedPkgs[myPkgPos] = {};
		gFetchedPkgs[myPkgPos].pkgID = myID;
		gFetchedPkgs[myPkgPos].widgetRow = row;
		gFetchedPkgs[myPkgPos].resultArrayPos = arrayPos;
		gFetchedPkgs[myPkgPos].gVar = gVar;
		gFetchedPkgs[myPkgPos].dataType = requestType;

		var dispatchURL = g_serverURL + "/" + requestType + "/" + myID;
		tsw_loadjscssfile(dispatchURL);
	}
}

function tswShowRow(inRowNum, inShow, gVar)
{
	var dispVal = inShow ? "block" : "none";
	var rowID = "row-" + gVars[gVar].varTag + "-" + inRowNum;
	try { document.getElementById(rowID).style.display = dispVal; } catch (e) { }
}

// inObj = the raw data (in JSON form) returned by the "package info fetch" routine
function tswFetchedPkgInfoCallback(inObj)
{
	var i;
	for (i = 0; i < gFetchedPkgs.length; i++) {
		if (gFetchedPkgs[i].pkgID == inObj.id && gFetchedPkgs[i].dataType == inObj.dataType) {
			gFetchedPkgs[i].pkgObj = inObj;
			DoActualRowPopulate(gFetchedPkgs[i].widgetRow,gFetchedPkgs[i].gVar,gFetchedPkgs[i].pkgObj);
			gFetchedPkgs[i].pkgID = 0;
			break;
		}
	}
}

// callback executed after the appropriate PKG XML is fetched
// widgetRow = the row # in the widget to populate
// gVar = array element in gVars to process
// fetchedPkgObj = raw JSON data of package
// this function actually gets called for ALL display items - packages or content elements
	// all of the complexity happens inside the functions, which are set as the type of widget
	// is decided.  so this function just looks to see if a "set" function exists, and if it does
	// it passes whatever it has and assumes that function knows what to do.
function DoActualRowPopulate(widgetRow,gVar,fetchedPkgObj)
{
	var myTag = gVars[gVar].varTag;
	gVars[gVar].fSetCaption(widgetRow,fetchedPkgObj,myTag);
	if (gVars[gVar].fSetFacebook != undefined)	gVars[gVar].fSetFacebook(widgetRow, fetchedPkgObj, myTag);
	if (gVars[gVar].fSetDesc != undefined)		gVars[gVar].fSetDesc(widgetRow, fetchedPkgObj, myTag);
	if (gVars[gVar].fSetSource != undefined)	gVars[gVar].fSetSource	(widgetRow,fetchedPkgObj,myTag);
	if (gVars[gVar].fSetPostDate != undefined)	gVars[gVar].fSetPostDate(widgetRow, fetchedPkgObj, myTag);
	if (gVars[gVar].fSetPostUser != undefined)	gVars[gVar].fSetPostUser(widgetRow, fetchedPkgObj, myTag);
	if (gVars[gVar].fSetImage != undefined) gVars[gVar].fSetImage(widgetRow, fetchedPkgObj, myTag);
	if (gVars[gVar].fSetPrice != undefined)		gVars[gVar].fSetPrice	(widgetRow,fetchedPkgObj,myTag);
	if (gVars[gVar].fSetViewInfo != undefined) gVars[gVar].fSetViewInfo(widgetRow, fetchedPkgObj, myTag);
	DefaultSetRowBEID(widgetRow, fetchedPkgObj, myTag);
	DefaultSetTrackPixel(widgetRow, fetchedPkgObj, myTag);
}

function SetElementInnerHTML(widgetRow,inTag,inFieldLabel,inValue)
{
	var myElement = document.getElementById(GetElementID(widgetRow,inTag,inFieldLabel));
	if (myElement != null)
		myElement.innerHTML = inValue;
}

function SetElementSrc(widgetRow,inTag,inFieldLabel,inValue)
{
	var myElement = document.getElementById(GetElementID(widgetRow,inTag,inFieldLabel));
	if (myElement != null)
		myElement.src = inValue;
}

function DefaultSetTrackPixel(widgetRow,fetchedPkgObj,inTag)
{
	var trackURL = fetchedPkgObj.track;
	SetElementSrc(widgetRow,inTag,"pixel",trackURL);
}

function GetPkgLinkURL(inTag, inPkg, inLinkText)
{
	var myTag = FindGVar(inTag);
	var linkTarget = gVars[myTag].pLinkTarget;
	var trackClick = gVars[myTag].pTrackClick;

	var finalUC;
	var trackUC = gVars[myTag].pTrackUC;
	if (trackUC.length > 0) {
		var myURL = document.URL;
		var myRegex = /.*a([0-9]*)[\.htm,\/]/;
		if (myRegex.exec(myURL) != null) {
			var myHostID = myRegex.exec(myURL)[1];
			finalUC = trackUC.replace("#hostPkgID#", myHostID);
		}
		else {
			finalUC = trackUC;
		}
	}
	else {
		finalUC = trackUC;
	}

	var linkURL = gVars[myTag].pLinkURL;
	if (inPkg.direct == 1 && gVars[myTag].pUsingCustomLinkURL == true) {
		linkTarget = "_blank";
		linkURL = gVars[myTag].pCustomLinkURL;
	}
	var pkgURL = linkURL.replace("%s", inPkg.id);
	var aTag = '<a target="' + linkTarget + '" href="' + trackClick + pkgURL + finalUC + '">' + inLinkText + '</a>';
	return aTag;
}

function TSWHandlePackageClick(inURL, inTarget, inPkgID)
{
	if (inTarget.length < 1)
		window.location = inURL;
	else
		window.open(inURL, inTarget);
}


function cwSetCaption(widgetRow,fetchedPkgObj,inTag)
{
	var lHTML = '<a target="_blank" href="' + fetchedPkgObj.u + '">' + fetchedPkgObj.c + '</a>';
	SetElementInnerHTML(widgetRow,inTag,"label",lHTML);
}

function cwSetImage(widgetRow,fetchedPkgObj,inTag)
{
	var workIdx = FindGVar(inTag);
	if (gVars[workIdx].pShowImages == true && fetchedPkgObj.m.length > 0) {
		var lHTML = '<img src="' + fetchedPkgObj.m + '" border="0" class="tsw_cw_img_thumb"/>';
		SetElementInnerHTML(widgetRow,inTag,"img",lHTML);
	} else {
		var lHTML = '<img src="http://images.travelscream.com/spacer.gif" border="0" class="tsw_cw_img_spacer"/>';
		SetElementInnerHTML(widgetRow,inTag,"img",lHTML);
	}
}



// default function provided for setting a pkg caption into the display
// widgetRow = the row # in the widget to populate
// fetchedPkgObj = raw JSON data of package
// inTag = array element in gVars to process
function DefaultSetCaption(widgetRow,fetchedPkgObj,inTag)
{
	var myTag = FindGVar(inTag);
	var captionLength = gVars[myTag].pTruncateCaption;
	var truncateText = gVars[myTag].pTruncateText;
	
	var captionToUse;
	if (gVars[myTag].pUseAltCaption) {
		if (fetchedPkgObj.altcaption.length > 0) {
			captionToUse = fetchedPkgObj.altcaption;
		}
		else {
			captionToUse = fetchedPkgObj.caption;
		}
	}
	else {
		captionToUse = fetchedPkgObj.caption;
	}
	var dispCaption = unescape(captionToUse.substr(0,captionLength));
	dispCaption = dispCaption.replace(/#p/g,FetchConvertedPrice(inTag,fetchedPkgObj));
	
	var viewInfo = gVars[myTag].pViewInfo;
	var linkText;
	if (captionToUse.length > captionLength) {
		linkText = dispCaption+truncateText;
	}
	else {
		linkText = dispCaption;
	}
	var myHTML = GetPkgLinkURL(inTag,fetchedPkgObj,linkText);
	if (widgetRow == 1 && g_IsDebug == true && document.getElementById('roboDebug') == null) {
		myHTML += "<textarea>" + gVars[myTag].varDebug + "</textarea>";
	}
	SetElementInnerHTML(widgetRow,inTag,"label",myHTML);
}

function cwSetDesc(widgetRow,fetchedPkgObj,inTag)
{
	var lHTML = fetchedPkgObj.ds;
	var workIdx = FindGVar(inTag);
	if (gVars[workIdx].pShowDesc == true) {
		var descLength = gVars[workIdx].pTruncateDesc;
		var truncateTextDesc = gVars[workIdx].pTruncateTextDesc;
		var dispCWDesc = fetchedPkgObj.ds.substr(0,descLength);
		if (fetchedPkgObj.ds.length > descLength){
			SetElementInnerHTML(widgetRow,inTag,"description",dispCWDesc+truncateTextDesc);
		}
		else {
			SetElementInnerHTML(widgetRow,inTag,"description",dispCWDesc);
		}
	}
}

// default function provided for setting a pkg desc into the display
// widgetRow = the row # in the widget to populate
// fetchedPkgObj = raw JSON data of package
// inTag = array element in gVars to process
function DefaultSetDesc(widgetRow,fetchedPkgObj,inTag)
{
	var workIdx = FindGVar(inTag);
	if (gVars[workIdx].pShowDesc == true) {
		var descLength = gVars[workIdx].pTruncateDesc;
		var truncateTextDesc = gVars[workIdx].pTruncateTextDesc;
		var dispDesc = fetchedPkgObj.desc.substr(0,descLength);
		if (fetchedPkgObj.desc.length > descLength){
			SetElementInnerHTML(widgetRow,inTag,"description",dispDesc+truncateTextDesc);
		}
		else {
			SetElementInnerHTML(widgetRow,inTag,"description",dispDesc);
		}
	}
}


// default function provided for setting a pkg desc into the display
// widgetRow = the row # in the widget to populate
// fetchedPkgObj = raw JSON data of package
// inTag = array element in gVars to process
function DefaultSetFBLike(widgetRow, fetchedPkgObj, inTag)
{
	var workIdx = FindGVar(inTag);
	var myFBDomain = gVars[workIdx].pFacebookLikeDomain;
	if (myFBDomain.length < 1) myFBDomain = "deals.travelscream.com";
	var fbHTML = '<fb:like href="http://' + myFBDomain + '/a' + fetchedPkgObj.id + '.htm" font="arial"></fb:like>';
	SetElementInnerHTML(widgetRow, inTag, "tsfb", fbHTML);
}

// default function provided for setting a pkg desc into the display
// widgetRow = the row # in the widget to populate
// fetchedPkgObj = raw JSON data of package
// inTag = array element in gVars to process
function DefaultSetRowBEID(widgetRow, fetchedPkgObj, inTag)
{
	var workIdx = FindGVar(inTag);
	try {
		document.getElementById("row" + widgetRow + "_" + inTag + "_beid").value = fetchedPkgObj.id;
		document.getElementById("row" + widgetRow + "_" + inTag + "_bepc").value = tswGetBase62(fetchedPkgObj.id);
		document.getElementById("row" + widgetRow + "_" + inTag + "_bepcap").value = fetchedPkgObj.caption;
		document.getElementById("row" + widgetRow + "_" + inTag + "_vmi").href = "/a" + fetchedPkgObj.id + ".html";
	}
	catch (e) { }
}

function tswGetBase62(inID)
{
	var workID = '' + inID;
	workID = workID.substr(0, workID.length - 4);
	var string62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
	var outString = '';
	var workNum = workID;
	for (var i = 3; i >= 0; i--) {
		var curPow = Math.pow(62, i);
		var workDigit = Math.floor(workNum / curPow);
		outString += string62.substring(workDigit, workDigit + 1);
		workNum = workNum % curPow;
	}
	return outString;
}



// default function provided for setting a pkg image into the display
// widgetRow = the row # in the widget to populate
// fetchedPkgObj = raw JSON data of package
// inTag = array element in gVars to process
function DefaultSetImage(widgetRow,fetchedPkgObj,inTag)
{
	var workIdx = FindGVar(inTag);
	if (gVars[workIdx].pShowImages == true) {
		var newHTML = GetPkgLinkURL(inTag,fetchedPkgObj,'<img src="'+fetchedPkgObj.img+'" width="80" height="60" class="tsw_thumb"/>');
		SetElementInnerHTML(widgetRow,inTag,"img",newHTML);
	}
}

// default function provided for setting a source into the display
// widgetRow = the row # in the widget to populate
// fetchedPkgObj = raw JSON data of package
// inTag = array element in gVars to process
function DefaultSetSource(widgetRow,fetchedPkgObj,inTag)
{
	var workIdx = FindGVar(inTag);
	if (gVars[workIdx].pShowSource == true) {
		if (fetchedPkgObj.src.length > 0) {
			SetElementInnerHTML(widgetRow,inTag,"source",fetchedPkgObj.src);
		}
	}
}

function DefaultSetPostDate(widgetRow, fetchedPkgObj, inTag)
{
	try {
		var workIdx = FindGVar(inTag);
		if (fetchedPkgObj.postDateNoDay.length > 0) {
			SetElementInnerHTML(widgetRow, inTag, "postdate", fetchedPkgObj.postDateNoDay);
		}
	}
	catch (e) { }
}
function DefaultSetPostUser(widgetRow, fetchedPkgObj, inTag)
{
	try {
		var workIdx = FindGVar(inTag);
		if (fetchedPkgObj.userName.length > 0) {
			SetElementInnerHTML(widgetRow, inTag, "username", fetchedPkgObj.userName);
		}
	}
	catch (e) { }
}

function FetchConvertedPrice(inTag,inPkgObj)
{
	var workIdx = FindGVar(inTag);
	var workPrice = inPkgObj.price;
	if (workPrice > 0) {
		var priceSymbol = gVars[workIdx].pObj.pl.currSymbol;
		workPrice = Math.round(workPrice * gVars[workIdx].pObj.pl.currRatio);
		return (priceSymbol + workPrice);
	}
	return "";
}
// default function provided for setting a pkg price into the display
// widgetRow = the row # in the widget to populate
// fetchedPkgObj = raw JSON data of package
// inTag = array element in gVars to process
function DefaultSetPrice(widgetRow,fetchedPkgObj,inTag)
{
	var workIdx = FindGVar(inTag);
	if (gVars[workIdx].pShowPrice == true) {
		if (fetchedPkgObj.price > 0) {
			SetElementInnerHTML(widgetRow,inTag,"price",FetchConvertedPrice(inTag,fetchedPkgObj) + '<br/><span class="tsw_priceSub">& up</span>');
		}
		else {
			SetElementInnerHTML(widgetRow,inTag,"price",'Save');
		}
	}
}

// default function provided for setting a pkg "more info" link into the display
// widgetRow = the row # in the widget to populate
// fetchedPkgObj = raw JSON data of package
// inTag = array element in gVars to process
function DefaultSetViewInfo(widgetRow,fetchedPkgObj,inTag)
{
	var workIdx = FindGVar(inTag);
	if (gVars[workIdx].pShowViewInfo == true) {
		var viewVarInfo = gVars[workIdx].pViewInfo;
		SetElementInnerHTML(widgetRow,inTag,"moreInfo",GetPkgLinkURL(inTag,fetchedPkgObj,viewVarInfo));
	}
}

// clear a row in the display
// this uses try/catch so that it doesn't have to check for the existence of each field
// widgetRow = the row # in the widget to populate
// inTag = array element in gVars to process
function EraseRow(widgetRow,inTag)
{
	tswShowRow(widgetRow, false, FindGVar(inTag));
	SetElementInnerHTML(widgetRow,inTag,"label"," ");
	SetElementInnerHTML(widgetRow,inTag,"price"," ");
	SetElementInnerHTML(widgetRow,inTag,"moreInfo"," ");
	SetElementInnerHTML(widgetRow,inTag,"title"," ");
	SetElementInnerHTML(widgetRow,inTag,"footer"," ");
	SetElementInnerHTML(widgetRow,inTag,"source"," ");
	SetElementInnerHTML(widgetRow,inTag,"description"," ");
	SetElementInnerHTML(widgetRow,inTag,"img","<img src=\"http://static.travelscream.com/images/spacer.gif\"/>");
	SetElementSrc(widgetRow,inTag,"pixel","http://static.travelscream.com/images/spacer.gif");
}

// build the element ID from the appropriate components
function GetElementID(row,inTag,inIDBase)
{
	return inIDBase+"-"+inTag+"-"+row;
}

function SetWidgetHeadFoot(gVar)
{
	SetWidgetTitle(gVar);
	SetWidgetFooter(gVar);
}

function SetWidgetTitle(gVar)
{
	var myTag = gVars[gVar].varTag;
	var titleStr = gVars[gVar].pCustomTitle;
	if (titleStr.length < 1) return;

	if (titleStr.search('%ln') >= 0) {
		var outStr = '';
		try {
			for (i = 0; i < gVars[gVar].workLocArray.length; i ++) {
				if ((typeof gVars[gVar].workLocArray[i]) != "undefined") {
					var workLocName = g_MasterLocList[g_LookedUpLocations[gVars[gVar].workLocArray[i][0]]].s;
					outStr = SetInitialCaps(workLocName);
					break;
				}
			}
		}
		catch (err) {}
		titleStr = titleStr.replace('%ln',outStr,'g');
	}
	SetElementInnerHTML("0",myTag,"title",titleStr);
}

function SetWidgetFooter(gVar)
{
	var myTag = gVars[gVar].varTag;
	var footStr = gVars[gVar].pCustomFooter;
	if (footStr.length < 1) return;

	if (footStr.search('%ln') >= 0 || footStr.search('%li') >= 0) {
		var outStr = '';
		var outID = 0;
		try {
			for (i = 0; i < gVars[gVar].workLocArray.length; i ++) {
				if ((typeof gVars[gVar].workLocArray[i]) != "undefined") {
					var workLocName = g_MasterLocList[g_LookedUpLocations[gVars[gVar].workLocArray[i][0]]].s;
					outStr = SetInitialCaps(workLocName);
					outID = gVars[gVar].workLocArray[i][0];
					break;
				}
			}
		}
		catch (err) {}
		footStr = footStr.replace('%ln',outStr,'g');
		footStr = footStr.replace('%li',outID,'g');
	}
	SetElementInnerHTML("0",myTag,"footer",footStr);
}

function SetInitialCaps(inLocName)
{
	var outStr = '';
	try {
		var nextCap = true;
		for (var i = 0; i < inLocName.length; i ++) {
			if (nextCap && inLocName.charCodeAt(i) >= 97 && inLocName.charCodeAt(i) <= 122) {
				outStr += (String.fromCharCode(inLocName.charCodeAt(i) - 32));
				nextCap = false;
			}
			else
				outStr += (String.fromCharCode(inLocName.charCodeAt(i)));

			if (inLocName.charCodeAt(i) == 32)
				nextCap = true;
		}
	}
	catch (e) {}
	return outStr;
}

// main function for displaying packages in the display
// gVar = array element in gVars to process
function PopulateDisplay(gVar)
{
	var i, x;
	var myTag = gVars[gVar].varTag;
	if (gVars[gVar].varResultArray.length < 1) {
		for (i = 1; i <= gVars[gVar].varCurPageSize; i ++) {
			EraseRow(i,myTag);
		}
		SetElementInnerHTML(1,myTag,"label",gVars[gVar].pNoResultsString);
		return;
	}

	var lastArray = 1;
	g_PkgDispList='';
	for (i = gVars[gVar].varCurPos; i < (gVars[gVar].varCurPos+gVars[gVar].varCurPageSize); i ++) {
		if (i <= gVars[gVar].varResultArray.length) {
			if (g_PkgDispList.length > 0) g_PkgDispList += ',';
			g_PkgDispList+=gVars[gVar].varResultArray[i-1].i;
		}
	}
	for (i = gVars[gVar].varCurPos, x = 1; i < (gVars[gVar].varCurPos+gVars[gVar].varCurPageSize); i ++, x ++) {
		if (i > gVars[gVar].varResultArray.length) {
			EraseRow(i-(gVars[gVar].varCurPos-1),myTag);
		}
		else {
			if (gVars[gVar].pUseExtraPackageDividerLabel) {
				if (lastArray == 1 && lastArray != gVars[gVar].varResultArray[i - 1].z) {
					tswShowSeparator(x, gVar);
					lastArray = gVars[gVar].varResultArray[i - 1].z;
				}
			}
			PopulateRow(x,i-1,gVar);
		}
	}
	tswFacebookReparse(gVar);
}

function tswShowSeparator(inIndex,gVar)
{
	var elemArray = document.getElementsByName('separator-' + gVars[gVar].varTag);
	for (var x = 0; x < elemArray.length; x++) {
		if (x == (inIndex - 1)) {
			if (gVars[gVar].pCustomNoMatchSeparator.length > 0) {
				elemArray[x].innerHTML = gVars[gVar].pCustomNoMatchSeparator;
			}
			elemArray[x].style.display = "block";
		}
		else {
			elemArray[x].style.display = "none";
		}
	}
}

function tswFacebookReparse(gVar)
{
	try {
		if (gVars[gVar].mWidgetType == g_TSPackageWidget) tsFBParse();
	}
	catch (e) { }
}

// increment or decrement the position to go to the right page
// inX = difference in pos to apply
// inTag = "tag" of element in gVar array
function ChangePage(inX,inTag)
{
	var myVar = FindGVar(inTag);
	gVars[myVar].varCurPos += (inX * gVars[myVar].varCurPageSize);
	PopulateDisplay(myVar);
}

// lookup a gVar by its tag	
// inTag = value to search in varTag member in gVars array
function FindGVar(inTag)
{
	var i;
	for (i = 0; i < gVarCount; i ++) {
		if (gVars[i].varTag == inTag)
			return i;
	}
	return -1;
}

// randomize the elements in an array
function fisherYates ( myArray ) 
{
	var i = myArray.length;
	if ( i == 0 ) return false;
	while ( --i ) {
		var j = Math.floor( Math.random() * ( i + 1 ) );
		var tempi = myArray[i];
		var tempj = myArray[j];
		myArray[i] = tempj;
		myArray[j] = tempi;
	}
}

function DoDirectLinks(inVar)
{
	if (gVars[inVar].mWidgetType != g_TSPackageWidget) return;
	var myDL;
	// pIncludeDirectLinks is a tri-state:
	//		0 = ignore
	//		1 = include only DL
	//		-1 = exculde all DL
	switch (gVars[inVar].pIncludeDirectLinks) {
	case 0:
		return;
	case 1:
		myDL = 1;
		break;
	case -1:
		myDL = 0;
		break;
	}
	var maxIter = gVars[inVar].pObj.pl.p.length;
	for (i = 0; i < maxIter; i++) {
		if (gVars[inVar].pObj.pl.p[i].d != myDL) {
			gVars[inVar].pObj.pl.p[i].z = -1;
		}
	}
}


// find locations (either "dest" or "orig", based on inT)
// and merge them to the appropriate list
// inLocIDList = list of locations we're searching for
// inT = location type (dest or origin) to search for... only dest for now
// gVar = array index in gVars to use
function FindLocations(inLocIDList,inT,gVar,inLocPos,inLocAltPos)
{
	var mainArray = [];
	var impliedArray = [];
	PrepLocationListsForSearch(inLocIDList, gVar, mainArray, impliedArray);

	var maxIter = gVars[gVar].pObj.pl.p.length;
	var i;
	for (i = 0; i < maxIter; i++) {
		FindPackageArrayAttribute(gVars[gVar].pObj.pl.p[i], gVar, inT, inLocPos, inLocAltPos, mainArray, impliedArray);
	}
}

function PrepLocationListsForSearch(inLocIDList, gVar, outMainArray, outImpliedArray)
{
	var maxIter = inLocIDList.length;

	// this loop builds the implied array for each element in the location list.
	// the inner loop is for copying the built array into a merged array for passing to the code that does the 
	// intersect test with the packages.
	for (var i = 0; i < maxIter; i++) {
		outMainArray[inLocIDList[i]] = 1;
		BuildImpliedListFromID(inLocIDList[i]);
		AddToDebug(gVar, 'implied for:' + inLocIDList[i]);

		var iterArray = g_LookedUpImplied[inLocIDList[i]];
		for (var propertyName in iterArray) {
			// gotta check the type of the array element here - prototype-1.6.0.2.js file adds functions to the array object,
			// and those appear in the     for...in    iterator.  as far as i can tell, they appear at the END of the array,
			// so that's why we can break we find one.
			if (typeof iterArray[propertyName] == 'function') break;
			outImpliedArray[propertyName] = 1;
			AddToDebug(gVar, propertyName);
		}
		AddToDebug(gVar, '---');
	}
}




// inLocIDList = list of locations we're looking for
// inPkgLocs = list of locations on the pkg (O or D) that we're checking against
// gVar = array index in gVars to use
function FindPackageArrayAttribute(inPkg,gVar,inT,inLocPos, inLocAltPos,inMainArray,inImpliedArray)
{
	if (inPkg.z != undefined && inPkg.z < 100) return;
	
	var locArray;
	if (inT == 'd')
		locArray = inPkg.ld;
	else
		locArray = inPkg.lo;

	if (ArraySect(locArray, inMainArray)) {
		inPkg.z = inLocPos;
		return;
	}
	if (inLocAltPos != 0 && inLocAltPos != undefined) {
		if (ArraySect(locArray, inImpliedArray)) {
			inPkg.z = inLocAltPos;
			return;
		}
	}
	if (gVars[gVar].strictLocationProcessing) {
		if (inPkg.t == 1 && gVars[gVar].pUseExtraPackageDividerLabel)
			inPkg.z = 200;
		else
			inPkg.z = 300;
	}
}

function LocIDSort(a,b)
{
	if (a > b) return 1;
	return -1;
}

function LookupID(inID)
{
	if (g_LookedUpLocations[inID] != undefined) return g_LookedUpLocations[inID];
	return 0;
}

function BuildImpliedListFromID(inID)
{
	if (g_LookedUpImplied[inID] == undefined) {
		var workArray = [];
		FindParents(inID, workArray);
		FindChildren(inID, workArray);
		
		var resultArray = [];
		for (var wi = 0; wi < workArray.length; wi ++) {
			resultArray[workArray[wi]] = 1;
		}
		g_LookedUpImplied[inID] = resultArray;
	}
}

function FindChildren(inID, inArray)
{
	var childList = g_LookedUpChildren[inID];
	if (childList == undefined) return;
	
	for (var i = 0; i < childList.length; i ++) {
		inArray.push(childList[i]);
		FindChildren(childList[i], inArray);
	}
}

function FindParents(inID, inArray, inDepth)
{
	if (inDepth == undefined) inDepth = 0;
	if (inDepth > 20) return;
	
	var myParent = g_MasterLocList[LookupID(inID)].p;
	if (myParent != 0) {
		inArray.push(myParent);
		FindParents(myParent, inArray, inDepth + 1);
	}
}

var gSectCount = 0;

// inPkgArray - the list of locations in a "plain" array of a package
// inLocArray - the "indirect" array of locations to check
function ArraySect(inPkgArray,inLocArray)
{
	for (var ldIter = 0; ldIter < inPkgArray.length; ldIter ++) {
		if (inLocArray[inPkgArray[ldIter]] == 1) {
			return true;
		}
	}
	return false;
}

function AddLocIDToArray(inVar,inLocPos,inLocID)
{
	if (inLocID.length < 1) return;
	if (gVars[inVar].workLocArray[inLocPos] == undefined) {
		gVars[inVar].workLocArray[inLocPos] = [];
		if (gVars[inVar].locMax[inLocPos] == undefined) {
			gVars[inVar].locMax[inLocPos] = -1;
		}
	}
	var workArray = gVars[inVar].workLocArray[inLocPos];
	workArray[workArray.length] = inLocID;
}



// how many packages in the master list?
// gVar = index of element in gVars
function GetPkgCount(gVar)
{
	return gVars[gVar].pObj.pl.p.length;
}

//function TSWCopyArray(inSrc)
//{
//	var destArray = [];
//	for (key in inSrc) {
//		destArray[key] = inSrc[key];
//	}
//	return destArray;
//}






function tsw_loadjscssfile(filename)
{
	if (g_LoadViaHeadTag) {
		var fileref=document.createElement('script')
		fileref.setAttribute("type","text/javascript")
		fileref.setAttribute("src", filename)

		if (typeof fileref!="undefined")
			document.getElementsByTagName("head")[0].appendChild(fileref)
	}
	else {
		document.write('<scr'+'ipt type="text/javascript" src="'+filename+'"></scr'+'ipt>');
	}
}

function tswPrintDate()
{
	today = new Date();
	weekDayName = new Array ("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday")
	monthName = new Array ("January","February","March","April","May","June","July","August","September","October","November","December")
	document.write(monthName[today.getMonth()] + " " + today.getDate() + ", " + today.getFullYear());
}

function PointCompareDesc(a,b)
{
	if (a.x > b.x) return -1;
	return 1;
}

function PointCompareAsc(a,b)
{
	if (a.x > b.x) return 1;
	return -1;
}




function tswSetLocIDsCheck(inTag)
{
	tswSetIncludeOnlyFlags("11-12-13", inTag);
	privateDoLocationDataReset(FindGVar(inTag));
	tswSetLocID(FetchCheckBoxList("tsw_locCheck"), 1, inTag);
	tswSetIncludeOnlyFlags(FetchCheckBoxGroup("tsw_flagCheck"), inTag);
	tswRedisplayWidget(inTag);
}

function FetchCheckBoxList(inName)
{
	var myChecks = document.getElementsByName(inName);
	var newLocString = "";
	for (var i = 0; i < myChecks.length; i++) {
		if (myChecks[i].checked) {
			if (newLocString.length > 0) newLocString += "-";
			newLocString += myChecks[i].value;
		}
	}
	return newLocString;
}

function FetchCheckBoxGroup(inName)
{
	var myArray = {};

	var myFlags = document.getElementsByName(inName);
	for (var i = myFlags.length - 1; i > -1; i--) {
		if (myFlags[i].checked && myFlags[i].value.length > 0) {
			var curGroup = myFlags[i].getAttribute("tswfGroup");
			if (curGroup == null) curGroup = "default";
			if (myArray[curGroup] == undefined) {
				myArray[curGroup] = [];
			}
			PushStringToArray(myFlags[i].value, myArray[curGroup]);
		}
	}
	return myArray;
}

function tswClickSetFlag(inNewTitle, inFlags, inTag)
{
	tswSetLocID('', 1, inTag, true);
//	tswDefaultShowsAllPackages(inTag);
	tswSetIncludeOnlyFlags(inFlags, inTag);
	tswSetCustomTitle(inNewTitle, inTag);
	tswRedisplayWidget(inTag);
}

function tswClickSetLocation(inNewTitle, inLocIDs, inTag)
{
	tswSetLocID(inLocIDs, 1, inTag, true);
//	tswLimitDefaultToTopPackages(inTag);
	tswSetCustomTitle(inNewTitle, inTag);
	tswRedisplayWidget(inTag);
}

function tswClickSetTopDeals(inNewTitle, inTag)
{
	tswSetTopDealsOnly(inTag);
	tswSetCustomTitle(inNewTitle, inTag);
	tswRedisplayWidget(inTag);
}

function PushStringToArray(inString, inArray)
{
	var workArray = inString.split("-");
	for (var i = workArray.length - 1; i > -1; i--) {
		if (workArray[i].length > 0) {
			inArray.push(workArray[i]);
		}
	}
}






function DoSpecificDebug(inListItem,inPrefix)
{
	var maxIter = gVars[inListItem].pObj.pl.p.length;
	for (var i = 0; i < maxIter; i++) {
		if (gVars[inListItem].pObj.pl.p[i].i == 409265791) SpecificOut(gVars[inListItem].pObj.pl.p[i], inPrefix);
	}
}

function SpecificOut(inPkg, inPrefix)
{
	alert(inPrefix + '\r\nid:' + inPkg.i + '//z:' + inPkg.z);
}


