	//constants
			var TOP = "Top";
			var LEFT = "Left";
			var PADDING_TOP = 10;
			var TOP_BORDER_WIDTH = 1;
			var ELEMENT_DIV = "Div";
			var SHOW = "show";
			var HIDE = "hide";
			var TIMER_MILLISECONDS = 700;
			var COMPETITOR = "competitor";
			var AIC_COMP_TRIMS = "aic-comp-trims";
			var AIC_ALL_COMP_FRAG = "aic-comp-frag";
			var AIC_BATCH_NUMBER = 10;
			var LAST_SUB = "";
			var TEXT_SELECT_NEW = "Select New Model >>";
			var TEXT_CLEAR_SELECT = "Clear Selection >>";
			var MSG_WORKING = "Working ... &nbsp;&nbsp;&nbsp;<a href=\"javascript:killAjax();\">Stop/Reset</a>";
			var COMPARE_ERROR_MARKUP = "<div style=\"color:#ff0000; font-size: 11px; font-weight: bold;\">An error has occurred with this comparison. Please Select a new comparison set and try again</div>";
			var MENU_HEIGHT = 300;
			var DIR_UP = "up";
			var DIR_DOWN = "down";
			var _interval = null; //used for sliding competitors
			var isSliding = false; // "
			var SCROLL_INCREMENT = 5;
			var LEGAL_TOP_COORDINATE = "600px";
			if(navigator.userAgent.indexOf("Safari") != -1) SCROLL_INCREMENT = 15; //Safari is slow
			var Menu1Subs = new Array();
			var Menu2Subs = new Array();
			var Menu3Subs = new Array();
			var Menu4Subs = new Array();
			var columnElementIDs = new Array();
			columnElementIDsReplaceChar = "~";
			columnElementIDs.push("m" + columnElementIDsReplaceChar + "Housing");
			columnElementIDs.push("menu" + columnElementIDsReplaceChar);
			columnElementIDs.push("vehicleImg" + columnElementIDsReplaceChar);
			columnElementIDs.push("m" + columnElementIDsReplaceChar + "RadioHousing");
			columnElementIDs.push("m" + columnElementIDsReplaceChar + "RadioBlockName");
			columnElementIDs.push("m" + columnElementIDsReplaceChar + "RadioBlockNameMsg");
			columnElementIDs.push("m" + columnElementIDsReplaceChar + "RadioBlockList");
			var hasMore = false; //a variable the value of which will be affected by calls for all Models within the competitor tab
			
			
			//actions for Ajax:
			var ACTION_GET_ALL_MITSU = "/MMNA/getMitsuModels.do";
			var ACTION_GET_ALL_TRIMS = "/MMNA/getAllTrims.do";
			var ACTION_GET_COMPARISON = "/MMNA/compareModels.do";
			var ACTION_GET_COMP_TO_TRIM = "/MMNA/getCompTrims.do";
			
			var menus = new Object(); //hashmap to hold references to each dynamicMenu object on the page
			var menuMirrors = new Object(); // will mirror the previous for values which need to persist from menu creation to re-creation
			var lastOpened = "";
			
			var defaultModelReference = null; //will hold a reference to the model wrapper associated with the current "model-context" of the site
			var StateMonitor; // will be initialized below as of type selectedTrimsMonitor
			var SpaceManager; // will be initialized below as of type coordinatesHolder
			var ImageMapper; // is of type aicToMitsuMapper, will be initialized below
			var RolloverTracker //is of type rollOvertracker, will be initialzed below
			var aicModels = new Object(); //data structure of mitsu models
			var hovers = new Array(); //array to track hovering styling on menus:
			var compareData;
			
			Array.prototype.unique = function() {
			
			 var a = [];
			 var l = this.length;
			 for( i = 0; i < l; i++ ) {
			 	if( a.toString().indexOf( this[i], 0) < 0 ) {
					a.push( this[i] ); 
				}
				
			 }
			 
			 return a;
			};
			
			function findIndexes(arr, value) {
				for(var i = 0; i < arr.length; i++) {
					if(arr[i] == value) {
						alert(value + " found at index " + i);
					}
				}
			}
			
			function fetch(id) {
				return document.getElementById(id);
			}
			
			function showHideFamily(toDo,refParent) {
				/*
					can be overloaded to provided a child-element-type to hide
				*/
				var elemType = arguments.length == 3 ? arguments[2] : "DIV";
				//TBD:
				
				var state = "";
				if(toDo == SHOW) {
					state = 'visible';
				}
				else if(toDo == HIDE) {
					state = 'hidden';
				}
				refParent.style.visibility = state;
				if(refParent.childNodes != null) {
					
					for(var i = 0; i < refParent.childNodes.length; i++) {
						//alert(refParent.childNodes[i].nodeName);
						if(refParent.childNodes[i].nodeName == elemType) {
							//alert("hiding " + refParent.childNodes[i].id + "; " + state);
							refParent.childNodes[i].style.visibility = state;
						}
					}
				}
			}
			
			function getPos(element, which) {
			/*
				@which --> "Left" or "Top"
			*/
				pos = 0
				while (element != null) {
				pos += element["offset" + which]
				element = element.offsetParent;
				}
				return pos;
			} 
			
			
			
			function addMenuToElementAssociation(menuRef, elementID, subMenuID) {
				menuRef.components[elementID] = subMenuID;
			}
			
			function testFuncBuilder(arg) {
				var x = arg;
				return function() { alert(x); };
			}
			
		
			
			function showMenu(obj, menuID) {
				//alert(obj.id + " " + menuID);
				//get a reference to the "owner" menu with which this functions caller is associated
				//alert(menuID.length);
				
				//var menuWrapper = menus[menuID];
				//if(menuWrapper) {
					//alert('wrap');
					//if the caller has a sub-menu, display it
					//var sub = menuWrapper.components[obj.id];
					var sub = obj.id + "Sub";
					
					//if(sub) {
						//fetch("feedback").value = sub;
						
						//alert("has sub!");
						//get a reference to the sub html element
						var refSubElem = fetch(sub);
						if(refSubElem != null) {
							LAST_SUB = sub;
							/*
							"scrolling" functionality
							
							child[lastcount].offsetheight + .offsettop
							javascript:alert(fetch("menu2SubElem2Sub").childNodes[fetch("menu2SubElem2Sub").childNodes.length - 1].nodeName)
							
							*/
							//is the first child the up arrow div?
							var scrollID = refSubElem.id + "Scroller";
							if(menuID != "menu1" && StateMonitor.getCompetitiveTabState() == selectedTrimsMonitor.ON) {
								var firstID = refSubElem.childNodes[0].id;
								if(firstID != refSubElem.id + "Up") {
									var height = refSubElem.lastChild.offsetHeight + refSubElem.lastChild.offsetTop;
									if(height > MENU_HEIGHT) {
										htmlStore = refSubElem.innerHTML;
										putHtml = "<div id=\"" +refSubElem.id + "Up" + "\" style=\"position:absolute; cursor:pointer; background-color:#cecece; width: 225px; z-index: 5\"><img onmouseover=\"moveSlides('" + scrollID + "','" + DIR_DOWN + "'); this.src='/MMNA/images/compare/cmp_up_arrow_over.en-us.gif';\" onmouseout=\"stopSlides(); this.src='/MMNA/images/compare/cmp_up_arrow.en-us.gif';\" border=\"0\" src=\"/MMNA/images/compare/cmp_up_arrow.en-us.gif\"/></div>";
										putHtml += "<div id=\"" + scrollID + "\" style=\"position:absolute; top:18px;  z-index: 1\">";
										putHtml += htmlStore;
										putHtml += "</div>";
										putHtml += "<div style=\"position:absolute; cursor:pointer; background-color:#cecece; width: 225px; z-index: 5; top:"+(MENU_HEIGHT - 19)+"px\"><img onmouseover=\"moveSlides('" + scrollID + "','" + DIR_UP + "'); this.src='/MMNA/images/compare/cmp_down_arrow_over.en-us.gif';\" onmouseout=\"stopSlides(); this.src='/MMNA/images/compare/cmp_down_arrow.en-us.gif';\" border=\"0\" src=\"/MMNA/images/compare/cmp_down_arrow.en-us.gif\"/>/div></div>";
										refSubElem.innerHTML = putHtml;
										//alert("put:\n" + putHtml);
										if(sub.length >= 24) {
											//alert("sub:\n" + refSubElem.innerHTML);
										}
									}
								}
							}
							
						
						//get the positioning info of @obj, to be used as a benchmark:
						//alert(getPos(obj, TOP));
						//var extra = (fetch(scrollID) != null) ? 19 : 0;
						var top;
						if (fetch(scrollID)) {
							top = -65;
						} else {
							top = getPos(obj, TOP)  - getPos(fetch("dynamicContainer"), TOP);
						}
						
						
						var dynamAbsTop = getPos(fetch("dynamicContainer"), TOP);
						var bdOffset = parseInt(fetch("pageContent").style.left);
						var left = getPos(obj, LEFT) - bdOffset;
						
						if(sub.length >= 24) {
									var refSecondary = fetch(sub.substring(0, 16));
									if(refSecondary) {
										//case of a tertiary nav sub
										if (fetch(scrollID) != null) {
											top = -65;
										} else {
										var extra = fetch(scrollID) != null ? fetch(scrollID).offsetTop : 0;
										//top = (getPos(refSecondary, TOP) - getPos(fetch("dynamicContainer"), TOP) + 18) + (obj.offsetTop + extra);
										
										top = getPos(obj, TOP) - getPos(fetch("dynamicContainer"), TOP);
										//fetch("feedback").value = top + " | " + (refSubElem.lastChild.offsetTop + refSubElem.lastChild.offsetHeight) + " | " + (refSubElem.lastChild.offsetTop + refSubElem.lastChild.offsetHeight + top);
										//top = document.body.clientHeight - refSubElem.offsetHeight;
										
										if((refSubElem.lastChild.offsetTop + refSubElem.lastChild.offsetHeight + top) > (document.body.clientHeight - dynamAbsTop) + document.body.scrollTop) {
											//top = document.body.clientHeight - (top + refSubElem.lastChild.offsetTop + refSubElem.lastChild.offsetHeight);
											//fetch("feedback").value = "Move It!";
											top = fetch(scrollID) != null ? -65 : (document.body.clientHeight - dynamAbsTop + document.body.scrollTop) - (refSubElem.lastChild.offsetTop + refSubElem.lastChild.offsetHeight) - 15;
										}
										
										}
									}
								}
						
						
						//in the case where @obj.id == @menuID, @obj is a "top-level" object;
						//hence the sub will have the same left as @obj; otherwise, it needs to be to the *left* of @obj
						//The exact inverse is the case, with respect to incrementing the top value
						if(obj.id != menuID) {
							//is the left value of @obj < left of fetch(@menuID)? 
							if(StateMonitor.getCompetitiveTabState() == selectedTrimsMonitor.ON && menuID != "menu1" && menuID != "menu2") {
								if((refSubElem.lastChild.offsetTop + refSubElem.lastChild.offsetHeight + top) > (document.body.clientHeight - dynamAbsTop) + document.body.scrollTop) {
									//top = document.body.clientHeight - (top + refSubElem.lastChild.offsetTop + refSubElem.lastChild.offsetHeight);
									//fetch("feedback").value = "Move It!";
									top = fetch(scrollID) != null ? -65 : (document.body.clientHeight - dynamAbsTop + document.body.scrollTop) - (refSubElem.lastChild.offsetTop + refSubElem.lastChild.offsetHeight) - 15;
								}
								left -= refSubElem.offsetWidth;
							}
							else {
								//if(StateMonitor.getCompetitiveTabState() == selectedTrimsMonitor.OFF) {
									if((refSubElem.lastChild.offsetTop + refSubElem.lastChild.offsetHeight + top) > (document.body.clientHeight - dynamAbsTop) + document.body.scrollTop) {
											//top = document.body.clientHeight - (top + refSubElem.lastChild.offsetTop + refSubElem.lastChild.offsetHeight);
											//fetch("feedback").value = "Move It!";
											top = fetch(scrollID) != null ? -65 : (document.body.clientHeight - dynamAbsTop + document.body.scrollTop) - (refSubElem.lastChild.offsetTop + refSubElem.lastChild.offsetHeight) - 15;
										}
								//}
								left += obj.offsetWidth;
							}
						}
						else {
								//alert(fetch(possibleSubID));
							//increase top based on @obj's height:
							top += obj.offsetHeight;
							//lastOpened = "";
						}
						
						//alert(refSubElem.id);
						//position the sub element:
						refSubElem.style.top = top + "px";
						refSubElem.style.left = left + "px";
						refSubElem.style.visibility = "visible";
					//}
				//}
				}
			}

				
			
			function getKey(hMap, val) {
				/* for @hMap, looks to see if there is an associated key with @val
					assumes that @val is unique to one key; or, at least, returns the first
					instance found
				*/
				var key = null;
				for(k in hMap) {
					if(hMap[k] == val) {
						key = k;
						break;
					}
				}
				return key;
			}
			
			function isAnAncestor(idStartingPt, candidateAncestor, menuID) {
				var isAncestor = false;
				//get a reference to the menu wrapper:
				var wrapper = menus[menuID];
				if(wrapper != null) {
					//get the sub menu which is the the container of the starting point:
					var ancestor = fetch(idStartingPt).parentNode.id;
					while(ancestor != null && ancestor != menuID) {
						if(ancestor == candidateAncestor) {
							isAncestor = true;
							//alert("ancestor!");
							break;
						}
						else {
							//get the key in components hashTable corresponding to the ancestor:
							var ancestorKey = getKey(wrapper.components, ancestor);
							if(ancestorKey && ancestorKey != menuID) {
								ancestor = fetch(ancestorKey).parentNode.id;
							}
							else {
								ancestor = null;
							}
							
						}
					}
				}
				
				
				return isAncestor;
			}
			
			function hideLastSub(obj) {
				//fetch("feedback").value = "mo= " + obj.id + " last = " + LAST_SUB;
				//why length of 8? --> menu_Sub
				if(LAST_SUB.length != 8 && obj.id.indexOf(LAST_SUB) == -1) {
					var ref = fetch(LAST_SUB);
					ref.style.visibility = "hidden";
					//hack for tertiary nav:
					
					if(LAST_SUB.length >= 24) {
						//build the string of the sub which would have been opened at the secondary level
						var subStrLimit = 16;
						var secondaryID = LAST_SUB.substring(0, subStrLimit); // again, assumptions about length can be made because of how the elements are named when built
						
						if(obj.id.indexOf(secondaryID) == -1) {
							var refSecondary = fetch(secondaryID);
							if(refSecondary != null) {
								refSecondary.style.visibility = "hidden";
							}
						}
						
					}
					
				}
			}
			
			function hideSubmenus(menuID) {
				
				var subsArray = eval("Menu" + (menuID.charAt(menuID.length - 1)) + "Subs");
				
					for(var i = 0; i < subsArray.length; i ++) {
						//get a reference to the sub
						
						var subRef = fetch(subsArray[i]);
						if(subRef != null) {
							if(subRef.style.visibility = "visible") {
								subRef.style.visibility = "hidden";
								if(subRef.onhidden != null) {
									subRef.onhidden();
								}
							}
						}
					}
				
				
				
			}
			
			
			
		function hideAllNowAsync(menuID) {
			var callback = "hideSubmenus('" + menuID + "')";
			var temp = setTimeout(callback, 1);
		}
		
		function timeoutHideSubMenus(menuID) { //selstart
			//get a reference to this menu structure:
			var menuRef = menus[menuID];
			if(menuRef != null) {
				if(!menuRef.timerOn) {
					var callback = "hideSubmenus('" + menuID + "')";
					menuRef.timerOn = true;
					menuRef.timerID = setTimeout(callback, menuRef.timerTicksInMS);
				}
			}
		}
		
		function clearTimedOutHide(menuID) { //selstop
			//get a reference to this menu structure:
			var menuRef = menus[menuID];
			if(menuRef != null) {
				//if(menuRef.timerOn) {
					try {
					clearTimeout(menuRef.timerID);
					menuRef.timerID = null;
					menuRef.timerOn = false;
					}
					catch(e) {
						
					}
				//}
			}
		}
		
		function trimRadioHandler(obj, parentKey, menuColumn) {
			//alert(obj.id + " " + obj.value + " column: " + menuColumn + " parent: " + parentKey);
			var trimID = obj.value;
			var modelWrapper = aicModels[parentKey];
			if(modelWrapper == null) {
				//could be a competitor:
				try {
					modelWrapper = eval(parentKey);
				}
				catch(e) {
					alert(e);
				}
			}
			if(modelWrapper != null) {
				//alert(trimID);
				//construct the names of the elements to toggle on/off
					var idImg = "vehicleImg" + menuColumn;
					var idRadioName = "m" + menuColumn + "RadioBlockName";
					//grab references:
					
					var refImg = fetch(idImg);
					var refVehName = fetch(idRadioName);
					var brokeOut = false;
					if(refImg && refVehName) {
						var trimRef;
						for(var i=0; i < modelWrapper.trims.length; i++) {
							trimRef = modelWrapper.trims[i];
							if(trimRef.id == trimID) {
								brokeOut = true;
								break;
							}
						}
						if(brokeOut) {
							//record state for the system:
							StateMonitor.trimEvent(selectedTrimsMonitor.TYPE_SELECTED, menuColumn, trimID, parentKey);
							checkForTrimBasedReload(menuColumn, trimID);
							//now we have the right trim reference:
							var img = new Image();
							img.src = trimRef.img;
							refImg.innerHTML = '<img src="' + img.src + '"/>';
							var markup;
							if(menuColumn != 1 && StateMonitor.getCompetitiveTabState() == selectedTrimsMonitor.ON) {
								markup = "<b>" + trimRef.shortName + "</b><br/><br/>";
							}
							else {
								markup = "<b>" + modelWrapper.name + "<br/>" + trimRef.shortName + "</b><br/><br/>";
							}
							refVehName.innerHTML = markup;
							
						}
					}
			}
		}
		

		
		function resetMenus(menuColumn) {
			
			StateMonitor.setHaveCompareData(false);
			
			//construct the names of the elements to toggle on/off
				var idMenu = "menu" + menuColumn;
				var idImg = "vehicleImg" + menuColumn;
				var idRadio = "m" + menuColumn + "RadioHousing";
				//grab references:
				var refMenu = fetch(idMenu);
				var refImg = fetch(idImg);
				var refHousing = fetch(idRadio);
				if(refMenu != null && refImg != null && refHousing != null) {
					//record state for the system:
					StateMonitor.trimEvent(selectedTrimsMonitor.TYPE_CLEARED, menuColumn, null);
					
					refImg.style.visibility = "hidden";
					refHousing.style.visibility = "hidden";
					//clear content of the housing too:
					clearVehicleSelectionContent(menuColumn);
					refMenu.style.visibility = "visible";
				}
				
		}
		
		function clearVehicleSelectionContent() {
			//if no arguments, cycle through all, otherwise 
			//use the integer passed in
			
			if(arguments.length == 0) {
				for(var i = 0; i < StateMonitor.getNumberOfColumns(); i++) {
					var menuColumn = i + 1;
					var blockName = "m" + menuColumn + "RadioBlockName";
					var blockList =  "m" + menuColumn + "RadioBlockList";
					fetch(blockName).innerHTML = "";
					fetch(blockList).innerHTML = "";
				}
			}
			else {
				var menuColumn = arguments[0];
				var blockName = "m" + menuColumn + "RadioBlockName";
				var blockList =  "m" + menuColumn + "RadioBlockList";
				fetch(blockName).innerHTML = "";
				fetch(blockList).innerHTML = "";
			}
		}
		
		function checkAndHideResults() {
			var refDataPane = fetch("compareDisplayPane");
			if(refDataPane.style.visibility == "visible") {
				//alert("checkAndHideResults");
				refDataPane.innerHTML = "";
				refDataPane.style.visibility = "hidden";
				
				
				
				
				//loop through the columns; if one is selected, restore its
				//radio list (if it has a radio list), and if it has an
				//appended "clear" div, get rid of it:
				for(var i = 0; i < StateMonitor.getNumberOfColumns(); i++) {
				
					if(StateMonitor.isColumnSelected(i + 1)) {
						var radioBlockID = "m" + (i + 1) + "RadioBlockList";
						fetch(radioBlockID).style.visibility = "visible";
						var addSelectID = "m" + (i + 1) + "CompareBlockSelect";
						var refAddSelect = fetch(addSelectID);
						if(refAddSelect != null) {
							//alert("exists in column " + (i + 1) + " with parent node id of " + refAddSelect.parentNode.id + "\n" + refAddSelect.innerHTML);
							refAddSelect.innerHTML = "";
							//get reference to parent node:
							refParent = refAddSelect.parentNode;
							if(refParent != null) {
								try {
									var discarded = refParent.removeChild(refAddSelect);
								}
								catch(e) {
									alert(e);
								}
							}
						}
						
					}
				
				}
				
			}//
			
		}
		
		function checkForTrimBasedReload(colNum, trimID) {
			//
					if(StateMonitor.getCompetitiveTabState() == selectedTrimsMonitor.ON && colNum == 1) {
						//alert("need to restock list");
						//buildCompetitiveSet(trimID);
						//call Show msg
						//invoke Ajax callback
						
						
						try {
							StateMonitor.setIsAjaxInProgress(true);
							showHideAsyncMsg(SHOW);
							makeRequest(ACTION_GET_COMP_TO_TRIM, ("trim=" + trimID), 'callBackTrimBasedReload(http_request[i].responseText)');
							
						}
						catch(e) {
							StateMonitor.setIsAjaxInProgress(false);
							alert(e);
						}
						
					}
		}
		
		function callBackTrimBasedReload(strData) {
			//eval @strData
			try {
				eval(strData);
			}
			catch(e) {
				alert(e);
			}
			//alert("data: " + strData);
			//loop through menus 2 - 4 (inclusive)
			//build out new menus for each
			for(var i = 1; i < 4; i++) {
				var toWrite = competitiveBuilder(i);
				dynamContainer = fetch("dynamContainer" + (i + 1));
				if(dynamContainer != null) {
					dynamContainer.innerHTML = toWrite;
				}
			}
			attachExtraMenuFunctionality(4);
			
			showHideAsyncMsg(HIDE);
			
			StateMonitor.setIsAjaxInProgress(false);
			setCompetitiveDefaults();
		}
		
		function retrieveTrimFromModel(modelRef, trimID) {
			var ptrTrim = null;
			var trimRef;
			for(var i=0; i < modelRef.trims.length; i++) {
				trimRef = modelRef.trims[i];
				if(trimRef.id == trimID) {
					brokeOut = true;
					break;
				}
			}
			
			if(brokeOut) {
				ptrTrim = trimRef;
			}
			
			return ptrTrim;
			
		}
		
		function getTrimPacket(trimID, key) {
			
			var shortTrimWrap = null;
			//
			if(key == null) {
				//we have no model "parent" in this case - when we get the short set of trims from AIC, based on a mitsu trim
				trimWrap = grabCompetitorsTrimWrapper(trimID);
				if(trimWrap) {
					shortTrimWrap = new shortHandTrimWrapper(trimID, trimWrap.shortName, trimWrap.img);
				}
			}
			else {
				try {
					//this is the case of the mitsu trims
					var modelWrap = aicModels[key];
					var trimRef = retrieveTrimFromModel(modelWrap, trimID);
					
					if(trimRef != null) {
						var text = modelWrap.name + "<br>" + trimRef.shortName;
						shortTrimWrap = new shortHandTrimWrapper(trimRef.id, text, trimRef.img);
					}
					
					
				}
				catch(e) {
					
				}
			}
			
			//still null?
			if(shortTrimWrap == null) {
				try {
					//this is the case of the get all competitor's models fragment call:
					var mdl = eval(key);
					if(mdl) {
						trimRef = retrieveTrimFromModel(mdl, trimID);
							
						if(trimRef != null) {
							shortTrimWrap = new shortHandTrimWrapper(trimID, trimRef.shortName, trimRef.img);
						}
					}
				}
				catch(e) {
					
				}
			}
			
			return shortTrimWrap;
			
			
		}
		
		function trimSelected(trimID, parentKey, menuColumn) {
			//alert("Selected trim *" + trimID + "* with parent key of *" + parentKey + "* from the menu in Column " + menuColumn);
			//plug parentKey into overall hashmap:
			//alert(parentKey);
			var modelWrapper;
			if(arguments.length == 4 && arguments[3] == COMPETITOR) {
				modelWrapper = eval(parentKey);
			}
			else {
				modelWrapper = aicModels[parentKey];
			}
			
			
			//construct the names of the elements to toggle on/off
				var idMenu = "menu" + menuColumn;
				var idImg = "vehicleImg" + menuColumn;
				var idRadio = "m" + menuColumn + "RadioHousing";
				var idRadioName = "m" + menuColumn + "RadioBlockName";
				var idRadioList = "m" + menuColumn + "RadioBlockList";
				//grab references:
				var refMenu = fetch(idMenu);
				var refImg = fetch(idImg);
				var refHousing = fetch(idRadio);
				var refVehName = fetch(idRadioName);
				var refVehTrimList = fetch(idRadioList);
			
				//a bit of overkill, but has to be done because of the nature of the UI:
				StateMonitor.setHaveCompareData(false);
			
			if(modelWrapper != null && parentKey != null) {
				//alert("Selected trim of " + modelWrapper.name);
				/*
				hide the select menu, display the vehicle's image in its place
				build the string of markup representing the trims list for this model
				Name, (Price), Radioset of Trims
				*/
				
				if(refMenu != null && refImg != null && refHousing != null && refVehName != null && refVehTrimList != null) {
					
					//if there's a visible result set, hide it:
					checkAndHideResults();
					//record state for the system:
					StateMonitor.trimEvent(selectedTrimsMonitor.TYPE_SELECTED, menuColumn, trimID, parentKey);
					checkForTrimBasedReload(menuColumn, trimID);
					
					//build the radios:
					var radioGroupName = "m" + menuColumn + "Radios";
					var radioBlockMarkupHdr;
					var radioBlockMarkup = "<b>SELECT TRIMS</b><br/>";
					var radioStyles = ["style='background-color:#cccccc;clear:both'", "style='background-color:#aaaaaa;clear:both'"];
					for(var i=0; i < modelWrapper.trims.length; i++) {
						var trimRef = modelWrapper.trims[i];
						
						if(trimRef.id == trimID) {
							checked = "checked";
							var radioBlockMarkupHdr;
							//need a slightly different header if we're dealing w/ a trim that comes from the 
							//all competitors selection; the following test tells us if we have such a trim:
							if(menuColumn != 1 && StateMonitor.getCompetitiveTabState() == selectedTrimsMonitor.ON) {
								radioBlockMarkupHdr = "<b>" + trimRef.shortName + "</b><br/><br/>";
							}
							else {
								radioBlockMarkupHdr = "<b>" + modelWrapper.name + "<br/>" + trimRef.shortName + "</b><br/><br/>";
							}
							
							var img = new Image();
							img.src = trimRef.img;
							refImg.innerHTML = '<img src="' + img.src + '"/>';
							
						}
						else {
							checked = "";
						}
						radioBlockMarkup += '<div ' + radioStyles[i%2] + '><div style="float:left"><input type="radio" id="' + radioGroupName + '" name="' + radioGroupName + '" value="' + trimRef.id + '" onclick="trimRadioHandler(this, \'' + parentKey + '\', \'' + menuColumn + '\')" ' + checked + ' ></div><div style="padding: 4px 0px 4px 22px;">' + trimRef.shortName + '</div></div>  ';
					}
					radioBlockMarkup += '<br/><b><a href="javascript:resetMenus(' + menuColumn + ');">SELECT NEW MODEL</a>';  //make the menu invisible:
					//turn off the menu, and turn on the image:
					refMenu.style.visibility = "hidden";
					refImg.style.visibility = "visible";
					
					refVehName.innerHTML = radioBlockMarkupHdr;
					refVehTrimList.innerHTML = radioBlockMarkup;
					// setting this container to visible will show the innerHTML we've just assigned previously
					
					
					
					refHousing.style.visibility = "visible";
					resizerForTrimColumn(resizerForTrimColumn.AT_LEAST);
					
					//make sure all of refHousing''s children are visible too
					var blockID = "m" + menuColumn + "RadioBlockName";
					var listID =  "m" + menuColumn + "RadioBlockList";
					try {
						fetch(blockID).style.visibility = "visible";
						fetch(listID).style.visibility = "visible";
					}
					catch(e) {
						
					}
				}
			}
			else {
				var trimRef = grabCompetitorsTrimWrapper(trimID);
				if(trimRef != null) {
					if(refMenu != null && refImg != null && refHousing != null && refVehName != null && refVehTrimList != null) {
							//if there's a visible result set, hide it:
							checkAndHideResults();
						//record state for the system:
						StateMonitor.trimEvent(selectedTrimsMonitor.TYPE_SELECTED, menuColumn, trimID, null);
					
						var hdr = "<b>" + trimRef.shortName + "</b><br/><br/>";
						var img = new Image();
						var endMarkup = '<b><a href="javascript:resetMenus(' + menuColumn + ');">SELECT NEW MODEL</a>';  //make the menu invisible:
						img.src = trimRef.img;
						refImg.innerHTML = '<img src="' + img.src + '"/>';
						refVehName.innerHTML = hdr;
						refVehTrimList.innerHTML  = endMarkup;
						refMenu.style.visibility = "hidden";
						refImg.style.visibility = "visible";
						refHousing.style.visibility = "visible";
						resizerForTrimColumn(resizerForTrimColumn.AT_LEAST);
						//make sure all of refHousing''s children are visible too
						var blockID = "m" + menuColumn + "RadioBlockName";
						var listID =  "m" + menuColumn + "RadioBlockList";
						try {
							fetch(blockID).style.visibility = "visible";
							fetch(listID).style.visibility = "visible";
						}
						catch(e) {
							
						}
					}//
				}
			}
		}
		
		function resizerForTrimColumn(typeOfResize) {
			var cols = StateMonitor.getNumberOfColumns();
			var heightBenchmark = 0;
			//loop through to get the greatest height of the currently selected columns:
			for(var i = 0; i < cols; i++) {
				var id = "m" + (i + 1) + "RadioBlockList";
				if(StateMonitor.isColumnSelected(i + 1)) {
					var elemHeight = fetch(id).offsetHeight;
					heightBenchmark = elemHeight > heightBenchmark ? elemHeight : heightBenchmark;
				}
			}
			
			var xtra = arguments.length == 2 ?  600: 420;
			//alert(xtra);
			
			switch(typeOfResize) {
				case resizerForTrimColumn.AT_LEAST:
					//alert("at least : " + parseInt(fetch("individual_vehicle_content").style.height) + " " + (heightBenchmark + fetch("m1RadioBlockList").offsetTop + xtra));
					
					//if(parseInt(fetch("individual_vehicle_content").style.height) < (heightBenchmark + fetch("m1RadioBlockList").offsetTop + xtra)) {
						if ((heightBenchmark + fetch("m1RadioBlockList").offsetTop + xtra) > 1000) {
							fetch("individual_vehicle_content").style.height = (heightBenchmark + fetch("m1RadioBlockList").offsetTop + xtra) + "px";
						} else {
							fetch("individual_vehicle_content").style.height = "1000px";
						}
						if ((heightBenchmark + fetch("m1RadioBlockList").offsetTop + 45) > 600) {
							fetch("legalCopy").style.top = (heightBenchmark + fetch("m1RadioBlockList").offsetTop + 45) + "px";
						} else {
							fetch("legalCopy").style.top = "600px";
						}
						
					//}
					
					//fetch("individual_vehicle_content").style.height = "1000px";
					//fetch("legalCopy").style.top = "600px";
					//alert("after: " + fetch("individual_vehicle_content").style.height);
				break;
			
			  case resizerForTrimColumn.NO_MORE_THAN:
				//alert("no more " + parseInt(fetch("individual_vehicle_content").style.height) + " " + (heightBenchmark + fetch("m1RadioBlockList").offsetTop + xtra));
					fetch("individual_vehicle_content").style.height = (heightBenchmark + fetch("m1RadioBlockList").offsetTop + xtra) + "px";
					//alert("after: " + fetch("individual_vehicle_content").style.height);
				break;
			}
			
			
			
			
		}
		
		resizerForTrimColumn.AT_LEAST = "at-least";
		resizerForTrimColumn.NO_MORE_THAN = "no-more-than";
		
		function retrieveCompetitorFragment(menuID, retrievalType) {
			//grab the reference to the menu object associated with this ID:
			var menuRef = menuMirrors[menuID];
			if(menuRef != null) {
				//get a reference to the wrapper that monitors state of the competitors menu:
				
				
				var strCallback = "callbackRetrieveFragment(http_request[i].responseText, " + menuRef.columnNumber + ")";
				var previousFirst;
				var previousLast;
				var query;
				
				//need to get the trim wrapper associated with the selected mitsubishi vehicle
				var trimRef = null;
				if(StateMonitor.isColumnSelected(1)) {
					//get the columnWrapper:
					var columnWrap = StateMonitor.getDataWrapperForColumn(1);
					if(columnWrap) {
						var parentKey = columnWrap.parentID;
						if(parentKey != null && parentKey != "") {
							//get the model based on this key:
							var modelRef = null;
							try {
								modelRef = aicModels[parentKey];
							}
							catch(e) {}
							if(modelRef) {
								//finally, get the trimRef:
								trimRef = retrieveTrimFromModel(modelRef, columnWrap.trimID);
								//alert(modelRef.id  + " " + columnWrap.parentID + " " + trimRef.shortName);
							}
						}
					}
				}
				
				switch(retrievalType) {
					case dynamicMenu.FIRST:
						//alert(menuRef.columnNumber);
						menuRef.setCompetitorFirstIndex(1);
						
						menuRef.setCompetitorLastIndex(AIC_BATCH_NUMBER);
						
						var query = "startPos=" + menuRef.getCompetitorFirstIndex() + "&asc=true&batch=" + menuRef.getCompetitorLastIndex();
						if(trimRef) {
							query += "&year=" + trimRef.year;
						}
						//alert(query);
						showHideAsyncMsg(SHOW, MSG_WORKING);
						makeRequest(ACTION_GET_ALL_TRIMS, query, strCallback);
						
					break;
					case dynamicMenu.NEXT:
						//alert(menuRef.columnNumber);
						previousFirst = menuRef.getCompetitorFirstIndex();
						previousLast = menuRef.getCompetitorLastIndex();
						//alert("Before assignment: " + previousFirst);
						menuRef.setCompetitorFirstIndex(previousFirst + AIC_BATCH_NUMBER);
						//alert("AFter assignment: " + menuRef.getCompetitorFirstIndex());
						menuRef.setCompetitorLastIndex(previousLast + AIC_BATCH_NUMBER);
						query = "startPos=" + menuRef.getCompetitorFirstIndex() + "&asc=true&batch=" + AIC_BATCH_NUMBER;
						if(trimRef) {
							query += "&year=" + trimRef.year;
						}
						showHideAsyncMsg(SHOW, MSG_WORKING);
						makeRequest(ACTION_GET_ALL_TRIMS, query, strCallback);
						
					break;
					case dynamicMenu.PREVIOUS:
						previousFirst = menuRef.getCompetitorFirstIndex();
						previousLast = menuRef.getCompetitorLastIndex();
						menuRef.setCompetitorFirstIndex(previousFirst - AIC_BATCH_NUMBER);
						menuRef.setCompetitorLastIndex(previousLast - AIC_BATCH_NUMBER);
						query = "startPos=" + menuRef.getCompetitorFirstIndex() + "&asc=true&batch=" + AIC_BATCH_NUMBER;
						if(trimRef) {
							query += "&year=" + trimRef.year;
						}
						//alert(query);
						showHideAsyncMsg(SHOW, MSG_WORKING);
						makeRequest(ACTION_GET_ALL_TRIMS, query, strCallback);
						
					break;
				}
			}
		}
		
		function callbackRetrieveFragment(strData, menuCol) {
			try {
				eval(strData);
			}
			catch(e) {
				alert(e);
			}
			
			//overload the function call with the the competitor wrapper
			//associated with the current menu:
			var menuID = "menu" + menuCol;
			var competitorMenuWrap = menuMirrors[menuID].allCompetitorsState;
			
			var markup = constructCompetitorsMenuSystems(1, (menuCol - 1), competitorMenuWrap);
			var containerID = "dynamContainer" + menuCol;
			
			var dynamContainer = fetch(containerID);
			if(dynamContainer != null) {
				dynamContainer.innerHTML = markup;
			}
			attachExtraMenuFunctionality(menuCol);
			showHideAsyncMsg(HIDE);
			competitorMenuWrap.isVisible = true;
			
			showMenu(fetch(menuID), menuID);
		}
		
		function grabCompetitorsTrimWrapper(id) {
			var wrapper = null;
			if(compVehicles != null) {
				for(var i = 0; i < compVehicles.length; i++) {
					var ref = compVehicles[i];
					if(ref.id == id) {
						wrapper = ref;
						break;
					}
				}
			}
			
			return wrapper;
		}
		
		function initiateCompare(obj) {
			if(StateMonitor.numberSelected < 2) {
				//TBD
				alert("Select at least 2 vehicles");
			}
			else if(StateMonitor.getCompetitiveTabState() == "on" && !StateMonitor.isColumnSelected(1)) {
				alert("A mitsubishi vehicle must be selected from the first menu in order to make a comparison");
			}
			else {
				//call to StateMonitor
				
				var normalized = StateMonitor.getNormalizedSelections();
				if(normalized.length < 2) {
					alert("Select at least 2 DIFFERENT vehicles");
				}
				else {
					//build up the query string:
					var query = "compTrims=";
					for(var i = 0; i < normalized.length; i++) {
						query += (i == (normalized.length - 1)) ? normalized[i] : normalized[i] + "|";
					}
					
				 prepareElementsForCompare();
				//invoke AJAX async
				query += "&hippo=" + new Date().getTime().toString();
				showHideAsyncMsg(SHOW, MSG_WORKING);
				makePOSTRequest(ACTION_GET_COMPARISON, query, 'displayComparison(http_request[i].responseText)');
				//alert(ACTION_GET_COMPARISON + query);
					
				}
				
			}
		}
		
		function prepareElementsForCompare() {
			
			//hide all of the radio-button data:
			for(var i = 0; i < StateMonitor.getNumberOfColumns(); i++) {
				
				if(StateMonitor.isColumnSelected(i + 1)) {
					//alert("column " + (i + 1) + " is selected");
					//construct the name of the radio display block
					//of the form m1RadioBlockList"
					var name = "m" + (i + 1) + "RadioBlockList";
					hideElement(name);
					
					//add the message to clear the selection:
					var blockID = "m" + (i + 1) + "RadioBlockName";
					var blockRef = fetch(blockID);
					var markup = blockRef.innerHTML;
					
					var newID = "m" + (i + 1) + "CompareBlockSelect";
					
					//does the newID already exist?
					var refNew = fetch(newID);
				
					if(refNew == null) {
						markup += "<div id=\"" + newID + "\">";
						markup += '<b><a href="javascript:resetMenus(' + (i + 1) + '); checkAndHideResults();">SELECT NEW MODEL</a>';
						markup += "</div>";
						blockRef.innerHTML = markup;
					}
					
				}
			}
			
			
			
			
		}
		
		function hideElement(elemID) {
			var elemRef = fetch(elemID);
			if(elemRef != null) {
				elemRef.style.visibility = "hidden";
			}
		}
		
		//called asynchronously via "AJAX"
		function displayComparison(strCompareStructure) {
			try {
				eval(strCompareStructure);
			}
			catch(e) {
				var errMarkup = COMPARE_ERROR_MARKUP;
				var resizePane = false;
				displayEncapsulation(errMarkup, resizePane);
				return;
			}
			
			var exceptionTest = false; //mockup for catch block above
			
			if(exceptionTest) {
				var errMarkup = COMPARE_ERROR_MARKUP;
				var resizePane = false;
				displayEncapsulation(errMarkup, resizePane);
				return;
			}
			
			//firstly, loop through the short list of trims which are being compared; determine and set the column:
			var comparedTrims = new Array();
			var compareMarkup;
			var resize = true;
			if(compareData.length > 0) {
				for(var i = 0; i < compareModels.length; i++) {
					var trimRef = compareModels[i];
					trimRef.columnNumber = StateMonitor.getColumnforID(trimRef.id);
					comparedTrims.push(trimRef);
					//alert(trimRef.id + ": column:" + trimRef.columnNumber);
				}
				var numberOfColumns = 5;
				var competitorSpecificMarkup = (StateMonitor.getCompetitiveTabState() == "on") ? "<img src=\"/MMNA/images/compare/icon_light.gif\"/>&nbsp; = Mitsubishi Advantage" : "&nbsp;";
				compareMarkup = "<table width=\"959\" border=\"0\" cellpadding=\"4\" cellspacing=\"0\">";
				compareMarkup += "<tr><td width=\"192\">" + competitorSpecificMarkup + "</td><td width=\"180\">&nbsp;</td><td width=\"175\">&nbsp;</td><td width=\"175\">&nbsp;</td><td width=\"237\">&nbsp;</td></tr>";
				
				for(var i = 0; i < compareData.length; i++) { //number of categories
					var refCompare = compareData[i];
					//get the compare's id, and retrieve its display column
					//get the sectional header:
					//compareMarkup += ' <div style="color:#cccccc; background-color:#000000; font-size:11px; font-weight:bold;">' + refCompare.header + '</div><br/>';
					compareMarkup += "<tr><td style=\"color:#cccccc; background-color:#000000; font-size:11px; font-weight:bold;\" colspan=\"" + numberOfColumns + "\">" + refCompare.header + "</td></tr>";
					
					//now for the details - discrete sections and values - for this section:
					var left;
					var refCoordinates;
					var styles = ["#cccccc", "#aaaaaa"];
					var advantage = ["/MMNA/images/compare/icon_light.gif", "/MMNA/images/compare/icon_dark.gif"]
					for(var j = 0; j < refCompare.details.length; j++) { //subheads within categories
						//get ref to detail object
						refCoordinates = SpaceManager.fetchCoordinates(1);
						left = refCoordinates.x;
						var refDetail = refCompare.details[j];
						//compareMarkup += ' <div style="position:absolute">';
						//compareMarkup += ' <div style="font-size:9px; font-weight:bold; position: top: 0px; absolute: ' + left + 'px; background-color:' + styles[j%2] +';">' + refDetail.label + '</div>';
						//advantageFlag
						compareMarkup += "<tr><td style=\"background-color:" + styles[j%2] + "; font-size:9px; font-weight:bold;\">" + refDetail.label;
						//is there a mitsu advantage here?
						compareMarkup += (StateMonitor.getCompetitiveTabState() == "on" && refDetail.getAdvantageFlag() == true) ? "&nbsp;<img src=\"" + advantage[j%2] + "\"/></td>" : "</td>";
						//populate values in columns:
						var lastWritten = 0;
						for(var jj = 0; jj < numberOfColumns - 1; jj++) { //individual data
							if (StateMonitor.isColumnSelected(jj + 1)) {
								//get the value to display:
								var val = refDetail.values[lastWritten];              
								lastWritten++;
								//get the coordinates object 
								//refCoordinates = SpaceManager.fetchCoordinates(comparedTrims[jj].columnNumber);
								//left = refCoordinates.x;
								//compareMarkup += ' <div> ';
								//compareMarkup += '<div style="border: red solid 0px; width:120px; font-size:9px; top: 0px; position:absolute; left: ' + left + 'px;">' + val + '</div>';
								//compareMarkup += ' </div>';
								compareMarkup += "<td style=\"background-color:" + styles[j%2] + "; font-size:9px;\">" + val + "</td>";
							} else {
								compareMarkup += "<td style=\"background-color:" + styles[j%2] + ";\">&nbsp;</td>";
							}
						}
						//compareMarkup += '</div><br/><br/>';
						compareMarkup += "</tr>";
					}
				}
				compareMarkup += "</table>";
				StateMonitor.setHaveCompareData(true);
			}
			else {
				compareMarkup = COMPARE_ERROR_MARKUP;
				resize = false;
			}
			displayEncapsulation(compareMarkup, resize);
		}
		
		function displayEncapsulation(displayMarkup, resize) {
			var refDataPane = fetch("compareDisplayPane");
			refDataPane.innerHTML = displayMarkup;
			
			if(resize) {
				resizeAncestor("compareDisplayPane", 4, (refDataPane.offsetTop + refDataPane.parentNode.offsetTop + 205));
			}
			refDataPane.style.visibility = "visible";
			var legalHeight = refDataPane.offsetHeight + 100;
			fetch("legalCopy").style.top = legalHeight + "px";
			showHideAsyncMsg(HIDE);
			
			
			StateMonitor.setIsAjaxInProgress(false);
		}
		
		function getHvrObject(obj) {
			//if the immediate child of @obj is a <div>, use that; otherwise, get the first child's first child, which WILL be a div
			toUse = obj.childNodes[0].nodeName == "DIV" ? obj.childNodes[0] : obj.childNodes[0].childNodes[0];
			
			return toUse;
		}
		
		function hvrPackage(originalObj, txtColorObj) {
			this.originalObject = originalObj;
			this.textColorObject =  txtColorObj;
		}
		
		function copyArray(arrToCopy) {
			var copied = new Array();
			for(var i = 0; i < arrToCopy.length; i++) {
				copied[i] = arrToCopy[i];
			}
			
			return copied;
		}
		
		function hvr(obj) {
			//fetch("feedback").value = obj.id + " hovers' length: " +  hovers.length;
			var txtColorObj = getHvrObject(obj);
			
			//we set @obj's background color to "on" and one of its descendants color:
			obj.style.backgroundColor = "#5c5c5c";
			txtColorObj.style.color = "#ffffff";
			
			//set to the "off" state whatever elements are currently selected that no longer should be:
			var hoverCopy = copyArray(hovers);
			
			//fetch("feedback").value = "Copy's length: " + hoverCopy.length + "; hovers' length: " +  hovers.length;
			for(var i = 0; i < hoverCopy.length; i++) {
				var packageRef = hoverCopy[i];
				//we determine "ancestry" - the need to leave an object activated
				//by whether or not the currently hovered over object shares a "namespace"
				//with another object; all objects are named according to a pattern, which exhibits hierarchy
				//alert(i + " current id: *" + currBgndObj.id + "* hovers Object id: *" + packageRef.backgroundColorObject.id + "*");
				if(obj.id.indexOf(packageRef.originalObject.id) == -1) {
					packageRef.originalObject.style.backgroundColor = "#f7f7f9";
					packageRef.textColorObject.style.color = "#333333";
					
					//remove this array-element, since it's been turned off:
					hovers.splice(i, 1);
					
					
				}
				else if(obj.id == packageRef.originalObject.id) {
					//remove this array-element, since it's been turned off:
					hovers.splice(i, 1);
				}
			}
			
			//build the wrapper package for @obj and push it onto the hovers stack:
			//alert("about to push; hovers' length: " + hovers.length);
			hovers.push(new hvrPackage(obj, txtColorObj));
			
				
		}
		
		
		/* Data structures */
		
		function rollOvertracker() {
			var latest = new Array(); //an array of one element
			
			this.clearAndRegister = function(obj, key) {
				
				//create a wrapper based on this element
				var latestElem = new trackerElement(obj, key);
				
				if(latest.length == 1) {
					//get a reference to the last element:
					var last = latest[0];
					//is this a different element than the previous?
					if(last.objectReference.id != latestElem.objectReference.id) {
						//grab the imagewrapper associated with last:
						var wrap = ImageMapper.get(last.key);
						if(wrap != null) {
							last.objectReference.style.backgroundImage = "url(" + wrap.src + ")";
						}
						last = null;				
						//make latest the new 'last'
						latest[0] = null;
						latest[0] = latestElem;
						//fetch("feedback").value = "Overwriting to make this the 'latest': " + latest[0].key;
					}
				}
				else {
					latest[0] = latestElem;
					//fetch("feedback").value = "Making this the 'latest': " + latest[0].key;
				}
				
			};
			
			this.getLatestInfo = function() {
				if(latest.length == 1) {
					var latestElem = latest[0];
					alert("Latest rollover: Element of id *" + latestElem.objectReference.id + "* - KEY: " + latestElem.key);
				}
				else {
					alert("No latest yet");
				}
			};
		}
		
		function trackerElement(obj, key) {
			this.objectReference = obj;
			this.key = key;
		}
		
		function aicToMitsuMapper() {
			var self = this;
			var map = new Object();
			var counter = 0;
			
			this.getNumberOfVehicles = function() {
				return counter;
			};
			
			this.add = function(name, img, overImg) {
				map[name.toLowerCase()] = new simpleImageWrapper(img, overImg);
				counter++;
			};
			
			this.get = function(name) {
				var lwrKey = name.toLowerCase();
				if(map[lwrKey] != null) {
				 return map[lwrKey];
				}
				else {
					return null;
				}
			};
		}
		
		function simpleImageWrapper(normalImg, overImg) {
		
			
			this.src = normalImg;
			this.mouseoverSrc = overImg;
			//create image Objects to preload the images:
			var temp = new Image();
			temp.src = normalImg;
			var temp2 = new Image();
			temp2.src = overImg;
		}
		
		
		
		function coordinatesHolder(numOfColumns) {
			var self = this;
			
			this.coordinates = new Array();
			for(var i = 0; i < numOfColumns; i++) {
				this.coordinates[i] = new coordinate(null, null);
			}
			
			this.fetchCoordinates = function(column) {
				if(column <= self.coordinates.length && column >= 1) {
					return self.coordinates[column - 1];
				}
			};
		}
		
		function coordinate(x, y) {
			this.x = x;
			this.y = y;
		}
		
		function selectedTrimsMonitor(numOfColumns) {
			var self = this;
			
			var compTabOnState = selectedTrimsMonitor.OFF;
			var ajaxInProgress = false;
			
			var haveCompareData = false;
			var haveCompareCallbacks = new Array();
			var noCompareCallbacks = new Array();
			
			this.numberSelected = 0;
			this.columnPointers = new Array(); //will contain trimColumn objects
			
			for(var i=0; i < numOfColumns; i++) {
				this.columnPointers[i] = new trimColumn(i + 1);
			}
			
			this.getDataWrapperForColumn = function(colNum) {
				var ptr = null;
				if(!colNum < 1 && !(colNum > self.columnPointers.length)) {
					ptr = self.columnPointers[colNum - 1];
				}
				
				return ptr;
			};
			
			this.registerDataCallback = function(type, func) {
				switch(type) {
					case selectedTrimsMonitor.COMPARE_DATA:
						haveCompareCallbacks.push(func);
					break;
					
					case selectedTrimsMonitor.NO_COMPARE_DATA:
						noCompareCallbacks.push(func);
					break;
				}
			};
			
			function fireCallbacks(type) {
				var arrRef;
				switch(type) {
					case selectedTrimsMonitor.COMPARE_DATA:
						arrRef = haveCompareCallbacks;
					break;
					
					case selectedTrimsMonitor.NO_COMPARE_DATA:
						arrRef = noCompareCallbacks;
					break;
				}
				
				for(var i = 0; i < arrRef.length; i++) {
					var func = arrRef[i];
					func();
				}
			}
			
			this.setHaveCompareData = function(val) {
				
				if(val) {
					fireCallbacks(selectedTrimsMonitor.COMPARE_DATA);
				}
				else {
					//only fire the callback if the value has just changed, for efficiency's sake:
					if(val != self.getHaveCompareData()) {
						fireCallbacks(selectedTrimsMonitor.NO_COMPARE_DATA);
					}
					
				}
				haveCompareData = val;
			};
			
			this.getHaveCompareData = function() {
				return haveCompareData;
			};
			
			this.setIsAjaxInProgress = function(val) {
				ajaxInProgress = val;
			};
			
			this.getIsAjaxInProgress = function() {
				return ajaxInProgress;
			};
			
			this.setCompetitiveTabState = function(val) {
				if(val == selectedTrimsMonitor.OFF || val == selectedTrimsMonitor.ON) {
					compTabOnState = val;
				}
				else {
					alert("Error: selectedTrimsMonitor.setCompetitiveTabState ... illegal argument");
				}
			};
			
			this.getCompetitiveTabState = function() {
				return compTabOnState;
			};
			
			this.getNumberOfColumns = function() {
				return self.columnPointers.length;
			};
			
			this.isColumnSelected = function(id) {
				/*
				 @id is assumed to >= 1
				*/
				var selected = false;
				
				if(i >= 1 && i <= self.columnPointers.length) { 
					
					var colRef = self.columnPointers[id - 1];
					selected = colRef.selected;
				}
				
				return selected;
			};
			
			this.getColumnforID = function(id) {
				var column = null;
				for(var i = 0; i < self.columnPointers.length; i++) {
					 
					var colRef = self.columnPointers[i];
					//alert("passed in: " + id + " this iteration" + colRef.trimID);
					if(colRef.trimID == id) {
						column = colRef.columnNumber;
						break;
					}
				}
				
				return column;
			};
			
			this.report = function() {
				var reportBody = "Competitive Tab State: " + this.getCompetitiveTabState() + "\n";
				for(var i = 0; i < self.columnPointers.length; i++) {
					var colRef = self.columnPointers[i];
					if(colRef.selected) {
						reportBody += "Column " + colRef.columnNumber + ": selected\n";
						reportBody += "Trim ID " + colRef.trimID + "\n";
						reportBody += "Parent ID " + colRef.parentID + "\n"; 
					}
					else {
						reportBody += "Column " + colRef.columnNumber + ": NOT selected\n";
					}
					
				
				}
				alert(reportBody);
			}
			
			this.clear = function() {
				for(var i = 0; i < self.columnPointers.length; i++) {
					var colRef = self.columnPointers[i];
					if(colRef.selected) {
						colRef.selected = false;
					}
				}
			}
			
			//helper function for  internal consumption only:
			function markDuplicates(arr) {
			
			 var a = [];
			 var l = arr.length;
			 for( i = 0; i < arr.length; i++ ) {
			 	if( a.toString().indexOf( arr[i], 0) < 0 ) {
					a.push( arr[i] ); 
				}
				else {
					//reset duplicate columns here:
					resetMenus(i + 1);
					
				}
			 }
			 
			 return a;
			}
			
			this.getNormalizedSelections = function() {
				var uniqueSet;
				
				ids = new Array();
				for(var i = 0; i < self.columnPointers.length; i++) {
					var refTrimColumn = self.columnPointers[i];
					if(refTrimColumn.selected) {
						ids.push(refTrimColumn.trimID);
					}
				}
				uniqueSet = markDuplicates(ids);
				return uniqueSet;
			};
			
			this.trimEvent = function(type, colNum, newID, pID) {
			 /* 
			 @newID is functionally optional; is only meaningfully passed in when
			 @type equals  selectedTrimsMonitor.TYPE_SELECTED
			 */
			 
				var colRef = self.columnPointers[colNum - 1]; //remember, array is zero-indexed
				if(type == selectedTrimsMonitor.TYPE_SELECTED) {
					//alert("selected");
					//get the associated trimColumn
					
					
					if(!colRef.selected) {
						colRef.selected = true;
						self.numberSelected ++;
					}
					colRef.trimID = newID;
					colRef.parentID = pID;
					
				}
				else if(selectedTrimsMonitor.TYPE_CLEARED) {
					//alert("cleared");
					colRef.selected = false;
					self.numberSelected --;
				}
			};
		} // end of selectedTrimsMonitor constructor
		
		selectedTrimsMonitor.TYPE_SELECTED = "selected";
		selectedTrimsMonitor.TYPE_CLEARED = "cleared";
		selectedTrimsMonitor.ON = "on";
		selectedTrimsMonitor.OFF = "off";
		selectedTrimsMonitor.COMPARE_DATA = "compare-data";
		selectedTrimsMonitor.NO_COMPARE_DATA = "no-compare-data";
		
		function trimColumn(id) {
			this.columnNumber = id;
			this.trimID;
			this.parentID;
			this.selected = false;
		}
		
		
		function compareObject(header, arrCompareDetailObject) {
				this.header = header;
				this.details = arrCompareDetailObject; //an array of compareDetailObjects
			}
			
		function compareDetailObject(label, arrValues) {
			var self = this;
			this.label = label;
			this.values = arrValues; //an array of string values
			this.advantageFlag = (arguments.length == 3) ? arguments[2] : false;
			
			this.getAdvantageFlag = function() {
				return self.advantageFlag;
			};
		}
		
		function aicMake(makeName, arrModelKeys) {
			this.name = makeName;
			this.models = arrModelKeys; //an array of aicModel objects
		}
		
		function shortHandTrimWrapper(id, displayText, img) {
			this.id = id;
			this.text = displayText;
			this.img = img;
		}
		
		function aicModel(id, name, defaultImageUrl, arrTrims) {
			//alert(id + " " + name + " " + defaultImageUrl + " " + arrTrims.length);
			this.id = id;
			this.name = name;
			this.defaultImg = defaultImageUrl;
			this.trims = arrTrims;
		}
		
		function trimWrapper(id, shortName, imgUrl, year, parentID) {
			this.id = id;
			this.shortName = shortName;
			this.img = imgUrl;
			this.year = year;
			this.parentID = parentID;
			this.currentColumn = null; //a convenience field which can be added/accessed later
			this.make = (arguments.length == 6) ? arguments[5] : null;
		}
		
		function dynamicMenuMirror(id) {
			var self = this;
			this.id = id;
			this.columnNumber = parseInt(id.substring(4)); // id will always be "menu_" (with "_" = to an integer - 1, 2, 3)
			
			this.allCompetitorsState = new allCompetitorMenuState();
				
				this.setCompetitorFirstIndex = function(val) {
					self.allCompetitorsState.firstItemIndex = val;
					//alert(self.id + " setting competitorFirst to " + self.allCompetitorsState.firstItemIndex);
				};
				
				this.getCompetitorFirstIndex = function(val) {
					//alert(self.id + " returning competitorFirst " + self.allCompetitorsState.firstItemIndex);
					return 	self.allCompetitorsState.firstItemIndex;
				};
				
				this.setCompetitorLastIndex = function(val) {
					self.allCompetitorsState.lastItemIndex = val;
					//alert(self.id + " setting competitorLast to " + self.allCompetitorsState.lastItemIndex);
				};
				
				this.getCompetitorLastIndex = function(val) {
					//alert(self.id + " returning competitorLast " + self.allCompetitorsState.lastItemIndex);
					return 	self.allCompetitorsState.lastItemIndex;
				};
		}
		
		function allCompetitorMenuState() {
			this.isVisible = false;
			this.firstItemIndex = 0;
			this.lastItemIndex = 0;
		}
		
		function dynamicMenu(id, timerMS) {
				var self = this;
				this.id = id; //corresponds to a top-level Div
				this.columnNumber = parseInt(id.substring(4)); // id will always be "menu_" (with "_" = to an integer - 1, 2, 3)
				this.components = new Object(); //hashmap - acts as a flat collection of the menu-item/sub-menu mappings
				this.timerID = null;
				this.timerOn = false;
				this.timerTicksInMS = timerMS;
				
				
			}
			
		dynamicMenu.FIRST = "first";
		dynamicMenu.NEXT = "next";
		dynamicMenu.PREVIOUS = "previous";
		
		
			
			//data structure for an element - in effect, a row - in a subMenu
			function element(id, text, arrClickFuncArgs) {
				this.id = id;
				this.text = text;
				this.clickFunctionParams = arrClickFuncArgs; //array
			}
			
		/*  Construction functions */
			
		//function which builds a sub-menu
		function buildSubMenu(topLvlID, id, arrElements) {
				var extraTopLvlStyle = (arguments.length == 4 && arguments[3] == AIC_ALL_COMP_FRAG) ? "width:225px; overflow:hidden; height:" + MENU_HEIGHT + "px;" : "";
				var divStructure = '';
				divStructure += '<div id="' + id + '" class="menuContainer" ' + extraTopLvlStyle;
				divStructure += " onmouseover='clearTimedOutHide(\"" + topLvlID + "\");' ";
				divStructure += " onmouseout='timeoutHideSubMenus(\"" + topLvlID + "\");' ";
				divStructure += ' style="' + extraTopLvlStyle + 'z-index:99; position:absolute; top:0px; left:0px; visibility:hidden;">';
				if(arguments.length == 5 && arguments[3] == AIC_ALL_COMP_FRAG) {
						//get a reference to the competitive menu wrapper:
						wrap = arguments[4];
						if(wrap.firstItemIndex != 1) {
							divStructure += "<div class=\"menuItem\"><a href=\"javascript:retrieveCompetitorFragment('" + topLvlID + "', dynamicMenu.PREVIOUS);\">" + "<< Previous Makes" + "</a></div>";
						}
					}
				for(var i=0; i < arrElements.length; i++) {
					var refElement = arrElements[i];
					var imageWrap = ImageMapper.get(refElement.text);
					var borderStyle;
					if(imageWrap != null) {
						borderStyle = i == 0 ? "" : "";
					}
					else {
						if(i == arrElements.length - 1) {
							borderStyle = "border-bottom: black solid 1px";
						}
					}
					
					//overloaded with *5* arguments in the competitive fragment - "all competitors" - case:
					var wrap;
					
					borderStyle += (arguments.length == 4 && arguments[3] == AIC_ALL_COMP_FRAG) ? "; width:205px; _width:225px; " : "";
					divStructure += '<div id="' + refElement.id + '" class="menuItem" style="z-index:99;' + borderStyle;
					
					var contentStyle = "";
					var xtraMouseover = "";
					var xtraMouseout = "";
					var firstMouseover = "clearTimedOutHide('" + topLvlID + "');";
					var txtStyleMousover = "this.style.cursor='pointer'";
					var txtStyleMouseout = "";
					if(imageWrap != null) {
						//background image:
						divStructure += ' background-image:url(' + imageWrap.src + ');';
						//a bit heavy-handed, but we have to change the width of the display below to accomodate this image, so
						//we need to set a variable value here:
						contentStyle = "style='width:60px; height:32px;'";
						xtraMouseover = " RollOverTracker.clearAndRegister(this, '" + refElement.text + "' ); this.style.backgroundImage = 'url(" + imageWrap.mouseoverSrc + ")'; ";
						xtraMouseout  = "  ";
						//this.style.backgroundImage = \"url(" + imageWrap.src + ")\";
						
					}
					else {
						//some special markup for the non-mitsu-menus:
						xtraMouseover = " hvr(this); ";
						txtStyleMousover = "this.style.cursor='pointer'";
						txtStyleMouseout = "";
					}
					
					divStructure += '"';
					divStructure += " onmouseover=\"" + firstMouseover + xtraMouseover + "hideLastSub(this); showMenu(this,'" + topLvlID + "');\"";
					divStructure += " onmouseout='" + xtraMouseout + "'>";       
					if(refElement.clickFunctionParams) {
						
						var paramList = "";
						
						for(var j=0; j < refElement.clickFunctionParams.length; j++) {
							paramList += "'" + refElement.clickFunctionParams[j] + "'";
							if(j != refElement.clickFunctionParams.length - 1) {
								paramList += ",";
							}
						}
						
						//divStructure += '<a href="javascript:hideAllNowAsync(\'' + topLvlID + '\'); trimSelected(' + paramList + ');">';
						
					}
					
					var uniqueDivSize = "style='padding-left: 10px; padding-right: 10px; height: 32px; width: 66px; _width:86px;'";
					if (imageWrap == null) {
						//Trim Div
						uniqueDivSize = "style='padding-left: 10px; padding-right: 10px; width: 120px; _width:140px;'";
						divStructure += "<div " + uniqueDivSize + " onclick=\"javascript:hideAllNowAsync('" + topLvlID + "'); trimSelected(" + paramList + ");\" onmouseover=\"" + txtStyleMousover + "\" onmouseout=\"" + txtStyleMouseout + "\" " + contentStyle + " >" + refElement.text + "</div>";
					} else {
						//Mitsu Model Div
						divStructure += "<div " + uniqueDivSize + " onmouseover=\"" + txtStyleMousover + "\" onmouseout=\"" + txtStyleMouseout + "\" " + contentStyle + " >" + refElement.text + "</div>";
					}
					
					//do we need to close an anchor?
					
					if(refElement.clickFunctionParams) {
						//divStructure += "</a>";
					}
					
					divStructure += '</div>';
					
				}
				//function is overloaded in the case of an AIC-preselected-trim-list:
				if(arguments.length == 4 && arguments[3] == AIC_COMP_TRIMS) {
					//Commented out for temp AIC deploy
					//divStructure += "<div class=\"menuItem\" style=\"border-top: 0px; border-bottom: black solid 1px;\"><a href=\"javascript:retrieveCompetitorFragment('" + topLvlID + "', dynamicMenu.FIRST);\">" + "See all Makes" + "</a></div>";
				}
				else if(arguments.length == 5 && arguments[3] == AIC_ALL_COMP_FRAG && hasMore) {
						//get a reference to the competitive menu wrapper:
						wrap = arguments[4];
						divStructure += "<div class=\"menuItem\" style=\"border-top: 0px; border-bottom: black solid 1px;\"><a href=\"javascript:retrieveCompetitorFragment('" + topLvlID + "', dynamicMenu.NEXT);\">" + "Next Makes >>" + "</a></div>";
				}
				divStructure += '</div>';
				//document.write(divStructure);
				//alert(divStructure);
				return divStructure;
			}
		
			function constructAicKey(id) {
				var PREFIX = "aicModel";
				var SUFFIX = "key";
				
				return PREFIX + id + SUFFIX;
			}
		
		function attachExtraMenuFunctionality(numOfSubs) {
			//attach a custom event-handler to the sub:
			for(var i = 1; i <= numOfSubs; i ++) {
				var menuID = "menu" + i;
				var subID = menuID + "Sub";
				var refCurrSub = fetch(subID);
					//alert("hi " + refCurrSub);
					if(refCurrSub != null) {
						refCurrSub.onhidden = function() {
							//alert("Hi Bobo");
							//parse the id to get the id of the "owner" menu object:
							var id = this.id;
							var menuName = id.substring(0, id.indexOf("Sub"));
							//retrieve the image associated with this menu:
							var img = null;
							try {
								img = fetch(menuName).childNodes[0];
							}
							catch(e) {
								alert(e);
							}
							if(img != null) {
								//retrieve the image, via the mapper
								var wrapper = ImageMapper.get(menuName);
								if(wrapper != null) {
									img.src = wrapper.src;
								}
							}
						};
						
						//add a mapping for this menu - this can piggyback on top of the primary usage of the mapper::
						ImageMapper.add(menuID, "/MMNA/images/compare/compare_SelectVehicle_arrowright.gif", "/MMNA/images/compare/compare_SelectVehicle_arrowdown.gif");
			
						
					}
				}
		}
			
		
		
		function constructTrimBasedCompetitiveSet(numberOfMenus, startingIndex) {
			var SUB = "Sub";
			var ELEM = "Elem";
			var CURRENT_MENU_ID = "menu";
			var NUM_OF_MENUS = numberOfMenus;
			
			var menuMarkup = "";
			for(var ii= 0; ii < NUM_OF_MENUS; ii++) {
				var subsArray = eval("Menu" + (startingIndex + ii + 1) + "Subs");
				subsArray.length = 0;
				var currentMenu = CURRENT_MENU_ID + (startingIndex + ii + 1);
				
				var MenuObject = new dynamicMenu(currentMenu, TIMER_MILLISECONDS);
				var currentSub = currentMenu + SUB;
				var subElements = new Array();
				
				
				for(var i = 0; i < compVehicles.length; i++) {
					//get a reference to this trim wrapper:
					var trimRef = compVehicles[i];
					//need the dom id of the element
					var trimElemID = currentSub + ELEM + (i + 1);
					//need the text to display on the element
					var displayText = trimRef.make + "|" + trimRef.shortName;
					
					var args = new Array();
					args.push(trimRef.id);
					args.push(null); //this is to maintain symmetry with the other construction functions
					args.push(ii + startingIndex + 1);
					args.push(COMPETITOR);
					subElements.push(new element(trimElemID, trimRef.shortName, args));
				}
					//build the sub menu for this model:
					menuMarkup +=  buildSubMenu(currentMenu, currentSub, subElements, AIC_COMP_TRIMS);
					subsArray.push(currentSub);
				
				menus[currentMenu] = MenuObject;
				//attachExtraMenuFunctionality(currentMenu, currentSub);
				//alert("competitors; " + ii + " " + subsArray.length);
			}
			return menuMarkup;
			
		}
		
		function constructCompetitorsMenuSystems(numberOfMenus, startingIndex, competitorMenuWrapper) {
			/*
			@startingIndex should be understood as - starting *after*
			*/
			var SUB = "Sub";
			var ELEM = "Elem";
			var CURRENT_MENU_ID = "menu";
			var NUM_OF_MENUS = numberOfMenus;
			
			var menuMarkup = "";
			var counter = 0;
			//meta-loop: build @numberOfMenus many identical menus; startingIndex is likely > 1 (first menu would be mitsu menu)
			for(var ii= 0; ii < NUM_OF_MENUS; ii++) {
				var subsArray = eval("Menu" + (startingIndex + ii + 1) + "Subs");
				subsArray.length = 0;
				var currentMenu = CURRENT_MENU_ID + (startingIndex + ii + 1);
				//alert(currentMenu);
				
				var MenuObject = new dynamicMenu(currentMenu, TIMER_MILLISECONDS);
				
				var currentSub = currentMenu + SUB;
				var subElements = new Array();
				//first loop-unit builds the subMenu of makes
				for(var i = 0; i < allCompetitorMakes.length; i++) {
					var elemID = currentSub + ELEM + (i + 1);
					
					//get a reference to the make object:
					var refMake = allCompetitorMakes[i];
					
					subElements.push(new element(elemID, refMake.name));
				}
				
				menuMarkup += buildSubMenu(currentMenu, currentSub, subElements, AIC_ALL_COMP_FRAG, competitorMenuWrapper);
				//addMenuToElementAssociation(MenuObject, currentMenu, currentSub);
				subsArray.push(currentSub);
				counter++;
				//loop over the makes again, and this time, for each make, build the sub of its models:
				
				//alert(subElements.length);
				for(var i = 0; i < allCompetitorMakes.length; i++) {
					subElements = new Array();
					//get a reference to the make object:
					var refMake = allCompetitorMakes[i];
					//construct the id for the element which opens the sub menu:
					var openingElementID = currentSub + ELEM + (i + 1);
					//construct the id for this sub:
					var subID = openingElementID + SUB;
					
					for(j = 0; j < refMake.models.length; j++) {
						//generate this element's id:
						var currElemID = subID + ELEM + (j + 1);
						//get a reference to the model object:
						var refModel = eval(refMake.models[j]);
						//push the element onto the "stack"
						//alert(refMake.name + " " + refModel.name + " subElements currently:" + subElements.length);
						subElements.push(new element(currElemID, refModel.name));
					}
					menuMarkup +=  buildSubMenu(currentMenu, subID, subElements, AIC_ALL_COMP_FRAG);
					//addMenuToElementAssociation(MenuObject, openingElementID, subID);
					subsArray.push(subID);
					counter++;
					
					//finally, loop through the models again, building out the subs of the trims:
					for(j = 0; j < refMake.models.length; j++) {
						//generate this element's id:
						var currModelElemID = subID + ELEM + (j + 1);
						var currModelElemSubID = currModelElemID + SUB;
						//get a reference to the model object:
						var refModel = eval(refMake.models[j]);
						//reinitialize:
						subElements = new Array();
						//now, loop over all trims for this model, building up the submenu's elements:
						for(x = 0; x < refModel.trims.length; x++) {
							//get a reference to the trim object:
							var trimRef = refModel.trims[x];
							//define the ID of this element:
							var trimElemID = currModelElemSubID + ELEM + (x + 1);
							//need to add click functionality args function
							var args = new Array();
							args.push(trimRef.id);
							args.push(constructAicKey(trimRef.parentID));
							args.push(ii + startingIndex + 1);
							args.push(COMPETITOR);
							subElements.push(new element(trimElemID, trimRef.shortName, args));
						}
						
						//build the sub menu for this model:
					menuMarkup +=  buildSubMenu(currentMenu, currModelElemSubID, subElements, AIC_ALL_COMP_FRAG);
					//associate the sub with it's "owner" element:
					//addMenuToElementAssociation(MenuObject, currModelElemID, currModelElemSubID);
					subsArray.push(currModelElemSubID);
					counter ++;
					}
					
				}
				
				menus[currentMenu] = MenuObject;
				//attachExtraMenuFunctionality(currentMenu, currentSub);
				//alert("competitors; " + ii + " " + subsArray.length);
			}
			//alert("subsArray.length = " + subsArray.length + "; counter: " + counter);
			return menuMarkup;
		}
		
		
				//function which takes the data-structure generated via AIC, server-side, and calls buildSubMenu() sequentially, for each
		//menu-system
		function constructMitsuMenuSystems(numberOfMenus, startingIndex) {
			var SUB = "Sub";
			var ELEM = "Elem";
			var CURRENT_MENU_ID = "menu";
			var NUM_OF_MENUS = numberOfMenus;
			
			var menuMarkup = "";
			
			for(var ii = 0; ii < numberOfMenus; ii++) {
				var subsArray = eval("Menu" + (startingIndex + ii + 1) + "Subs");
				subsArray.length = 0;
				var currentMenu = CURRENT_MENU_ID + (startingIndex + ii + 1);
				//steps:
				//1. create dynamic menu wrapper
				//2. build the sub menu associated with the menu object - contains the list of models
				//3. For each model-element, build the associated sub menu, which contains the trims associated with each model
				
				//#1:
				
				var currentSub = currentMenu + SUB;
				var subElements = new Array();
				var counter = 0;
				
				
				
				var MenuObject = new dynamicMenu(currentMenu, TIMER_MILLISECONDS);
				//#2:
				for(var i=0; i < modelIndex.length; i++) {
					var key = constructAicKey(modelIndex[i]);
					var modelRef = aicModels[key];
					counter += 1;
					var elemID = currentSub + ELEM + counter;
					subElements.push(new element(elemID, modelRef.name));
				}
				
				menuMarkup += buildSubMenu(currentMenu, currentSub, subElements);
				//addMenuToElementAssociation(MenuObject, currentMenu, currentSub);
				subsArray.push(currentSub);
				//#3:
				counter = 0;
				
				for(var i=0; i < modelIndex.length; i++) {
					subElements = new Array();
					var key = constructAicKey(modelIndex[i]);
					var modelRef = aicModels[key];
					counter += 1;
					//define the ID of the element with which the sub will be associated:
					var ownerElemID = currentSub + ELEM + counter;
					var subID = ownerElemID + SUB;
					for(var j=0; j < modelRef.trims.length; j++) {
						//get a reference to the trim object:
						var trimRef = modelRef.trims[j];
						//define the ID of this element:
						var elemID = subID + j;
						//need to add click functionality args function
						var args = new Array();
						args.push(trimRef.id);
						args.push(constructAicKey(trimRef.parentID));
						args.push(ii + 1 + startingIndex);
						subElements.push(new element(elemID, trimRef.shortName, args));
					}
	
					//build the sub menu for this model:
					menuMarkup +=  buildSubMenu(currentMenu, subID, subElements);
					//associate the sub with it's "owner" element:
					//addMenuToElementAssociation(MenuObject, ownerElemID, subID);
					subsArray.push(subID);
					
					
					
				}
				//alert(currentMenu);
				menus[currentMenu] = MenuObject;
				//attachExtraMenuFunctionality(currentMenu, currentSub);
				//alert("mitsu; " + ii + " " + subsArray.length);
			}
			
			return menuMarkup;
				
		}
		
		
		
		function resetSystem() {
			//clear any selected trims
			//alert("resetting system");
			for(var i = 0; i < StateMonitor.getNumberOfColumns(); i++) {
				//alert("resetting menu " + (i + 1));
				resetMenus(i + 1);
			}
			checkAndHideResults();
			if(isSafari) {
				makeMenusVisible();
			}
			//hideComparePrint();
			StateMonitor.numberSelected = 0;
		}
		
		function makeMenusVisible() {
			for(var i = 0; i < StateMonitor.getNumberOfColumns(); i++) {
				var menuHousingID = "m" + (i + 1) + "Housing";
				var refHousing = fetch(menuHousingID);
				if(refHousing) {
					refHousing.style.visibility = "visible";
				}
			}
		}
		
		function buildMitsuSet(numberOfMenus) {
			killAjax();
			
			
				redrawFlash();
				resizerForTrimColumn(resizerForTrimColumn.AT_LEAST);
				
				//reset all variables, display, etc:
				hovers.length = 0;
				resetSystem();
				
				//set whether we're on the competitive tab or not:
				var onComp = numberOfMenus != 4 ? selectedTrimsMonitor.ON : selectedTrimsMonitor.OFF;
				StateMonitor.setCompetitiveTabState(onComp);
				
				
				for(var i = 0; i < numberOfMenus; i++) {
						var	toWrite = constructMitsuMenuSystems(1, i);
						//toWrite = "<p>Hi there</p>";
						var containerID = "dynamContainer" + (i + 1);
						var refDynamContainer = fetch(containerID);
						if(1) {
							refDynamContainer.innerHTML = toWrite;
							//alert(refDynamContainer.id);
							//alert("hippozz\n" + (i + 1) + "\n" + refDynamContainer.innerHTML);
						}
						else {
							alert("no go, hobo");
						}
						
				}
				
				
				attachExtraMenuFunctionality(numberOfMenus);
				
				setDefaultMitsuTrim();
				setAICMessaging();
				
				setInitialLegal();
				
		}
		
		function setInitialLegal() {
			if(defaultModelReference != null) {
					if(defaultModelReference.name == "2006 Raider") {
						resizerForTrimColumn(resizerForTrimColumn.AT_LEAST);
					}
					else {
						fetch("legalCopy").style.top = LEGAL_TOP_COORDINATE;
					}
				}
				else {
					fetch("legalCopy").style.top = LEGAL_TOP_COORDINATE;
				}
		}
		
		function determineDefaultMitsuTrim() {
				if(defaultModelReference == null) {
					var key = pullKeyFromUrl();
					if(key != null) {
						MSG_AIC_VEH_REPLACE = key;
						var refModel = retrieveModelwithName(key);
						//set the global reference to this vehicle, for future use:
						defaultModelReference = refModel;
						
					}
				}
		}
		
		function setDefaultMitsuTrim() {
			if(defaultModelReference == null) {
					determineDefaultMitsuTrim();
					if(defaultModelReference != null) {
						trimSelected(defaultModelReference.trims[0].id, constructAicKey(defaultModelReference.trims[0].parentID), 1);
						
					}
			}
				else {
					trimSelected(defaultModelReference.trims[0].id, constructAicKey(defaultModelReference.trims[0].parentID), 1);
				}
		}
		
		function buildCompetitiveSet() {
				killAjax();
			//var refDynamContainer = fetch("dynamicContainer");
			//if(refDynamContainer) {
				//clear the current content of the container:
				//refDynamContainer.innerHTML = "";
				
				//reset all variables, display, etc:
				hovers.length = 0;
				resetSystem();
				
				showHideAsyncMsg(SHOW, MSG_WORKING);
				//competitorCallBack("");
				
				//we need the default trim in order to pass its id to the asynchronous call:
				if(defaultModelReference == null) {
					determineDefaultMitsuTrim();
				}
				
				var trimID = (arguments.length == 1) ? arguments[0] : defaultModelReference.trims[0].id;
				//alert("making request for *" + trimID + "*");
				
				try {
					makeRequest(ACTION_GET_COMP_TO_TRIM, ("trim=" + trimID), 'competitorCallBack(http_request[i].responseText)');
					StateMonitor.setIsAjaxInProgress(true);
				}
				catch(e) {
					StateMonitor.setIsAjaxInProgress(false);
				}
			//}
		}
		
		function competitorCallBack(data) {
			try {
				eval(data);
				//alert("evaluated ajax!");
			}
			catch(e) {
				alert("Hippo " + e);
			}
			
			var dynamContainer;
			
			if(StateMonitor.getCompetitiveTabState() != selectedTrimsMonitor.ON) {
				
				var markup = constructMitsuMenuSystems(1, 0);
				dynamContainer = fetch("dynamContainer1");
				if(dynamContainer != null) {
					dynamContainer.innerHTML = markup;
				}
			}
			
			for(var i = 1; i < 4; i++) {
				var toWrite = competitiveBuilder(i);
				dynamContainer = fetch("dynamContainer" + (i + 1));
				if(dynamContainer != null) {
					dynamContainer.innerHTML = toWrite;
				}
			}
			
			
			
			
			attachExtraMenuFunctionality(4);
			setDefaultMitsuTrim();
			StateMonitor.setCompetitiveTabState(selectedTrimsMonitor.ON);
			setAICMessaging();
			showHideAsyncMsg(HIDE);
			redrawFlash();
			StateMonitor.setIsAjaxInProgress(false);
			setInitialLegal();
			setCompetitiveDefaults();	
			//KILL
			/*
			menuMirrors["menu2"].setCompetitorFirstIndex(6);
			menuMirrors["menu2"].setCompetitorLastIndex(10);
			retrieveCompetitorFragment("menu2", dynamicMenu.NEXT);
			*/
		}
		
		
		function setCompetitiveDefaults() {
			//alert(compVehicles.length);
			//trimSelected(trimID, parentKey, menuColumn)
			var numColumns = StateMonitor.getNumberOfColumns();
			var numCompetitors = compVehicles.length;
			
			for(var i=2; i <= numColumns; i++) {
				var currIndex = i - 2;
				if(!(numCompetitors < (currIndex + 1))) {
					trimSelected(compVehicles[currIndex].id, null, i);
				} else {
					resetMenus(i);
				}
			}
		}
		
		function setAICMessaging() {
			var refAICMsg = fetch("aicMsgBox");
			if(refAICMsg) {
				if(StateMonitor.getCompetitiveTabState() == selectedTrimsMonitor.ON) {
					refAICMsg.innerHTML = MSG_AIC_COMP.replace(MSG_AIC_VEH_REPLACE_EXP, MSG_AIC_VEH_REPLACE);
				}
				else {
					refAICMsg.innerHTML = MSG_AIC_MITS.replace(MSG_AIC_VEH_REPLACE_EXP, MSG_AIC_VEH_REPLACE);
				}
			}
		}
		
		function competitiveBuilder(column) {
			var markup = "";
			//only want to write the first menu if we're coming into this tab from
			//the non-competitive tab:
			
			
			markup += constructTrimBasedCompetitiveSet(1, column);
			
			
			return markup;
		}
		
		
		function hideMenuDisplay() {
			var refMenuPane = fetch("menuDisplayPane");
			if(refMenuPane != null) {
				showHideFamily(HIDE,refMenuPane);
			}
		}
		
		function showHideAsyncMsg(action) {
			/*
			 @ action --> SHOW | HIDE
			 (optional) @arguments[1] --> a message
			*/
			var refMsg = fetch("asyncMsg");
			if(refMsg != null) {
				if(arguments.length == 2) {
					//refMsg.innerHTML = arguments[1];
					
				}
				var state = action == SHOW ? 'visible' : 'hidden';
				
				refMsg.style.visibility = state;
				//alert(refMsg.style.visibility);
			}
		}
		
var urlSignature = new Object();
urlSignature["lancer/11"] = "2011 Lancer";
urlSignature["sportback/11"] = "2011 Lancer Sportback";
urlSignature["sportback/12"] = "2012 Lancer Sportback";
urlSignature["evo/11"] = "2011 Lancer Evolution";
urlSignature["evo/12"] = "2012 Lancer Evolution";
urlSignature["galant/11"] = "2011 Galant";
urlSignature["outlander/11"] = "2011 Outlander";
urlSignature["outlandersport/11"] = "2011 Outlander Sport";
urlSignature["outlandersport/12"] = "2012 Outlander Sport";
urlSignature["endeavor/11"] = "2011 Endeavor";
urlSignature["eclipse/11"] = "2011 Eclipse";
urlSignature["spyder/11"] = "2011 Eclipse Spyder"; 
urlSignature["eclipse/12"] = "2012 Eclipse";
urlSignature["spyder/12"] = "2012 Eclipse Spyder"; 
urlSignature["outlander/12"] = "2012 Outlander";
urlSignature["galant/12"] = "2012 Galant";
urlSignature["lancer/12"] = "2012 Lancer";

function pullKeyFromUrl() {
	var key = null;
	
	var regX =  new RegExp(/jsp\/([\w]+\/[\d]{2})\//);              
	var path = window.location.pathname;
	var result = path.match(regX);
	
	if(result != null) {
		key = urlSignature[result[1]];
	}
	
	return key;
}

function retrieveModelwithName(name) {
	var model = null;
	
	if(aicModels != null) {
		for(key in aicModels) {
			model = aicModels[key];
			if(model.name == name) {
				break;
			}
			else {
				model = null;
			}
		}
	}
	
	return model;
}

function clearAndHideAllCompareElements() {
	
	//the menu display pane
	var refMenuPane = fetch("menuDisplayPane");
	if(refMenuPane != null) {
		//showHideFamily(HIDE,refMenuPane);
	}
	
	//hide the menu-column-related elements:
	for(var i = 0; i < StateMonitor.getNumberOfColumns(); i++) {
		for(var j = 0; j < columnElementIDs.length; j++) {
			var template = columnElementIDs[j];
			var elemID = template.replace(columnElementIDsReplaceChar, (i + 1));
			var refCompareElem = fetch(elemID);
			if(refCompareElem != null) {
				refCompareElem.style.visibility = "hidden";
			}
		}
	}
	//hide the compare results pane:
	var refResults = fetch("compareDisplayPane");
	if(refResults != null) {
		refResults.innerHTML = "";
		refResults.style.visibility = "hidden";
	}
	
	hideComparePrint();
}

function redrawFlash() {
	nav_event("close");
	transparent = "false";
	isOpen = false; 
	var fo = new FlashObject("/MMNA/swf/mitsubishi_vehicleNav.swf?xmlpath=" + swfXml + "&isOpen="+isOpen, "vehicleNav", "203", "360", "6", "black");
	fo.addParam("scale", "noscale");
	fo.addParam("menu", "false");
	fo.addParam("wmode", "transparent");
	fo.addVariable("isTransparent", transparent);
	fo.addVariable("currentPage", window.location.pathname);
	fo.write("individual_vehicle_nav");
	fo = null;
	delete(fo);
	
}

function showComparePrint() {
	try {
		fetch("printCompare").style.visibility = "visible";
	}
	catch(e) {
		
	}
}

function hideComparePrint() {
	try {
		fetch("printCompare").style.visibility = "hidden";
	}
	catch(e) {
		
	}
	
	resizerForTrimColumn(resizerForTrimColumn.AT_LEAST);
}

function resizeForTrims() {
	//alert("resizing");
	try {
		fetch("individual_vehicle_content").style.height = "1000px";
	}
	catch(e) {
		alert(e);
	}
}


function printComparison() {
	
	
	var openDirs = window.open("about:blank", "Comparison", "", "");
	
	var refDataPane = fetch("compareDisplayPane");
	var markup = "";
	markup += "<html>";
	markup += "<head>";
	markup += "<link href=\"/MMNA/css/styles.css\" rel=\"stylesheet\" type=\"text/css\">";
	markup += "</head>";
	markup += "<body>";
	//need to put the vehicle image and name in the proper column:
	//style=\"background-image:url(/MMNA/images/compare/compare_backgd_img.jpg); repeat:no-repeat;\"
	markup += "<table width=\"959\" border=\"0\" cellpadding=\"4\" cellspacing=\"0\">";
	markup += "<tr><td width=\"192\"></td><td width=\"180\">&nbsp;</td><td width=\"175\">&nbsp;</td><td width=\"175\">&nbsp;</td><td width=\"237\">&nbsp;</td></tr>";
	markup += "<tr>";
	var numberOfColumns = 4;
	markup += "<td style=\"color:#FFFFFF\">For best results print in landscape orientation.</td>";
	for(var i = 0; i < numberOfColumns; i++) { //individual data
		if (StateMonitor.isColumnSelected(i + 1)) {
			//get the column wrapper object
			//alert("column " + (i + 1) + " is selected");
			var wrap = StateMonitor.getDataWrapperForColumn(i + 1);
			var shortTrim = getTrimPacket(wrap.trimID, wrap.parentID);
			var objImg = new Image();
			objImg.src = shortTrim.img;
			var toDisplay = "<img src=\"" + objImg.src + "\"/><br>" + shortTrim.text;
			markup += "<td style=\"color:#ffffff;\">" + toDisplay + "</td>";
		} else {
			markup += "<td>&nbsp;</td>";
		}
	}
	markup += "<tr>";
	
	markup += "</table>";
	
	markup += refDataPane.innerHTML;
	var legal = "<div style=\"color:#ffffff\">" + fetch("legalCopy").innerHTML + "</div>";
	markup += legal;
	markup += "<script>setTimeout('window.print()', 3000);</script>";
	markup += "</body>";
	markup += "</html>";
	openDirs.document.write(markup);
	
	try {
		window.stop();
	}
	catch(e) {
		
	}

	
}

function killAjax() {
	//alert(whatFunction[whatFunction.length - 1]);
	if(whatFunction.length > 0) {
		whatFunction[whatFunction.length - 1] = "";
		try {
			fetch("asyncMsg").style.visibility = "hidden";
		}
		catch(e) { }
	}
	
	StateMonitor.setIsAjaxInProgress(false);
}

function slide(scrollerID, dir){
	var scrollerObj = fetch(scrollerID);
	if(scrollerObj) {
		var TOP_BOUND = 18;
		var BOTTOM_BOUND = MENU_HEIGHT - scrollerObj.offsetHeight + 19;
		var newTop;
		if(dir == DIR_UP) {
			newTop = scrollerObj.offsetTop - SCROLL_INCREMENT;
			if(newTop < BOTTOM_BOUND) {
				newTop = BOTTOM_BOUND;
			}
		}
		else if(dir == DIR_DOWN) {
			newTop = scrollerObj.offsetTop + SCROLL_INCREMENT;
			//fetch("feedback").value = newTop;
			if(newTop > TOP_BOUND) {
				newTop = TOP_BOUND;
			}
			
		}
		scrollerObj.style.top = newTop + "px";
	}		
}

function moveSlides(objID, dir) {
	if(! isSliding) {
		isSliding = true;
		var funcSignature = "slide('" + objID + "','" + dir + "')";
		_interval = setInterval(funcSignature,30);
	}
	
}

function clear() {
	clearInterval(_interval);
	isSliding = false;
}

function stopSlides() {
	clear();
}

