/*<script>*/
/*
 * This module purposely does not bog the client down with null continuous checks due to initial checks.
 * No client-side JavaScript should be modifying the HTML QQ DOM, unless you want errors.
 * Also, you will notice there aren't as many null checks in here as could be from the data we receive from Disney.
 * The production team know certain things that must be set correctly for this to work.
 * If something is broken in this JS it is because they forgot something vital, and should not be ran without.
 *
 * Business Units: It may be proper to ensure the selectedIndex value matches the index/key in the BU array, but this is time consuming
 *    and a waste of resources due to the HTML controlled by us.
 *
 * Components: If the SQQComponent exists in the object, the value is a valid array with length > 0; not making additional checks for this
 */
function DisneyQuickQuote() {
	// "cur*" variables should/can change, "qq*" variables should not
	this.arrAttributes = {
		'curOpenCalendar': -1,			// if a calendar is open this will be the # in our qqCalendars array, -1 means none open
		'curOpenCalendarBtn': '',		// the ID of the button that opened the calendar
		'fAfterInit': '',				// if function exists, fires after init is completed, before qq displays
		'qqCalendarPadding': 10,		// the padding around the calendar for where a click will not close the calendar
										// ** this should encompass the calendar button, or it will close when clicked **
										// if no padding is needed, change the event function to include a safe zone
										// for the calendar button image as well
		'qqCalendars': Array(),			// array of all available calendar objects
		'qqElement': 'DisneyQuickQuote',	// the qq container element ID, as a string
		'qqTravelMinLength': Array(),	// array of integers for minimum travel length; ID matches the calendar it
										// interfaces with, e.g. qqTravelMinLength[2] relative to qqCalendars[2]
		'qqWidth': 240		// width of the qq container/please wait layer
	};
	
	// array of supported SQQComponents for processing (not rendering)
	// we also need to process SQQBusinessUnit and SQQProductOption
	this.arrSupport = [
		'SQQTravelDates',
		'SQQPartyMix',
		'SQQDropDownMulti',
		'SQQDropDown',
		'SQQTextBox',
		'SQQGrouping',
		'SQQBusinessUnit',
		'SQQProductOption'
	];
	
	this.objData = null; // storage of json data
}

// custom function to handle loops that executes a function on all returns objects
DisneyQuickQuote.prototype.loopElementsWithCallback = function( nodeElements, funcCallback ) {
	if ( !nodeElements || !funcCallback ) {
		return false;
	}
	
	//var nodeElements = nodeRoot.getElementsByTagName( strTagName );
	if ( typeof( nodeElements ) === 'object') {
		var intLength = ( nodeElements.length - 1 );
		
		if ( intLength < 0 ) {
			return false;
		}
		
		do {
			funcCallback( nodeElements[intLength] );
		} while ( intLength-- );
	} else {
		nodeElements = Array.prototype.slice.call( nodeElements );
		
		while ( nodeElements.length > 0 ) {
			funcCallback( nodeElements.pop() );
		}
	}
	
	return true;
};


// errors are displayed in our please wait layer
// @param strMessage string - the error text that will be placed in the please wait layer
DisneyQuickQuote.prototype.displayError = function( strMessage ) {
	document.getElementById( 'qqPleaseWaitLabel' ).innerHTML = strMessage;
	document.getElementById( this.arrAttributes.qqElement ).style.display = 'none';
	document.getElementById( 'qqPleaseWait' ).style.display = 'block';
	return false;
};

// controller of the submission-related errors, utilizes this.displayMessage if the browser supports it
// @param strElement string - element id, used for ie6 to display message underneath the submit button
// @param strMessage string - the error text that will be placed in the notification
DisneyQuickQuote.prototype.displaySubmitError = function( strElement, strMessage ) {
	this.displayMessage( strMessage, this.objData.Prop.errors.strHead, this.objData.Prop.errors.strCloseLabel );
	
	return false;
};

// displays a notification to the client, creates the div if it doesn't exist
// @param strMessage string - the error text that will be placed in the please wait layer
// @param strTitle string - the title text
// @param strClose string - the close button text
// @param bHideInnerBox boolean - this is mostly used for IE6, it hides the inner box, only displaying the background
DisneyQuickQuote.prototype.displayMessage = function( strMessage, strTitle, strClose, bHideInnerBox ) {
	var nodeQQ = document.getElementById( this.arrAttributes.qqElement );
	var nodeWarn = document.getElementById( 'qqWarning' );
	if ( typeof( document.body.style.maxHeight ) == 'undefined' ) {
		this.loopElementsWithCallback( nodeQQ.getElementsByTagName( 'select' ), function( node ) {
			node.style.visibility = 'hidden';
		} );
	}
	
	if ( !nodeWarn ) {
		var that = this;
		nodeWarn = document.createElement( 'div' );
		nodeWarn.id = 'qqWarning';
		nodeWarn.style.display = 'block';
		
		var nodeBg = nodeWarn.appendChild( document.createElement( 'div' ) );
		nodeBg.className = 'qqWarningBackground';
		nodeBg.id = 'qqWarningBackground';
		nodeBg = undefined;
		
		var nodeContainer = nodeWarn.appendChild( document.createElement( 'div' ) );
		nodeContainer.className = 'qqWarningContainer';
		nodeContainer.id = 'qqWarningContainer';
		
		if ( document.all ) {
			nodeContainer.style.position = 'relative';
		}
		
		var nodeBox = nodeContainer.appendChild( document.createElement( 'div' ) );
		nodeBox.className = 'qqWarningBox';
		nodeContainer = undefined;
		
		var nodeText = nodeBox.appendChild( document.createElement( 'div' ) );
		nodeText.id = 'qqWarningTitle';
		nodeText.innerHTML = '&nbsp;';
		nodeText = undefined;
		
		nodeText = nodeBox.appendChild( document.createElement( 'div' ) );
		nodeText.id = 'qqWarningMessage';
		nodeText.innerHTML = '&nbsp;';
		nodeText = undefined;
		
		nodeText = nodeBox.appendChild( document.createElement( 'div' ) );
		nodeText.id = 'qqWarningClose';
		nodeText.innerHTML = 'Close';
		this.addEvent( nodeText, 'click', function() { that.hidePopup( 'qqWarning', 'click' ); }, false );
		nodeText = undefined;
		
		nodeBox = undefined;
		nodeQQ.appendChild( nodeWarn );
	} else {
		nodeWarn.style.display = 'block';
	}
	
	if ( bHideInnerBox ) {
		document.getElementById( 'qqWarningContainer' ).style.visibility = 'hidden';
	} else {
		document.getElementById( 'qqWarningContainer' ).style.visibility = 'visible';
	}
		
	document.getElementById( 'qqWarningTitle' ).innerHTML = strTitle;
	document.getElementById( 'qqWarningMessage' ).innerHTML = strMessage;
	document.getElementById( 'qqWarningClose' ).innerHTML = strClose;
	
	if ( document.all ) {
		if ( typeof( document.body.style.maxHeight )== 'undefined' ) {
			nodeWarn.style.display = 'block';
			nodeWarn.style.height = document.getElementById( this.arrAttributes.qqElement ).offsetHeight + 'px';
			document.getElementById( 'qqWarningBackground' ).style.height = nodeWarn.offsetHeight + 'px';
			document.getElementById( 'qqWarningBackground' ).style.width = nodeWarn.offsetWidth + 'px';
		}
		
		nodeWarn.style.display = 'block';
		document.getElementById( 'qqWarningContainer' ).style.top = ( Math.floor( nodeWarn.offsetHeight / 2 ) - Math.floor( document.getElementById( 'qqWarningContainer' ).offsetHeight / 2 ) ) + 'px';
	} else {
		nodeWarn.style.display = 'block';
	}
};

// function executed once the page loads
DisneyQuickQuote.prototype.startOnload = function() {
	if ( !this.arrAttributes.qqElement ) {
		return this.displayError( 'Unable to find the Disney Quick Quote placeholder.' );
	}
	
	// display our please wait layer, and create our container
	this.displayPleaseWait( true );
	
	// we don't have a "var" in front, because setTimeout() will not scope, our execute function frees the memory allocation
	that = this;
	// start our requests, this is in here to ensure the display of our please wait layer
	setTimeout( 'that.execute();', 1 );
	
	return true;
};

// this function's purpose is to call our functions and free up memory
// not hold onto functions by calling the next one inside of each
DisneyQuickQuote.prototype.execute = function() {
	that = undefined;
	
	this.requestPage();
	this.requestBusinessRules();
	
	// make sure our objects were created
	if ( this.objData && this.objData.Prop ) {
		this.processBusinessRules();
	} else {
		return this.displayError( 'Unable to find the Disney Quick Quote object data.' );
	}
	
	if ( typeof( this.arrAttributes.fAfterInit ) == 'function' ) {
		this.arrAttributes.fAfterInit();
	}
	
	this.displayPleaseWait( false );
	
	return true;
};

// display or hide our please wait layer, create QQ container if it doesn't exist
// @param bDisplay boolean - display (true)/hide (false) the please wait layer, qq container gets opposite
DisneyQuickQuote.prototype.displayPleaseWait = function( bDisplay ) {
	var nodeQQ = document.getElementById( this.arrAttributes.qqElement );
	var nodePleaseWait = document.getElementById( 'qqPleaseWait' );
	
	// if our container doesn't exist, create it
	if ( !nodeQQ ) {
		nodeQQ = document.createElement( 'div' );
		nodeQQ.id = this.arrAttributes.qqElement;
		
		document.body.appendChild( nodeQQ );
	}
	
	if ( bDisplay ) {
		// this should never happen, but we don't want to accidentally recreate this layer
		if ( nodePleaseWait ) {
			nodeQQ.style.display = 'none';
			nodePleaseWait.style.display = 'block';
		} else {
			nodePleaseWait = document.createElement( 'div' );
			nodePleaseWait.id = 'qqPleaseWait';
			
			// if a width is specified, restrain our please wait layer
			if ( this.arrAttributes.qqWidth && this.arrAttributes.qqWidth > 0 ) {
				nodePleaseWait.style.width = this.arrAttributes.qqWidth + 'px';
				nodeQQ.style.width = this.arrAttributes.qqWidth + 'px';
			}
			
			nodePleaseWait.style.display = 'block';
			
			var nodeContainer = nodePleaseWait.appendChild( document.createElement( 'div' ) );
			nodeContainer.className = 'qqPleaseWaitContainer';
			
			var nodeText = nodeContainer.appendChild( document.createElement( 'p' ) );
			nodeText.className = 'qqPleaseWaitLabel';
			nodeText.id = 'qqPleaseWaitLabel';
			nodeText.innerHTML = 'Please wait...';
			
			nodeText = undefined;
			nodeContainer = undefined;
			
			nodeQQ.style.display = 'none';
			// insert the please wait layer before the QQ container
			nodeQQ.parentNode.insertBefore( nodePleaseWait, nodeQQ );
		}
	} else {
		nodePleaseWait.parentNode.removeChild( nodePleaseWait );
		nodeQQ.style.display = 'block';
	}
	
	nodePleaseWait = undefined;
	nodeQQ = undefined;
	
	return true;
};

// wait until page has loaded the DOM until moving on with the business rules
DisneyQuickQuote.prototype.requestPage = function() {
	document.getElementById( this.arrAttributes.qqElement ).innerHTML = '<div id="NextGenCommerceSQQProperties_BookingGenie_en_US" class="SQQProperties"><div id="WDW_Container" class="SQQBusinessUnit"><div class="SQQBUProductOptions"><form action="#" onsubmit="return false;"><div id="WDW_NextGenCommercePackagesSQQProductOption_InputContainer" class="SQQProductOptionContainer"><div id="WDW_NextGenCommercePackagesSQQProductOption_InputDisplay" class="SQQProductOptionOnContainer"><input type="radio" class="SQQProductOptionInput" name="BusinessType" id="WDW_NextGenCommercePackagesSQQProductOption" value="WDWPackages" checked="checked" /><span class="SQQProductOptionInputLabel"><label for="WDW_NextGenCommercePackagesSQQProductOption">Vacation Packages</label></span></div></div><div id="WDW_NextGenCommerceRoomOnlySQQProductOption_InputContainer" class="SQQProductOptionContainer"><div id="WDW_NextGenCommerceRoomOnlySQQProductOption_InputDisplay" class="SQQProductOptionOffContainer"><input type="radio" class="SQQProductOptionInput" name="BusinessType" id="WDW_NextGenCommerceRoomOnlySQQProductOption" value="WDWRooms" /><span class="SQQProductOptionInputLabel"><label for="WDW_NextGenCommerceRoomOnlySQQProductOption"> Room Only</label></span></div></div><div id="WDW_NextGenTicketsSQQProductOption_InputContainer" class="SQQProductOptionContainer"><div id="WDW_NextGenTicketsSQQProductOption_InputDisplay" class="SQQProductOptionOffContainer"><input type="radio" class="SQQProductOptionInput" name="BusinessType" id="WDW_NextGenTicketsSQQProductOption" value="WDWTickets" /><span class="SQQProductOptionInputLabel"><label for="WDW_NextGenTicketsSQQProductOption">Tickets Only</label></span></div></div><div class="clearBoth"><!-- --></div></form><div class="clearBoth"><!-- --></div></div><div id="WDW_NextGenCommercePackagesSQQProductOption_Container" class="SQQProductOption"><form action="/services/BookingGenie/submitSearch" method="GET" id="WDW_NextGenCommercePackagesSQQProductOption_Form" name="WDW_NextGenCommercePackagesSQQProductOption_Form"><input type="hidden" name="publishedKey" value="NextGenCommercePackagesSQQProductOption_BookingGenie_en_US" /><input type="hidden" name="BusinessType" value="WDWPackages" /><input type="hidden" name="BusinessUnit" value="WDW" /><div class="SQQProductOptionTitle"><span class="SQQProductOptionLabel">Vacation Packages</span></div><div id="WDW_NextGenCommercePackagesSQQProductOption_NextGenPackagesSQQTravelDates" class="SQQTravelDates"><div class="SQQTravelDatesArrivalContainer"><div class="SQQTravelDatesLabel"><span class="SQQTravelDatesArrivalLabel">Check In</span></div><div class="SQQTravelDatesDateContainer transparent"><div class="SQQTravelDatesDate"><input name="arrivalDate" id="WDW_NextGenCommercePackagesSQQProductOption_NextGenPackagesSQQTravelDates_arrivalDate" value="11/24/2009" /></div><div class="SQQTravelDatesCalendar" id="WDW_NextGenCommercePackagesSQQProductOption_NextGenPackagesSQQTravelDates_arrivalCalendarBtn"><!-- --></div><div class="clearBoth"><!-- --></div></div><div class="clearBoth"><!-- --></div></div><div class="SQQTravelDatesDepartureContainer"><div class="SQQTravelDatesLabel"><span class="SQQTravelDatesDepartureLabel">Check Out</span></div><div class="SQQTravelDatesDateContainer"><div class="SQQTravelDatesDate"><input type="text" name="departureDate" id="WDW_NextGenCommercePackagesSQQProductOption_NextGenPackagesSQQTravelDates_departureDate" value="11/30/2009" /></div><div class="SQQTravelDatesCalendar" id="WDW_NextGenCommercePackagesSQQProductOption_NextGenPackagesSQQTravelDates_departureCalendarBtn"><!-- --></div><div class="clearBoth"><!-- --></div></div><div class="clearBoth"><!-- --></div></div><div class="clearBoth"><!-- --></div></div><div id="WDW_NextGenCommercePackagesSQQProductOption_NextGenMultiRoomBookingSQQFloatingText" class="SQQFloatingText"><div class="SQQFloatingTextContainer"><span class="SQQFloatingTextLabel"><a id="WDW_NextGenCommercePackagesSQQProductOption_NextGenMultiRoomBookingSQQFloatingText_Link" href="#" class="SQQFloatingTextAnchor">Multi-room booking?</a></span></div></div><div id="WDW_NextGenCommercePackagesSQQProductOption_NextGenSQQPartyMix" class="SQQPartyMix"><div class="SQQPartyMixAdultsContainer"><span class="SQQPartyMixAdultLabel">Adults</span><select class="SQQPartyMixAdultsSelect" name="numAdults" id="WDW_NextGenCommercePackagesSQQProductOption_NextGenSQQPartyMix_numAdults" size="1"><option value="1">1</option><option value="2" selected="selected">2</option><option value="3">3</option><option value="4">4</option><option value="5">5</option><option value="6">6</option></select></div><div class="SQQPartyMixChildrenContainer"><span class="SQQPartyMixChildrenLabel">Children</span><select class="SQQPartyMixChildrenSelect" name="numChildren" id="WDW_NextGenCommercePackagesSQQProductOption_NextGenSQQPartyMix_numChildren" size="1"><option value="0" selected="selected">0</option><option value="1">1</option><option value="2">2</option><option value="3">3</option><option value="4">4</option><option value="5">5</option><option value="6">6</option></select></div><div class="SQQPartyMixChildAgeContainer" id="WDW_NextGenCommercePackagesSQQProductOption_NextGenSQQPartyMix_childContainer"><div class="SQQPartyMixLabel" id="WDW_NextGenCommercePackagesSQQProductOption_NextGenSQQPartyMix_Label"><span class="SQQPartyMixChildInstructionsLabel">Children\'s Ages at Time of Travel</span></div><div class="SQQPartyMixSelectContainer"><div class="SQQPartyMixChildAgeCount" id="WDW_NextGenCommercePackagesSQQProductOption_NextGenSQQPartyMix_ageContainer1"><span class="SQQPartyMixChildAgeLabel">1</span><select class="SQQPartyMixChildAgeSelect" name="child1" id="WDW_NextGenCommercePackagesSQQProductOption_NextGenSQQPartyMix_child1" size="1"><option value="17" selected="selected">17</option><option value="16">16</option><option value="15">15</option><option value="14">14</option><option value="13">13</option><option value="12">12</option><option value="11">11</option><option value="10">10</option><option value="9">9</option><option value="8">8</option><option value="7">7</option><option value="6">6</option><option value="5">5</option><option value="4">4</option><option value="3">3</option><option value="2">2</option><option value="1">Inf</option></select></div><div class="SQQPartyMixChildAgeCount" id="WDW_NextGenCommercePackagesSQQProductOption_NextGenSQQPartyMix_ageContainer2"><span class="SQQPartyMixChildAgeLabel">2</span><select class="SQQPartyMixChildAgeSelect" name="child2" id="WDW_NextGenCommercePackagesSQQProductOption_NextGenSQQPartyMix_child2" size="1"><option value="17" selected="selected">17</option><option value="16">16</option><option value="15">15</option><option value="14">14</option><option value="13">13</option><option value="12">12</option><option value="11">11</option><option value="10">10</option><option value="9">9</option><option value="8">8</option><option value="7">7</option><option value="6">6</option><option value="5">5</option><option value="4">4</option><option value="3">3</option><option value="2">2</option><option value="1">Inf</option></select></div><div class="SQQPartyMixChildAgeCount" id="WDW_NextGenCommercePackagesSQQProductOption_NextGenSQQPartyMix_ageContainer3"><span class="SQQPartyMixChildAgeLabel">3</span><select class="SQQPartyMixChildAgeSelect" name="child3" id="WDW_NextGenCommercePackagesSQQProductOption_NextGenSQQPartyMix_child3" size="1"><option value="17" selected="selected">17</option><option value="16">16</option><option value="15">15</option><option value="14">14</option><option value="13">13</option><option value="12">12</option><option value="11">11</option><option value="10">10</option><option value="9">9</option><option value="8">8</option><option value="7">7</option><option value="6">6</option><option value="5">5</option><option value="4">4</option><option value="3">3</option><option value="2">2</option><option value="1">Inf</option></select></div><div class="SQQPartyMixChildAgeCount" id="WDW_NextGenCommercePackagesSQQProductOption_NextGenSQQPartyMix_ageContainer4"><span class="SQQPartyMixChildAgeLabel">4</span><select class="SQQPartyMixChildAgeSelect" name="child4" id="WDW_NextGenCommercePackagesSQQProductOption_NextGenSQQPartyMix_child4" size="1"><option value="17" selected="selected">17</option><option value="16">16</option><option value="15">15</option><option value="14">14</option><option value="13">13</option><option value="12">12</option><option value="11">11</option><option value="10">10</option><option value="9">9</option><option value="8">8</option><option value="7">7</option><option value="6">6</option><option value="5">5</option><option value="4">4</option><option value="3">3</option><option value="2">2</option><option value="1">Inf</option></select></div><div class="SQQPartyMixChildAgeCount" id="WDW_NextGenCommercePackagesSQQProductOption_NextGenSQQPartyMix_ageContainer5"><span class="SQQPartyMixChildAgeLabel">5</span><select class="SQQPartyMixChildAgeSelect" name="child5" id="WDW_NextGenCommercePackagesSQQProductOption_NextGenSQQPartyMix_child5" size="1"><option value="17" selected="selected">17</option><option value="16">16</option><option value="15">15</option><option value="14">14</option><option value="13">13</option><option value="12">12</option><option value="11">11</option><option value="10">10</option><option value="9">9</option><option value="8">8</option><option value="7">7</option><option value="6">6</option><option value="5">5</option><option value="4">4</option><option value="3">3</option><option value="2">2</option><option value="1">Inf</option></select></div><div class="SQQPartyMixChildAgeCount" id="WDW_NextGenCommercePackagesSQQProductOption_NextGenSQQPartyMix_ageContainer6"><span class="SQQPartyMixChildAgeLabel">6</span><select class="SQQPartyMixChildAgeSelect" name="child6" id="WDW_NextGenCommercePackagesSQQProductOption_NextGenSQQPartyMix_child6" size="1"><option value="17" selected="selected">17</option><option value="16">16</option><option value="15">15</option><option value="14">14</option><option value="13">13</option><option value="12">12</option><option value="11">11</option><option value="10">10</option><option value="9">9</option><option value="8">8</option><option value="7">7</option><option value="6">6</option><option value="5">5</option><option value="4">4</option><option value="3">3</option><option value="2">2</option><option value="1">Inf</option></select></div><div class="clearBoth"><!-- --></div></div><div class="SQQPartyMixDisclaimer" id="WDW_NextGenCommercePackagesSQQProductOption_NextGenSQQPartyMix_disclaimer"><a href="#" class="SQQPartyMixDisclaimerLink" id="WDW_NextGenCommercePackagesSQQProductOption_NextGenSQQPartyMix_disclaimerLink">null</a></div><div class="SQQPartyMixAlert" id="WDW_NextGenCommercePackagesSQQProductOption_NextGenSQQPartyMix_disclaimerAlert"><span class="SQQPartyMixAlertHead" id="WDW_NextGenCommercePackagesSQQProductOption_NextGenSQQPartyMix_disclaimerHead">null</span><p class="SQQPartyMixAlertBody" id="WDW_NextGenCommercePackagesSQQProductOption_NextGenSQQPartyMix_disclaimerBody">null</p></div></div><div class="clearBoth"><!-- --></div></div><div id="WDW_NextGenCommercePackagesSQQProductOption_WDWPackageResortsSQQDropDown" class="SQQDropDown"><span class="SQQDropDownLabel">Resort Hotel</span><select class="SQQDropDownSelect" name="WDWResorts" id="WDW_NextGenCommercePackagesSQQProductOption_WDWPackageResorts" size="1"><option value="">No Preference</option><option value="DLX">*** Disney\'s Deluxe Resorts ***</option><option value="1Q">Disney\'s Animal Kingdom Lodge</option><option value="1W">Disney\'s Beach Club Resort</option><option value="1I">Disney\'s BoardWalk Inn</option><option value="1C">Disney\'s Contemporary Resort</option><option value="1B">Disney\'s Grand Floridian Resort & Spa</option><option value="1P">Disney\'s Polynesian Resort</option><option value="1J">Disney\'s Wilderness Lodge</option><option value="1Y">Disney\'s Yacht Club Resort</option><option value="DVC">*** Disney\'s Deluxe Villa Resorts ***</option><option value="1Z">Disney\'s BoardWalk Villas</option><option value="1K">Disney\'s Old Key West Resort</option><option value="1X">The Villas at Disney\'s Wilderness Lodge</option><option value="1D">Disney\'s Beach Club Villas</option><option value="11">Disney\'s Saratoga Springs Resort & Spa</option><option value="14">Bay Lake Tower at Disney\'s Contemporary Resort</option><option value="12">Disney\'s Animal Kingdom Villas - Jambo House</option><option value="13">Disney\'s Animal Kingdom Villas - Kidani Village</option><option value="MOD">*** Disney\'s Moderate Resorts ***</option><option value="1R">Disney\'s Caribbean Beach Resort</option><option value="1N">Disney\'s Coronado Springs Resort</option><option value="1O">Disney\'s Port Orleans Resort - French Quarter</option><option value="1L">Disney\'s Port Orleans Resort - Riverside</option><option value="1FW">The Cabins at Disney\'s Fort Wilderness</option><option value="VALUE">*** Disney\'s Value Resorts ***</option><option value="1E">Disney\'s All-Star Movies Resort</option><option value="1A">Disney\'s All-Star Music Resort</option><option value="1S">Disney\'s All-Star Sports Resort</option><option value="1G">Disney\'s Pop Century Resort</option><option value="CAB">*** Campground ***</option><option value="1F">The Campsites at Disney\'s Fort Wilderness Resort</option><option value="ODLX">*** Other Deluxe Walt Disney World Resort Hotels ***</option><option value="DOL">Walt Disney World Dolphin Resort</option><option value="SWN">Walt Disney World Swan Resort</option></select></div><div id="WDW_NextGenCommercePackagesSQQProductOption_NextGenSQQBar1" class="SQQBar"><div class="SQQBarContainer"><hr /></div></div><div id="WDW_NextGenCommercePackagesSQQProductOption_NextGenDiningPlanSQQCheckBox" class="SQQCheckBox"><div class="SQQCheckBoxInputContainer"><input type="checkbox" class="SQQCheckBoxInput" name="WDWPackagePlans" value="RTM" /></div><div class="SQQCheckBoxLabelContainer"><span class="SQQCheckBoxLabel">Include Dining Plan</span></div><div class="clearBoth"><!-- --></div></div><div class="SQQProductOptionSubmitContainer"><input type="button" name="inputSubmit" class="SQQProductOptionInputSubmit" id="WDW_NextGenCommercePackagesSQQProductOption_Submit" value="Find Prices" /></div><div class="clearBoth"><!-- --></div></form><div class="SQQProductOptionsDisclaimerContainer" id="WDW_NextGenCommercePackagesSQQProductOption_Disclaimer"><div class="SQQTravelDates"><span class="SQQProductOptionsDisclaimerSecond"><a href="http://disneyworld.disney.go.com/special-needs-request/">Need special accommodations for Guests with disabilities?</a></span><span class="SQQFloatingTextLabel"><br />Book online or call (407) 939-7675.</span></div></div></div><div id="WDW_NextGenCommerceRoomOnlySQQProductOption_Container" class="SQQProductOption"><form action="/services/BookingGenie/submitSearch" method="GET" id="WDW_NextGenCommerceRoomOnlySQQProductOption_Form" name="WDW_NextGenCommerceRoomOnlySQQProductOption_Form"><input type="hidden" name="publishedKey" value="NextGenCommerceRoomOnlySQQProductOption_BookingGenie_en_US" /><input type="hidden" name="BusinessType" value="WDWRooms" /><input type="hidden" name="BusinessUnit" value="WDW" /><div class="SQQProductOptionTitle"><span class="SQQProductOptionLabel"> Room Only</span></div><div id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenRoomOnlySQQTravelDates" class="SQQTravelDates"><div class="SQQTravelDatesArrivalContainer"><div class="SQQTravelDatesLabel"><span class="SQQTravelDatesArrivalLabel">Check In</span></div><div class="SQQTravelDatesDateContainer transparent"><div class="SQQTravelDatesDate"><input name="arrivalDate" id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenRoomOnlySQQTravelDates_arrivalDate" value="11/22/2009" /></div><div class="SQQTravelDatesCalendar" id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenRoomOnlySQQTravelDates_arrivalCalendarBtn"><!-- --></div><div class="clearBoth"><!-- --></div></div><div class="clearBoth"><!-- --></div></div><div class="SQQTravelDatesDepartureContainer"><div class="SQQTravelDatesLabel"><span class="SQQTravelDatesDepartureLabel">Check Out</span></div><div class="SQQTravelDatesDateContainer"><div class="SQQTravelDatesDate"><input type="text" name="departureDate" id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenRoomOnlySQQTravelDates_departureDate" value="11/28/2009" /></div><div class="SQQTravelDatesCalendar" id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenRoomOnlySQQTravelDates_departureCalendarBtn"><!-- --></div><div class="clearBoth"><!-- --></div></div><div class="clearBoth"><!-- --></div></div><div class="clearBoth"><!-- --></div></div><div id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenMultiRoomBookingSQQFloatingText" class="SQQFloatingText"><div class="SQQFloatingTextContainer"><span class="SQQFloatingTextLabel"><a id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenMultiRoomBookingSQQFloatingText_Link" href="#" class="SQQFloatingTextAnchor">Multi-room booking?</a></span></div></div><div id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenSQQPartyMix" class="SQQPartyMix"><div class="SQQPartyMixAdultsContainer"><span class="SQQPartyMixAdultLabel">Adults</span><select class="SQQPartyMixAdultsSelect" name="numAdults" id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenSQQPartyMix_numAdults" size="1"><option value="1">1</option><option value="2" selected="selected">2</option><option value="3">3</option><option value="4">4</option><option value="5">5</option><option value="6">6</option></select></div><div class="SQQPartyMixChildrenContainer"><span class="SQQPartyMixChildrenLabel">Children</span><select class="SQQPartyMixChildrenSelect" name="numChildren" id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenSQQPartyMix_numChildren" size="1"><option value="0" selected="selected">0</option><option value="1">1</option><option value="2">2</option><option value="3">3</option><option value="4">4</option><option value="5">5</option><option value="6">6</option></select></div><div class="SQQPartyMixChildAgeContainer" id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenSQQPartyMix_childContainer"><div class="SQQPartyMixLabel" id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenSQQPartyMix_Label"><span class="SQQPartyMixChildInstructionsLabel">Children\'s Ages at Time of Travel</span></div><div class="SQQPartyMixSelectContainer"><div class="SQQPartyMixChildAgeCount" id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenSQQPartyMix_ageContainer1"><span class="SQQPartyMixChildAgeLabel">1</span><select class="SQQPartyMixChildAgeSelect" name="child1" id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenSQQPartyMix_child1" size="1"><option value="17" selected="selected">17</option><option value="16">16</option><option value="15">15</option><option value="14">14</option><option value="13">13</option><option value="12">12</option><option value="11">11</option><option value="10">10</option><option value="9">9</option><option value="8">8</option><option value="7">7</option><option value="6">6</option><option value="5">5</option><option value="4">4</option><option value="3">3</option><option value="2">2</option><option value="1">Inf</option></select></div><div class="SQQPartyMixChildAgeCount" id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenSQQPartyMix_ageContainer2"><span class="SQQPartyMixChildAgeLabel">2</span><select class="SQQPartyMixChildAgeSelect" name="child2" id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenSQQPartyMix_child2" size="1"><option value="17" selected="selected">17</option><option value="16">16</option><option value="15">15</option><option value="14">14</option><option value="13">13</option><option value="12">12</option><option value="11">11</option><option value="10">10</option><option value="9">9</option><option value="8">8</option><option value="7">7</option><option value="6">6</option><option value="5">5</option><option value="4">4</option><option value="3">3</option><option value="2">2</option><option value="1">Inf</option></select></div><div class="SQQPartyMixChildAgeCount" id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenSQQPartyMix_ageContainer3"><span class="SQQPartyMixChildAgeLabel">3</span><select class="SQQPartyMixChildAgeSelect" name="child3" id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenSQQPartyMix_child3" size="1"><option value="17" selected="selected">17</option><option value="16">16</option><option value="15">15</option><option value="14">14</option><option value="13">13</option><option value="12">12</option><option value="11">11</option><option value="10">10</option><option value="9">9</option><option value="8">8</option><option value="7">7</option><option value="6">6</option><option value="5">5</option><option value="4">4</option><option value="3">3</option><option value="2">2</option><option value="1">Inf</option></select></div><div class="SQQPartyMixChildAgeCount" id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenSQQPartyMix_ageContainer4"><span class="SQQPartyMixChildAgeLabel">4</span><select class="SQQPartyMixChildAgeSelect" name="child4" id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenSQQPartyMix_child4" size="1"><option value="17" selected="selected">17</option><option value="16">16</option><option value="15">15</option><option value="14">14</option><option value="13">13</option><option value="12">12</option><option value="11">11</option><option value="10">10</option><option value="9">9</option><option value="8">8</option><option value="7">7</option><option value="6">6</option><option value="5">5</option><option value="4">4</option><option value="3">3</option><option value="2">2</option><option value="1">Inf</option></select></div><div class="SQQPartyMixChildAgeCount" id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenSQQPartyMix_ageContainer5"><span class="SQQPartyMixChildAgeLabel">5</span><select class="SQQPartyMixChildAgeSelect" name="child5" id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenSQQPartyMix_child5" size="1"><option value="17" selected="selected">17</option><option value="16">16</option><option value="15">15</option><option value="14">14</option><option value="13">13</option><option value="12">12</option><option value="11">11</option><option value="10">10</option><option value="9">9</option><option value="8">8</option><option value="7">7</option><option value="6">6</option><option value="5">5</option><option value="4">4</option><option value="3">3</option><option value="2">2</option><option value="1">Inf</option></select></div><div class="SQQPartyMixChildAgeCount" id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenSQQPartyMix_ageContainer6"><span class="SQQPartyMixChildAgeLabel">6</span><select class="SQQPartyMixChildAgeSelect" name="child6" id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenSQQPartyMix_child6" size="1"><option value="17" selected="selected">17</option><option value="16">16</option><option value="15">15</option><option value="14">14</option><option value="13">13</option><option value="12">12</option><option value="11">11</option><option value="10">10</option><option value="9">9</option><option value="8">8</option><option value="7">7</option><option value="6">6</option><option value="5">5</option><option value="4">4</option><option value="3">3</option><option value="2">2</option><option value="1">Inf</option></select></div><div class="clearBoth"><!-- --></div></div><div class="SQQPartyMixDisclaimer" id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenSQQPartyMix_disclaimer"><a href="#" class="SQQPartyMixDisclaimerLink" id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenSQQPartyMix_disclaimerLink">null</a></div><div class="SQQPartyMixAlert" id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenSQQPartyMix_disclaimerAlert"><span class="SQQPartyMixAlertHead" id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenSQQPartyMix_disclaimerHead">null</span><p class="SQQPartyMixAlertBody" id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenSQQPartyMix_disclaimerBody">null</p></div></div><div class="clearBoth"><!-- --></div></div><div id="WDW_NextGenCommerceRoomOnlySQQProductOption_WDWRoomOnlyResortsSQQDropDown" class="SQQDropDown"><span class="SQQDropDownLabel">Resort Hotel</span><select class="SQQDropDownSelect" name="WDWResorts" id="WDW_NextGenCommerceRoomOnlySQQProductOption_WDWRoomOnlyResorts" size="1"><option value="">No Preference</option><option value="VALUE">*** Disney\'s Value Resorts ***</option><option value="1E">Disney\'s All-Star Movies Resort</option><option value="1A">Disney\'s All-Star Music Resort</option><option value="1S">Disney\'s All-Star Sports Resort</option><option value="1G">Disney\'s Pop Century Resort</option><option value="MOD">*** Disney\'s Moderate Resorts ***</option><option value="1R">Disney\'s Caribbean Beach Resort</option><option value="1N">Disney\'s Coronado Springs Resort</option><option value="1O">Disney\'s Port Orleans Resort - French Quarter</option><option value="1L">Disney\'s Port Orleans Resort - Riverside</option><option value="1FW">The Cabins at Disney\'s Fort Wilderness</option><option value="DLX">*** Disney\'s Deluxe Resorts ***</option><option value="1Q">Disney\'s Animal Kingdom Lodge</option><option value="1W">Disney\'s Beach Club Resort</option><option value="1I">Disney\'s BoardWalk Inn</option><option value="1C">Disney\'s Contemporary Resort</option><option value="1B">Disney\'s Grand Floridian Resort & Spa</option><option value="1P">Disney\'s Polynesian Resort</option><option value="1J">Disney\'s Wilderness Lodge</option><option value="1Y">Disney\'s Yacht Club Resort</option><option value="DVC">*** Disney\'s Deluxe Villa Resorts ***</option><option value="1Z">Disney\'s BoardWalk Villas</option><option value="1K">Disney\'s Old Key West Resort</option><option value="1X">The Villas at Disney\'s Wilderness Lodge</option><option value="1D">Disney\'s Beach Club Villas</option><option value="11">Disney\'s Saratoga Springs Resort & Spa</option><option value="14">Bay Lake Tower at Disney\'s Contemporary Resort</option><option value="12">Disney\'s Animal Kingdom Villas - Jambo House</option><option value="13">Disney\'s Animal Kingdom Villas - Kidani Village</option><option value="CAB">*** Campground ***</option><option value="1F">Disney\'s Fort Wilderness Campsites</option></select></div><div id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenSQQBar1" class="SQQBar"><div class="SQQBarContainer"><hr /></div></div><div id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenRoomOnlyDiningSQQFloatingText" class="SQQFloatingText"><div class="SQQFloatingTextContainer"><span class="SQQFloatingTextLabel"><a id="WDW_NextGenCommerceRoomOnlySQQProductOption_NextGenRoomOnlyDiningSQQFloatingText_Link" href="#" class="SQQFloatingTextAnchor">Want to add a Disney dining plan?</a></span></div></div><div class="SQQProductOptionSubmitContainer"><input type="button" name="inputSubmit" class="SQQProductOptionInputSubmit" id="WDW_NextGenCommerceRoomOnlySQQProductOption_Submit" value="Find Prices" /></div><div class="clearBoth"><!-- --></div></form><div class="SQQProductOptionsDisclaimerContainer" id="WDW_NextGenCommerceRoomOnlySQQProductOption_Disclaimer"><div class="SQQTravelDates"><span class="SQQProductOptionsDisclaimerSecond"><a href="http://disneyworld.disney.go.com/special-needs-request/">Need special accommodations for Guests with disabilities?</a></span><span class="SQQFloatingTextLabel"><br />Book online or call (407) 939-7675.</span></div></div></div><div id="WDW_NextGenTicketsSQQProductOption_Container" class="SQQProductOption"><form action="/services/BookingGenie/submitSearch" method="GET" id="WDW_NextGenTicketsSQQProductOption_Form" name="WDW_NextGenTicketsSQQProductOption_Form"><input type="hidden" name="publishedKey" value="NextGenTicketsSQQProductOption_BookingGenie_en_US" /><input type="hidden" name="BusinessType" value="WDWTickets" /><input type="hidden" name="BusinessUnit" value="WDW" /><div class="SQQProductOptionTitle"><span class="SQQProductOptionLabel">Tickets Only</span></div><div id="WDW_NextGenTicketsSQQProductOption_NextGenTicketPricesSQQFloatingText" class="SQQFloatingText"><div class="SQQFloatingTextContainer"><span class="SQQFloatingTextLabel">View Ticket Prices</span></div></div><div id="WDW_NextGenTicketsSQQProductOption_NextGenTicketsSQQDropDownMulti" class="SQQDropDownMulti"><div id="WDW_NextGenTicketsSQQProductOption_NextGenTicketsSQQDropDownMulti_S1" class="SQQDropDownMultiContainer"><span class="SQQDropDownLabel">Adults & Children Ages 10+</span><select class="SQQDropDownSelect" name="numAdults" id="WDW_NextGenTicketsSQQProductOption_NextGenTicketsSQQDropDownMulti_numAdults" size="1"><option value="1">1</option><option value="2">2</option><option value="3">3</option><option value="4">4</option><option value="5">5</option><option value="6">6</option></select><div class="clearBoth"><!-- --></div></div><div id="WDW_NextGenTicketsSQQProductOption_NextGenTicketsSQQDropDownMulti_S2" class="SQQDropDownMultiContainer"><span class="SQQDropDownLabel">Children Ages 3-9</span><select class="SQQDropDownSelect" name="numChildren" id="WDW_NextGenTicketsSQQProductOption_NextGenTicketsSQQDropDownMulti_numChildren" size="1"><option value="0">0</option><option value="1">1</option><option value="2">2</option><option value="3">3</option><option value="4">4</option><option value="5">5</option><option value="6">6</option></select><div class="clearBoth"><!-- --></div></div><div class="clearBoth"><!-- --></div></div><div id="WDW_NextGenTicketsSQQProductOption_NextGenTravelingFromSQQFloatingText" class="SQQFloatingText"><div class="SQQFloatingTextContainer"><span class="SQQFloatingTextLabel">Where are you traveling from?</span></div></div><div id="WDW_NextGenTicketsSQQProductOption_NextGenCountrySelectionSQQDropDownMulti" class="SQQDropDownMulti"><div id="WDW_NextGenTicketsSQQProductOption_NextGenCountrySelectionSQQDropDownMulti_S1" class="SQQDropDownMultiContainer"><span class="SQQDropDownLabel">Country</span><select class="SQQDropDownSelect" name="CountryList" id="WDW_NextGenTicketsSQQProductOption_NextGenCountrySelectionSQQDropDownMulti_CountryList" size="1"><option value="USA|USStates">United States</option><option value="ARG|">Argentina</option><option value="AUS|">Australia</option><option value="AUT|">Austria</option><option value="BEL|">Belgium</option><option value="BMU|">Bermuda</option><option value="BRA|">Brazil</option><option value="CAN|">Canada</option><option value="CHL|">Chile</option><option value="COL|">Columbia</option><option value="DNK|">Denmark</option><option value="DOM|">Dominican Republic</option><option value="ECU|">Ecuador</option><option value="FIN|">Finland</option><option value="FRA|">France</option><option value="DEU|">Germany</option><option value="GRC|">Greece</option><option value="GTM|">Guatemala</option><option value="KON|">Homg Kong</option><option value="ISL|">Iceland</option><option value="IND|">India</option><option value="ISR|">Israel</option><option value="ITA|">Italy</option><option value="JPN|">Japan</option><option value="KWT|">Kuwait</option><option value="LIE|">Liechtenstein</option><option value="LUX|">Luxemborg</option><option value="MYS|">Malaysia</option><option value="MEX|">Mexico</option><option value="NLD|">Netherlands</option><option value="NZL|">New Zealand</option><option value="NIC|">Nicaragua</option><option value="NOR|">Norway</option><option value="PAN|">Panama</option><option value="PRY|">Paraguay</option><option value="PER|">Peru</option><option value="PHL|">Philippines</option><option value="PRT|">Portugal</option><option value="PRI|">Puerto Rico</option><option value="SGP|">Singapore</option><option value="ZAF|">South Africe</option><option value="ESP|">Spain</option><option value="SWE|">Sweden</option><option value="CHE|">Switzerland</option><option value="THA|">Thailand</option><option value="ARE|">United Arab Emirates</option><option value="GBR|">United Kingdom</option><option value="URY|">Uruguay</option><option value="VEN|">Venezuela</option></select><div class="clearBoth"><!-- --></div></div><div id="WDW_NextGenTicketsSQQProductOption_NextGenCountrySelectionSQQDropDownMulti_S2" class="SQQDropDownMultiContainer"><span class="SQQDropDownLabel">State</span><select class="SQQDropDownSelect" name="CountryTarget" id="WDW_NextGenTicketsSQQProductOption_NextGenCountrySelectionSQQDropDownMulti_CountryTarget" size="1"><option value="" selected="selected"></option></select><div class="clearBoth"><!-- --></div></div><div class="clearBoth"><!-- --></div></div><div id="WDW_NextGenTicketsSQQProductOption_NextGenNumberOfDaysNeedingTicketsSQQFloatingText" class="SQQFloatingText"><div class="SQQFloatingTextContainer"><span class="SQQFloatingTextLabel">How many days will you need tickets?</span></div></div><div id="WDW_NextGenTicketsSQQProductOption_NextGenNumDaysSQQDropDown" class="SQQDropDown"><span class="SQQDropDownLabel">Number of Days</span><select class="SQQDropDownSelect" name="NumberOfDays" id="WDW_NextGenTicketsSQQProductOption_NumberOfDays" size="1"><option value="1">1</option><option value="2">2</option><option value="3">3</option><option value="4">4</option><option value="5">5</option><option value="6">6</option><option value="7">7</option><option value="8">8</option><option value="9">9</option><option value="10">10</option></select></div><div class="SQQProductOptionSubmitContainer"><input type="button" name="inputSubmit" class="SQQProductOptionInputSubmit" id="WDW_NextGenTicketsSQQProductOption_Submit" value="Find Prices" /></div><div class="clearBoth"><!-- --></div></form><div class="SQQProductOptionsDisclaimerContainer" id="WDW_NextGenTicketsSQQProductOption_Disclaimer"><div class="SQQTravelDates"><span class="SQQProductOptionsDisclaimerSecond"><a href="http://disneyworld.disney.go.com/special-needs-request/">Need special accommodations for Guests with disabilities?</a></span><span class="SQQFloatingTextLabel"><br />Book online or call (407) 939-7675.</span></div></div></div></div><div class="SQQBusinessUnitBottom"><!-- --></div></div>';
	
	return true;
};

// just like the rendered page request
DisneyQuickQuote.prototype.requestBusinessRules = function() {
	
	try {
		this.objData = eval( '({"Prop":{"name":"NextGenCommerceSQQProperties_BookingGenie_en_US","nextGenAnalytics":true,"listAllErrors":false,"monthLabels":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"errors":{"strArriveAfterDepart":"Your check-in date occurs after your check-out date. Please change your check-in or check-out date.","strArriveIsAfterMaxDate":"Currently, <b>Walt Disney World</b>® Resort reservations are only available for check-in dates up to and including December 31, 2010. Please modify your travel dates accordingly.","strArriveIsBeforeAllowable":"Arrival date is before the first allowable booking day, please select a later arrival date.","strCloseLabel":"OK","strHead":"Warning","strStayTooLong":"Sorry, this package must be booked for a maximum stay of [N] nights. Please adjust your vacation dates.","strStayTooShort":"Sorry, this package must be booked for a minimum stay of at least [N] nights. Please adjust your vacation dates.","strDiningMsg":"Disney dining plans are available when you purchase a vacation package (i.e., a room plus tickets) and can help you save on all your Disney dining needs. To add a Disney dining plan, select &quot;Vacation Packages.&quot;","strMultiRoomMsg":"Parties with 5 or more people can book additional rooms or a different room type. Other room types can accommodate up to 6 Guests at select Value and Moderate Resorts, up to 8 Guests at select Deluxe Resorts and up to 12 Guests at select Deluxe Villa Resorts.<br></br>To book more than one room, please make a separate reservation for each room. During the booking process, you can ask to have the rooms be located near each other or share a connecting door. "},"BU":[{"value":"WDW","name":"NextGenCommerceSQQBusinessUnit","PO":[{"name":"NextGenCommercePackagesSQQProductOption","trackingLinkId":"QQContPackage_Link","value":"WDWPackages","SQQDropDown":[{"name":"WDWPackageResortsSQQDropDown","isRequired":false,"htmlObjectName":"WDWResorts","xmlPointer":"WDWPackageResorts"}],"SQQPartyMix":{"name":"NextGenSQQPartyMix"},"SQQTravelDates":{"name":"NextGenPackagesSQQTravelDates","travelStartYear":2009,"travelStartMonth":1,"travelStartDate":1,"travelEndYear":2011,"travelEndMonth":1,"travelEndDate":14,"bookStartYear":2009,"bookStartMonth":4,"bookStartDate":1,"bookEndYear":2010,"bookEndMonth":12,"bookEndDate":31,"minBookTime":1,"maxBookTime":14,"singleTextField":true,"startDaysFromToday":3,"displayDateRange":6,"displayStartYear":2009,"displayEndYear":2011}},{"name":"NextGenCommerceRoomOnlySQQProductOption","trackingLinkId":"QQContRoomOnly_Link","value":"WDWRooms","SQQDropDown":[{"name":"WDWRoomOnlyResortsSQQDropDown","isRequired":false,"htmlObjectName":"WDWResorts","xmlPointer":"WDWRoomOnlyResorts"}],"SQQPartyMix":{"name":"NextGenSQQPartyMix"},"SQQTravelDates":{"name":"NextGenRoomOnlySQQTravelDates","travelStartYear":2009,"travelStartMonth":1,"travelStartDate":1,"travelEndYear":2011,"travelEndMonth":1,"travelEndDate":30,"bookStartYear":2009,"bookStartMonth":7,"bookStartDate":1,"bookEndYear":2010,"bookEndMonth":12,"bookEndDate":31,"minBookTime":1,"maxBookTime":30,"singleTextField":true,"startDaysFromToday":1,"displayDateRange":6,"displayStartYear":2009,"displayEndYear":2011}},{"name":"NextGenTicketsSQQProductOption","trackingLinkId":"QQContTickets_Link","value":"WDWTickets","SQQDropDownMulti":[{"name":"NextGenTicketsSQQDropDownMulti","htmlVarName1":"numAdults","xmlPointer1":"TicketsPartyMixAdults","targetSecond":false,"htmlVarName2":"numChildren","xmlPointer2":"TicketsPartyMix"},{"name":"NextGenCountrySelectionSQQDropDownMulti","htmlVarName1":"CountryList","xmlPointer1":"CountryListTickets","targetSecond":true,"htmlVarName2":"CountryTarget"}],"SQQDropDown":[{"name":"NextGenNumDaysSQQDropDown","isRequired":false,"htmlObjectName":"NumberOfDays","xmlPointer":"NumberOfDays"}]}]}]},"OptInfo":{},"Groups":{"CountryListTickets":[{l:"United States",d:"USA|USStates"},{l:"Argentina",d:"ARG|"},{l:"Australia",d:"AUS|"},{l:"Austria",d:"AUT|"},{l:"Belgium",d:"BEL|"},{l:"Bermuda",d:"BMU|"},{l:"Brazil",d:"BRA|"},{l:"Canada",d:"CAN|"},{l:"Chile",d:"CHL|"},{l:"Columbia",d:"COL|"},{l:"Denmark",d:"DNK|"},{l:"Dominican Republic",d:"DOM|"},{l:"Ecuador",d:"ECU|"},{l:"Finland",d:"FIN|"},{l:"France",d:"FRA|"},{l:"Germany",d:"DEU|"},{l:"Greece",d:"GRC|"},{l:"Guatemala",d:"GTM|"},{l:"Homg Kong",d:"KON|"},{l:"Iceland",d:"ISL|"},{l:"India",d:"IND|"},{l:"Israel",d:"ISR|"},{l:"Italy",d:"ITA|"},{l:"Japan",d:"JPN|"},{l:"Kuwait",d:"KWT|"},{l:"Liechtenstein",d:"LIE|"},{l:"Luxemborg",d:"LUX|"},{l:"Malaysia",d:"MYS|"},{l:"Mexico",d:"MEX|"},{l:"Netherlands",d:"NLD|"},{l:"New Zealand",d:"NZL|"},{l:"Nicaragua",d:"NIC|"},{l:"Norway",d:"NOR|"},{l:"Panama",d:"PAN|"},{l:"Paraguay",d:"PRY|"},{l:"Peru",d:"PER|"},{l:"Philippines",d:"PHL|"},{l:"Portugal",d:"PRT|"},{l:"Puerto Rico",d:"PRI|"},{l:"Singapore",d:"SGP|"},{l:"South Africe",d:"ZAF|"},{l:"Spain",d:"ESP|"},{l:"Sweden",d:"SWE|"},{l:"Switzerland",d:"CHE|"},{l:"Thailand",d:"THA|"},{l:"United Arab Emirates",d:"ARE|"},{l:"United Kingdom",d:"GBR|"},{l:"Uruguay",d:"URY|"},{l:"Venezuela",d:"VEN|"}],"WDWResortTypes":[{l:"No Preference",d:"null|"},{l:"Value",d:"VALUE|"},{l:"Moderate",d:"MOD|"},{l:"Deluxe",d:"DLX|"},{l:"Deluxe Villas",d:"DVC|"},{l:"Campgrounds",d:"CAB|"},{l:"I know the Resort I want",d:"null|WDWMYWResorts"}],"WDWRoomOnlyResorts":[{l:"No Preference"},{l:"*** Disney\'s Value Resorts ***",d:"VALUE"},{l:"Disney\'s All-Star Movies Resort",d:"1E"},{l:"Disney\'s All-Star Music Resort",d:"1A"},{l:"Disney\'s All-Star Sports Resort",d:"1S"},{l:"Disney\'s Pop Century Resort",d:"1G"},{l:"*** Disney\'s Moderate Resorts ***",d:"MOD"},{l:"Disney\'s Caribbean Beach Resort",d:"1R"},{l:"Disney\'s Coronado Springs Resort",d:"1N"},{l:"Disney\'s Port Orleans Resort - French Quarter",d:"1O"},{l:"Disney\'s Port Orleans Resort - Riverside",d:"1L"},{l:"The Cabins at Disney\'s Fort Wilderness",d:"1FW"},{l:"*** Disney\'s Deluxe Resorts ***",d:"DLX"},{l:"Disney\'s Animal Kingdom Lodge",d:"1Q"},{l:"Disney\'s Beach Club Resort",d:"1W"},{l:"Disney\'s BoardWalk Inn",d:"1I"},{l:"Disney\'s Contemporary Resort",d:"1C"},{l:"Disney\'s Grand Floridian Resort &amp; Spa",d:"1B"},{l:"Disney\'s Polynesian Resort",d:"1P"},{l:"Disney\'s Wilderness Lodge",d:"1J"},{l:"Disney\'s Yacht Club Resort",d:"1Y"},{l:"*** Disney\'s Deluxe Villa Resorts ***",d:"DVC"},{l:"Disney\'s BoardWalk Villas",d:"1Z"},{l:"Disney\'s Old Key West Resort",d:"1K"},{l:"The Villas at Disney\'s Wilderness Lodge",d:"1X"},{l:"Disney\'s Beach Club Villas",d:"1D"},{l:"Disney\'s Saratoga Springs Resort &amp; Spa",d:"11"},{l:"Bay Lake Tower at Disney\'s Contemporary Resort",d:"14"},{l:"Disney\'s Animal Kingdom Villas - Jambo House",d:"12"},{l:"Disney\'s Animal Kingdom Villas - Kidani Village",d:"13"},{l:"*** Campground ***",d:"CAB"},{l:"Disney\'s Fort Wilderness Campsites",d:"1F"}],"USStates":[{l:"State of Residence"},{l:"Alabama",d:"AL"},{l:"Alaska",d:"AK"},{l:"Arizona",d:"AZ"},{l:"Arkansas",d:"AR"},{l:"California",d:"CA"},{l:"Colorado",d:"CO"},{l:"Connecticut",d:"CT"},{l:"Delaware",d:"DE"},{l:"District Of Columbia",d:"DC"},{l:"Florida",d:"FL"},{l:"Georgia",d:"GA"},{l:"Hawaii",d:"HI"},{l:"Idaho",d:"ID"},{l:"Illinois",d:"IL"},{l:"Indiana",d:"IN"},{l:"Iowa",d:"IA"},{l:"Kansas",d:"KS"},{l:"Kentucky",d:"KY"},{l:"Louisiana",d:"LA"},{l:"Maine",d:"ME"},{l:"Maryland",d:"MD"},{l:"Massachusetts",d:"MA"},{l:"Michigan",d:"MI"},{l:"Minnesota",d:"MN"},{l:"Mississippi",d:"MS"},{l:"Missouri",d:"MO"},{l:"Montana",d:"MT"},{l:"Nebraska",d:"NE"},{l:"Nevada",d:"NV"},{l:"New Hampshire",d:"NH"},{l:"New Jersey",d:"NJ"},{l:"New Mexico",d:"NM"},{l:"New York",d:"NY"},{l:"North Carolina",d:"NC"},{l:"North Dakota",d:"ND"},{l:"Ohio",d:"OH"},{l:"Oklahoma",d:"OK"},{l:"Oregon",d:"OR"},{l:"Pennsylvania",d:"PA"},{l:"Rhode Island",d:"RI"},{l:"South Carolina",d:"SC"},{l:"South Dakota",d:"SD"},{l:"Tennessee",d:"TN"},{l:"Texas",d:"TX"},{l:"Utah",d:"UT"},{l:"Vermont",d:"VT"},{l:"Virginia",d:"VA"},{l:"Washington",d:"WA"},{l:"West Virginia",d:"WV"},{l:"Wisconsin",d:"WI"},{l:"Wyoming",d:"WY"}],"numAdults":[{l:"1",d:"1"},{l:"2",d:"2"},{l:"3",d:"3"},{l:"4",d:"4"},{l:"5",d:"5"},{l:"6",d:"6"}],"WDWPackageResorts":[{l:"No Preference"},{l:"*** Disney\'s Deluxe Resorts ***",d:"DLX"},{l:"Disney\'s Animal Kingdom Lodge",d:"1Q"},{l:"Disney\'s Beach Club Resort",d:"1W"},{l:"Disney\'s BoardWalk Inn",d:"1I"},{l:"Disney\'s Contemporary Resort",d:"1C"},{l:"Disney\'s Grand Floridian Resort &amp; Spa",d:"1B"},{l:"Disney\'s Polynesian Resort",d:"1P"},{l:"Disney\'s Wilderness Lodge",d:"1J"},{l:"Disney\'s Yacht Club Resort",d:"1Y"},{l:"*** Disney\'s Deluxe Villa Resorts ***",d:"DVC"},{l:"Disney\'s BoardWalk Villas",d:"1Z"},{l:"Disney\'s Old Key West Resort",d:"1K"},{l:"The Villas at Disney\'s Wilderness Lodge",d:"1X"},{l:"Disney\'s Beach Club Villas",d:"1D"},{l:"Disney\'s Saratoga Springs Resort &amp; Spa",d:"11"},{l:"Bay Lake Tower at Disney\'s Contemporary Resort",d:"14"},{l:"Disney\'s Animal Kingdom Villas - Jambo House",d:"12"},{l:"Disney\'s Animal Kingdom Villas - Kidani Village",d:"13"},{l:"*** Disney\'s Moderate Resorts ***",d:"MOD"},{l:"Disney\'s Caribbean Beach Resort",d:"1R"},{l:"Disney\'s Coronado Springs Resort",d:"1N"},{l:"Disney\'s Port Orleans Resort - French Quarter",d:"1O"},{l:"Disney\'s Port Orleans Resort - Riverside",d:"1L"},{l:"The Cabins at Disney\'s Fort Wilderness",d:"1FW"},{l:"*** Disney\'s Value Resorts ***",d:"VALUE"},{l:"Disney\'s All-Star Movies Resort",d:"1E"},{l:"Disney\'s All-Star Music Resort",d:"1A"},{l:"Disney\'s All-Star Sports Resort",d:"1S"},{l:"Disney\'s Pop Century Resort",d:"1G"},{l:"*** Campground ***",d:"CAB"},{l:"The Campsites at Disney\'s Fort Wilderness Resort",d:"1F"},{l:"*** Other Deluxe Walt Disney World Resort Hotels ***",d:"ODLX"},{l:"Walt Disney World Dolphin Resort",d:"DOL"},{l:"Walt Disney World Swan Resort",d:"SWN"}],"WDWPackagePlanTypes":[{l:"Magic Your Way Package",d:"RT"},{l:"Magic Your Way Plus Quick-Service Dining",d:"RTQM"},{l:"Magic Your Way Plus Dining",d:"RTM"},{l:"Magic Your Way Plus Dining &amp; Wine",d:"RTMW"},{l:"Magic Your Way Plus Deluxe Dining",d:"RTDM"},{l:"Magic Your Way Plus Deluxe Dining &amp; Wine",d:"RTDMW"},{l:"Magic Your Way Premium Package",d:"RTMR"},{l:"Magic Your Way Premium Package &amp; Wine",d:"RTMRW"},{l:"Magic Your Way Platinum Package",d:"RTMRS"},{l:"Magic Your Way Platinum Package &amp; Wine",d:"RTMRSW"},{l:"Swan and Dolphin Hotel Package",d:"HTL"}],"WDWMYWResorts":[{l:"*** Disney\'s Value Resorts ***",d:"VALUE"},{l:"Disney\'s All-Star Movies Resort",d:"1E"},{l:"Disney\'s All-Star Music Resort",d:"1A"},{l:"Disney\'s All-Star Sports Resort",d:"1S"},{l:"Disney\'s Pop Century Resort",d:"1G"},{l:"*** Disney\'s Moderate Resorts ***",d:"MOD"},{l:"Disney\'s Caribbean Beach Resort",d:"1R"},{l:"Disney\'s Coronado Springs Resort",d:"1N"},{l:"Disney\'s Port Orleans - Riverside",d:"1L"},{l:"Disney\'s Port Orleans - French Quarter",d:"1O"},{l:"The Cabins at Disney\'s Fort Wilderness",d:"1FW"},{l:"*** Disney\'s Deluxe Resorts ***",d:"DLX"},{l:"Disney\'s Animal Kingdom Lodge",d:"1Q"},{l:"Disney\'s Beach Club Resort",d:"1W"},{l:"Disney\'s Boardwalk Inn",d:"1I"},{l:"Disney\'s Contemporary Resort",d:"1C"},{l:"Disney\'s Grand Floridian Resort &amp; Spa",d:"1B"},{l:"Disney\'s Polynesian Resort",d:"1P"},{l:"Disney\'s Wilderness Lodge",d:"1J"},{l:"Disney\'s Yacht Club Resort",d:"1Y"},{l:"*** Disney Deluxe Villa Resorts ***",d:"DVC"},{l:"Disney\'s Saratoga Springs Resort &amp; Spa",d:"11"},{l:"Disney\'s Beach Club Villas",d:"1D"},{l:"Disney\'s Boardwalk Villas",d:"1Z"},{l:"Disney\'s Old Key West Resort",d:"1K"},{l:"The Villas at Disney\'s Wilderness Lodge",d:"1X"},{l:"Bay Lake Tower at Disney\'s Contemporary Resort",d:"1D"},{l:"Disney\'s Animal Kingdom Villas - Jambo House",d:"12"},{l:"Disney\'s Animal Kingdom Villas - Kidani Village",d:"13"},{l:"*** Campground ***",d:"CAB"},{l:"Disney\'s Fort Wilderness Campsites",d:"1F"}],"TicketsPartyMix":[{l:"0",d:"0"},{l:"1",d:"1"},{l:"2",d:"2"},{l:"3",d:"3"},{l:"4",d:"4"},{l:"5",d:"5"},{l:"6",d:"6"}],"WDWResorts":[{l:"*** Disney\'s Deluxe Resorts ***",d:"DLX"},{l:"Disney\'s Animal Kingdom Lodge",d:"1Q"},{l:"Disney\'s Beach Club Resort",d:"1W"},{l:"Disney\'s Boardwalk Inn",d:"1I"},{l:"Disney\'s Contemporary Resort",d:"1C"},{l:"Disney\'s Grand Floridian Resort &amp; Spa",d:"1B"},{l:"Disney\'s Polynesian Resort",d:"1P"},{l:"Disney\'s Wilderness Lodge",d:"1J"},{l:"Disney\'s Yacht Club Resort",d:"1Y"},{l:"*** Disney\'s Deluxe Villa Resorts ***",d:"DVC"},{l:"Disney\'s Boardwalk Villas",d:"1Z"},{l:"Disney\'s Old Key West Resort",d:"1K"},{l:"The Villas at Disney\'s Wilderness Lodge",d:"1X"},{l:"Disney\'s Beach Club Villas",d:"1D"},{l:"Disney\'s Saratoga Springs Resort &amp; Spa",d:"11"},{l:"Bay Lake Tower at Disney\'s Contemporary Resort",d:"14"},{l:"Disney\'s Animal Kingdom Villas - Jambo House",d:"12"},{l:"Disney\'s Animal Kingdom Villas - Kidani Village",d:"13"},{l:"*** Disney\'s Moderate Resorts ***",d:"MOD"},{l:"Disney\'s Caribbean Beach Resort",d:"1R"},{l:"Disney\'s Coronado Springs Resort",d:"1N"},{l:"Disney\'s Port Orleans - Riverside",d:"1L"},{l:"Disney\'s Port Orleans - French Quarter",d:"1O"},{l:"The Cabins at Disney\'s Fort Wilderness",d:"1FW"},{l:"*** Disney\'s Value Resorts ***",d:"VALUE"},{l:"Disney\'s All-Star Movies Resort",d:"1E"},{l:"Disney\'s All-Star Music Resort",d:"1A"},{l:"Disney\'s All-Star Sports Resort",d:"1S"},{l:"Disney\'s Pop Century Resort",d:"1G"},{l:"*** Campground ***",d:"CAB"},{l:"Disney\'s Fort Wilderness Campsites",d:"1F"},{l:"*** Other Deluxe Walt Disney World Resort Hotels ***",d:"ODLX"},{l:"Walt Disney World Dolphin",d:"DOL"},{l:"Walt Disney World Swan",d:"SWN"}],"NumberOfDays":[{l:"Length of Stay",d:"ddNum"},{l:"1",d:"1"},{l:"2",d:"2"},{l:"3",d:"3"},{l:"4",d:"4"},{l:"5",d:"5"},{l:"6",d:"6"},{l:"7",d:"7"},{l:"8",d:"8"},{l:"9",d:"9"},{l:"10",d:"10"}],"NextGenNumberOfDays":[{l:"Number of Days",d:"ddNum"},{l:"1",d:"1"},{l:"2",d:"2"},{l:"3",d:"3"},{l:"4",d:"4"},{l:"5",d:"5"},{l:"6",d:"6"},{l:"7",d:"7"},{l:"8",d:"8"},{l:"9",d:"9"},{l:"10",d:"10"}],"TicketsPartyMixAdults":[{l:"1",d:"1"},{l:"2",d:"2"},{l:"3",d:"3"},{l:"4",d:"4"},{l:"5",d:"5"},{l:"6",d:"6"}]}})' );
	} catch ( e ) {
		return this.displayError( 'An error has occurred while loading the Disney Quick Quote business rules.' );
	}
	
	return true;
};

// parse aspects of our feed to store in memory the exact portions we need
// @param objRequest object - ajax returned object reference
DisneyQuickQuote.prototype.processBusinessRules = function() {
	var intChild = 0;
	
	// this loops through each option types in our config and processes them individually
	intChild = ( this.arrSupport.length - 1 );
	do {
		this.processGroup( this.arrSupport[ intChild ] );
	} while ( intChild-- );
	
	return true;
};

DisneyQuickQuote.prototype.createCalendarConfig = function( strId, dtRangeStart, dtRangeEnd ) {
	var objConfig = {
		target: document.body,
		dateRangeStart: new Date( dtRangeStart ),
		dateRangeEnd: new Date( dtRangeEnd ),
		showInput: true,
		monthLabels: this.objData.Prop.monthLabels.join( ',' )
	};
	
	return objConfig;
};

// process all of a specific SQQComponent
// @param strTagName string - string of what SQQComponent will be processed
DisneyQuickQuote.prototype.processGroup = function( strTagName ) {
	var intCount = 0;
	var intBU = 0;
	var intPO = 0;
	var strName = null;
	var strParentName = null;
	var nodeElement = null;
	var that = this;
	
	// we can use the assumption that if the SQQComponent exists in the product option, its length is not 0
	// our JSON data feed ensures this
	switch ( strTagName ) {
		case 'SQQTravelDates':
			var bSingleTextField = false;
			var bUseDropDown = false;
			var dtEnd;
			var dtStart;
			var dtToday;
			var dtTravel;
			var intChild = 0;
			var intCal1 = null;
			var intCal2 = null;
			var intMinBookTime = 1;
			var intTravelStartDate = 0;
			var intTravelStartMonth = 0;
			var intTravelStartYear = 0;
			var intDisplayStartDate = 0;
			var intDisplayStartMonth = 0;
			var intDisplayStartYear = 0;
			var intDisplayEndYear = 0;
			var intStartDaysFromToday = 0;
			var intDisplayDateRange = 0;
			var intUpdateAfter = -1;
			var nodeArrivalMonth = null;
			var nodeArrivalDay = null;
			var nodeArrivalYear = null;
			var nodeArrivalDate = null;
			var nodeCalendarBtn1 = null;
			var nodeCalendarBtn2 = null;
			var nodeDepartureMonth = null;
			var nodeDepartureDay = null;
			var nodeDepartureYear = null;
			var nodeDepartureDate = null;
			var nodeOption = null;
			var objGroup;
			var objData;
			
			// prep our calendar mouse click event
			this.addOpenCalendarMouseCheckEvent();
			
			// if our json data does not month labels, set the var to ''
			if ( !this.objData.Prop.monthLabels && typeof this.objData.Prop.monthLabels.length != 'undefined' ) {
				this.objData.Prop.monthLabels = Array( '' );
			}
			
			// loop through all sqqbusinessunits
			intBU = ( this.objData.Prop.BU.length - 1 );
			do {
				// loop through all sqqproductoptions
				intPO = ( this.objData.Prop.BU[ intBU ].PO.length - 1 );
				do {
					if ( typeof( this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQTravelDates ) != 'undefined' ) {
						dtToday = new Date();
						dtToday.setToCalendarDate();
						bUseDropDown = false;
						intUpdateAfter = -1;
						
						strName = this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQTravelDates.name;
						bSingleTextField = this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQTravelDates.singleTextField;
						intMinBookTime = this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQTravelDates.minBookTime;
						intTravelStartDate = this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQTravelDates.travelStartDate;
						intTravelStartMonth = this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQTravelDates.travelStartMonth;
						intTravelStartYear = this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQTravelDates.travelStartYear;
						intDisplayStartDate = this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQTravelDates.displayStartDate;
						intDisplayStartMonth = this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQTravelDates.displayStartMonth;
						intDisplayStartYear = this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQTravelDates.displayStartYear;
						intDisplayEndYear = this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQTravelDates.displayEndYear;
						intStartDaysFromToday = this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQTravelDates.startDaysFromToday;
						intDisplayDateRange = this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQTravelDates.displayDateRange;
						
						strParentName = this.objData.Prop.BU[ intBU ].value + '_' + this.objData.Prop.BU[ intBU ].PO[ intPO ].name;
						nodeCalendarBtn1 = document.getElementById( strParentName + '_' + strName + '_arrivalCalendarBtn' );
						nodeCalendarBtn2 = document.getElementById( strParentName + '_' + strName + '_departureCalendarBtn' );
						
						// we only need specific elements if single text field is true
						if ( bSingleTextField ) {
							nodeArrivalDate = document.getElementById( strParentName + '_' + strName + '_arrivalDate' );
							nodeDepartureDate = document.getElementById( strParentName + '_' + strName + '_departureDate' );
						} else {
							nodeArrivalMonth = document.getElementById( strParentName + '_' + strName + '_arrivalMonth' );
							nodeArrivalDay = document.getElementById( strParentName + '_' + strName + '_arrivalDay' );
							nodeArrivalYear = document.getElementById( strParentName + '_' + strName + '_arrivalYear' );
							nodeDepartureMonth = document.getElementById( strParentName + '_' + strName + '_departureMonth' );
							nodeDepartureDay = document.getElementById( strParentName + '_' + strName + '_departureDay' );
							nodeDepartureYear = document.getElementById( strParentName + '_' + strName + '_departureYear' );
						}
							
						// all combo boxes and calendar buttons must exist
						if ( nodeCalendarBtn1 && nodeCalendarBtn2 && ( ( !bSingleTextField && nodeArrivalMonth && nodeArrivalDay && nodeArrivalYear && nodeDepartureMonth && nodeDepartureDay && nodeDepartureYear ) || ( bSingleTextField && nodeArrivalDate && nodeDepartureDate ) ) ) {
							// check our opt info data to preset our dates (important!)
							if ( typeof( this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDown ) != 'undefined' && typeof( this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDown.length ) != 'undefined' ) {
								intCount = ( this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDown.length - 1 );
								if ( intCount > -1 ) {
									do {
										// long if statement, checks dependency to make sure it's defined and set, then checks our group data from the xmlPointer
										if ( typeof( this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDown[ intCount ].dependency ) != 'undefined' && this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDown[ intCount ].dependency && typeof( this.objData.Groups[ this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDown[ intCount ].xmlPointer ] ) != 'undefined' ) {
											// make sure our group exists and has data
											objGroup = this.objData.Groups[ this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDown[ intCount ].xmlPointer ][ document.getElementById( strParentName + '_' + this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDown[ intCount ].xmlPointer ).selectedIndex ];
											if ( !objGroup || objGroup.length < 1 ) {
												continue;
											}
											
											// if our opt info code doesn't exist, end it
											if ( typeof( objGroup.t ) == 'undefined' || !this.objData.OptInfo[ objGroup.t ] ) {
												continue;
											}
											
											// for some reason we have a few items without a day/date, so lets put it to 1, then change it
											dtStart = new Date( dtToday );
											dtStart.setFullYear( this.objData.OptInfo[ objGroup.t ].travelStartYear, ( ( this.objData.OptInfo[ objGroup.t ].travelStartMonth * 1 ) - 1 ), 1 );
											if ( typeof( this.objData.OptInfo[ objGroup.t ].travelStartDate ) != 'undefined' && this.objData.OptInfo[ objGroup.t ].travelStartDate !== null ) {
												dtStart.setDate( this.objData.OptInfo[ objGroup.t ].travelStartDate );
											}
											
											// overwrite the travel info
											intTravelStartDate = dtStart.getDate();
											intTravelStartMonth = ( dtStart.getMonth() + 1 );
											intTravelStartYear = dtStart.getFullYear();
											bUseDropDown = true;
											
											// update our travel dates
											this.updateTravelDates( strParentName + '_' + strName + '_arrival', bSingleTextField, ( dtStart.getMonth() + 1 ), dtStart.getDate(), dtStart.getFullYear() );
											
											if (this.objData.OptInfo[ objGroup.t ].minBookTime && intDisplayDateRange > this.objData.OptInfo[ objGroup.t ].minBookTime) {
												dtStart.setDate( dtStart.getDate() + intDisplayDateRange );
											} else {
												dtStart.setDate( dtStart.getDate() + this.objData.OptInfo[ objGroup.t ].minBookTime );
											}
											
											this.updateTravelDates( strParentName + '_' + strName + '_departure', bSingleTextField, ( dtStart.getMonth() + 1 ), dtStart.getDate(), dtStart.getFullYear() );
											// set drop down # to update drop down selection after events
											intUpdateAfter = intCount;
											break;
										}
									} while ( intCount-- );
								}
							}
							
							// javascript users can click the calendar button
							nodeCalendarBtn1.style.display = 'block';
							nodeCalendarBtn2.style.display = 'block';
							
							// ie fix for putting the calendar in the wrong position if the qq is too small
							if ( document.all ) {
								if ( this.arrAttributes.qqWidth < 260 ) {
									nodeCalendarBtn1.parentNode.style.width = '100%';
									nodeCalendarBtn2.parentNode.style.width = '100%';
								}
							}
							
							// we can go ahead and create our dates now
							dtStart = new Date( dtToday );
							dtEnd = new Date( dtToday );
							
							// if a travel date is specified from our data, see if it's in the future
							// we need a date range start
							if ( intTravelStartYear > 0 && intTravelStartMonth > 0 && intTravelStartDate > 0 ) {
								dtTravel = new Date( dtStart );
								dtTravel.setFullYear( intTravelStartYear, ( intTravelStartMonth - 1 ), intTravelStartDate );
								
								// if the travel date is after than today's date, use that instead
								if ( dtStart.compare( dtTravel ) == -1 ) {
									dtStart = new Date( dtTravel );
								} else if ( !bUseDropDown ) { // travel date is in the past, today + 1
									dtStart.setDate( ( dtStart.getDate() * 1 ) + 1 );
								}
								
								dtTravel = undefined;
							} else if ( !bUseDropDown ) { // no travel date specified, today + 1
								dtStart.setDate( ( dtStart.getDate() * 1 ) + 1 );
							}
							
							// if not using a drop down, lets update our dates instead of relying on TEA
							if ( !bUseDropDown ) {
								dtTravel = new Date( dtStart );
								
								if ( intStartDaysFromToday > 0 ) {
									dtTravel.setDate( ( dtTravel.getDate() * 1 ) + intStartDaysFromToday );
								}
								
								this.updateTravelDates( strParentName + '_' + strName + '_arrival', bSingleTextField, ( dtTravel.getMonth() + 1 ), dtTravel.getDate(), dtTravel.getFullYear() );
								
								if ( intDisplayDateRange > 0 ) {
									dtTravel.setDate( ( dtTravel.getDate() * 1 ) + intDisplayDateRange );
								}
								
								this.updateTravelDates( strParentName + '_' + strName + '_departure', bSingleTextField, ( dtTravel.getMonth() + 1 ), dtTravel.getDate(), dtTravel.getFullYear() );
							}
							
							// by default date range is going to end of (current + 2)/display years, minus the minimum book days
							if ( intDisplayEndYear ) {
								dtEnd.setFullYear( intDisplayEndYear, 11, ( 31 - intMinBookTime ) );
							} else {
								dtEnd.setFullYear( ( dtStart.getFullYear() + 2 ), 11, ( 31 - intMinBookTime ) );
							}
							
							// 2 calendar id's
							intCal1 = ( this.arrAttributes.qqCalendars.length );
							intCal2 = ( intCal1 + 1 );
							
							// set our ints
							this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQTravelDates.arrival = intCal1;
							this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQTravelDates.departure = intCal2;
							
							this.arrAttributes.qqCalendars[ intCal1 ] = {};
							this.arrAttributes.qqCalendars[ intCal2 ] = {};
							
							// we instaniate a new object and pass it to our event setter so we can hold these values instead of by ref
							// store our data we need for the calendars to work properly
							objData = {
								minBookTime: intMinBookTime,
								displayDateRange: intDisplayDateRange,
								isArrival: true,
								departure: intCal2,
								parentName: strParentName,
								name: strParentName + '_' + strName + '_arrival',
								config: this.createCalendarConfig( strParentName + '_' + strName + '_arrivalCalendar', dtStart, dtEnd ),
								singleTextField: bSingleTextField
							};
							
							this.addDisplayCalendarEvent( nodeCalendarBtn1, objData, intCal1, true );
							
							if ( bSingleTextField ) {
								this.addDisplayCalendarEvent( nodeArrivalDate, null, intCal1, false );
							}
							
							// our ending date range differs, add the min book time to start and end
							dtStart.setDate( ( ( dtStart.getDate() * 1 ) + intMinBookTime ) );
							dtEnd.setDate( ( ( dtEnd.getDate() * 1 ) + intMinBookTime ) );
							
							objData = {
								minBookTime: intMinBookTime,
								isArrival: false,
								arrival: intCal1,
								parentName: strParentName,
								name: strParentName + '_' + strName + '_departure',
								config: this.createCalendarConfig( strParentName + '_' + strName + '_departureCalendar', dtStart, dtEnd ),
								singleTextField: bSingleTextField
							};
							
							this.addDisplayCalendarEvent( nodeCalendarBtn2, objData, intCal2, true );
							
							if ( bSingleTextField ) {
								this.addDisplayCalendarEvent( nodeDepartureDate, null, intCal2, false );
							}
							
							// our travel events covers date changes and selection handling for calendar
							this.addTravelEvents( this.arrAttributes.qqCalendars[ intCal1 ], this.arrAttributes.qqCalendars[ intCal2 ] );
							
							if ( intUpdateAfter > -1 ) {
								this.updateDropDownSelection( this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDown[ intUpdateAfter ].xmlPointer, strParentName, intUpdateAfter, 'initTravel', intBU, intPO );
							}
						}
					}
				} while ( intPO-- );
			} while ( intBU-- );
			
			break;
		case 'SQQPartyMix':
			var nodeChildren = null;
			var nodeContainer = null;
			var nodeDisclaimer = null;
			var nodeLink = null;
			var nodeAlert = null;
			
			// loop through all sqqbusinessunits
			intBU = ( this.objData.Prop.BU.length - 1 );
			do {
				// loop through all sqqproductoptions
				intPO = ( this.objData.Prop.BU[ intBU ].PO.length - 1 );
				do {
					if ( typeof( this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQPartyMix ) != 'undefined' ) {
						strName = this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQPartyMix.name;
						strParentName = this.objData.Prop.BU[ intBU ].value + '_' + this.objData.Prop.BU[ intBU ].PO[ intPO ].name;
						nodeChildren = document.getElementById( strParentName + '_' + strName + '_numChildren' );
						nodeContainer = document.getElementById( strParentName + '_' + strName + '_childContainer' );
						nodeDisclaimer = document.getElementById( strParentName + '_' + strName + '_disclaimer' );
						nodeLink = document.getElementById( strParentName + '_' + strName + '_disclaimerLink' );
						nodeAlert = document.getElementById( strParentName + '_' + strName + '_disclaimerAlert' );
						this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQPartyMix.currentChildren = -1;
						
						// if the children and container exist, add our events and go ahead and default our children box
						if ( nodeChildren && nodeContainer ) {
							this.addPartyMixEvent( strParentName, strName );
							
							// we execute this on init due to non-vendor html inclusion
							// meaning browsers could default a # if you refreshed after a selection
							this.updateNumChildren( strParentName, strName, 'init', intBU, intPO );
						}
						
						// this is separated due to disclaimers being optional
						if ( nodeDisclaimer && nodeLink && nodeAlert ) {
							// replace our href for the link, hide the default alert for non-JS users, and compact it with a link
							nodeLink.href = 'javascript:void(0);';
							nodeDisclaimer.style.display = 'block';
							nodeAlert.style.display = 'none';
							
							// child age disclaimer event for the link to change into our other layer (which used to cover the entire qq in a pretty way)
							this.addChildAgeDisclaimerEvent( strParentName + '_' + strName + '_disclaimer' );
						}
					}
				} while ( intPO-- );
			} while ( intBU-- );
			
			break;
		case 'SQQDropDownMulti':
			var strHTMLVarName1 = null;
			var strHTMLVarName2 = null;
			var bTargetSecond = null;
			nodeElement = null;
			var nodeSelect1 = null;
			var nodeSelect2 = null;
			
			// loop through all sqqbusinessunits
			intBU = ( this.objData.Prop.BU.length - 1 );
			do {
				// loop through all sqqproductoptions
				intPO = ( this.objData.Prop.BU[ intBU ].PO.length - 1 );
				do {
					if ( typeof( this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDownMulti ) != 'undefined' ) {
						intCount = ( this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDownMulti.length - 1 );
						do {
							bTargetSecond = this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDownMulti[ intCount ].targetSecond;
							
							// we only need multi drop downs that have business rules (where #1 effects #2)
							if ( bTargetSecond ) {
								strName = this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDownMulti[ intCount ].name;
								strParentName = this.objData.Prop.BU[ intBU ].value + '_' + this.objData.Prop.BU[ intBU ].PO[ intPO ].name;
								strHTMLVarName1 = this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDownMulti[ intCount ].htmlVarName1;
								strHTMLVarName2 = this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDownMulti[ intCount ].htmlVarName2;
								nodeElement = document.getElementById( strParentName + '_' + strName );
								nodeSelect1 = document.getElementById( strParentName + '_' + strName + '_' + strHTMLVarName1 );
								nodeSelect2 = document.getElementById( strParentName + '_' + strName + '_' + strHTMLVarName2 );
								
								if ( typeof( this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDownMulti[ intCount ].xmlPointer2 ) == 'undefined' ) {
									this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDownMulti[ intCount ].xmlPointer2 = '';
								}
								
								if ( nodeElement && nodeSelect1 && nodeSelect2 ) {
									// add our event to select1 to change select2
									this.addDropDownMultiEvent( nodeSelect1, intCount, strParentName + '_' + strName + '_' + strHTMLVarName1, strParentName + '_' + strName + '_' + strHTMLVarName2 );
									
									// initialize drop down change, this will set our internal var to our current select1/select2
									this.updateDropDownMultiSelection( intCount, strParentName + '_' + strName + '_' + strHTMLVarName1, strParentName + '_' + strName + '_' + strHTMLVarName2, 'init', intBU, intPO );
								}
							}
						} while ( intCount-- );
					}
				} while ( intPO-- );
			} while ( intBU-- );
			
			break;
		case 'SQQDropDown':
			var intChildCount = 0;
			
			// loop through all sqqbusinessunits
			intBU = ( this.objData.Prop.BU.length - 1 );
			do {
				// loop through all sqqproductoptions
				intPO = ( this.objData.Prop.BU[ intBU ].PO.length - 1 );
				do {
					// if we have any SQQDropDown's loop through them
					if ( typeof( this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDown ) != 'undefined' ) {
						intCount = ( this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDown.length - 1 );
						do {
							strName = this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDown[ intCount ].xmlPointer;
							strParentName = this.objData.Prop.BU[ intBU ].value + '_' + this.objData.Prop.BU[ intBU ].PO[ intPO ].name;
							nodeElement = document.getElementById( strParentName + '_' + strName );
							
							if ( nodeElement ) {
								if ( typeof( this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDown[ intCount ].dependency ) != 'undefined' ) {
									// loop through sqqdropdown's for one's XMLPointer to match the dependency
									intChildCount = ( this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDown.length - 1 );
									
									do {
										if ( typeof( this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDown[ intChildCount ].htmlObjectName ) != 'undefined' && this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDown[ intCount ].dependency == this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDown[ intChildCount ].htmlObjectName ) {
        										// add our event to update our dependency, etc. if we found it
											this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDown[ intCount ].child = intChildCount;
											this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDown[ intChildCount ].targetData = null;
											this.addDropDownEvent( nodeElement, strName, strParentName, intCount );
											
											if ( strName == 'DCLCruises' ) {
												this.updateDropDownSelection( strName, strParentName, intCount, 'init', intBU, intPO );
											}
											
											break;
										}
									} while ( intChildCount-- );
								}
							}
						} while ( intCount-- );
					}
				} while ( intPO-- );
			} while ( intBU-- );
			
			break;
		case 'SQQTextBox':
			var nodeOverlay = null;
			
			// loop through all sqqbusinessunits
			intBU = ( this.objData.Prop.BU.length - 1 );
			do {
				// loop through all sqqproductoptions
				intPO = ( this.objData.Prop.BU[ intBU ].PO.length - 1 );
				do {
					// if we have any SQQTextBox's loop through them
					if ( typeof( this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQTextBox ) != 'undefined' ) {
						intCount = ( this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQTextBox.length - 1 );
						do {
							strName = this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQTextBox[ intCount ].name;
							strParentName = this.objData.Prop.BU[ intBU ].value + '_' + this.objData.Prop.BU[ intBU ].PO[ intPO ].name;
							nodeElement = document.getElementById( strParentName + '_' + strName + '_Text' );
							nodeOverlay = document.getElementById( strParentName + '_' + strName + '_Overlay' );
							
							if ( nodeElement && nodeOverlay ) {
								if ( typeof( this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQTextBox[ intCount ].overlayLabel ) != 'undefined' ) {
									// this textbox has an overlay, add event to hide/display
									this.addTextBoxOverlayEvent( nodeElement, nodeOverlay, strName, strParentName );
								}
							}
						} while ( intCount-- );
					}
				} while ( intPO-- );
			} while ( intBU-- );
			
			break;
		case 'SQQGrouping':
			var nodeLabel = null;
			var nodeGroup = null;
			
			// loop through all sqqbusinessunits
			intBU = ( this.objData.Prop.BU.length - 1 );
			do {
				// loop through all sqqproductoptions
				intPO = ( this.objData.Prop.BU[ intBU ].PO.length - 1 );
				do {
					// if we have any SQQGroupings's loop through them
					if ( typeof( this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQGrouping ) != 'undefined' ) {
						intCount = ( this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQGrouping.length - 1 );
						do {
							strName = this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQGrouping[ intCount];
							strParentName = this.objData.Prop.BU[ intBU ].value + '_' + this.objData.Prop.BU[ intBU ].PO[ intPO ].name;
							nodeLabel = document.getElementById( strParentName + '_' + strName + '_Label' );
							nodeGroup = document.getElementById( strParentName + '_' + strName + '_Group' );
							
							// if the item has no label, then no points of adding event, cause you can't click anything
							// for a blank clickable item (like an image background), you should use a &nbsp;, then use CSS to stretch the object and this will pick it up like normal
							if ( nodeLabel && nodeGroup ) {
								// add our event to hide/display the group
								this.addGroupEvent( strParentName + '_' + strName );
							}
						} while ( intCount-- );
					}
				} while ( intPO-- );
			} while ( intBU-- );
			
			break;
		case 'SQQProductOption':
			var bChecked = false;
			nodeContainer = null;
			
			// loop through all sqqbusinessunits
			intBU = ( this.objData.Prop.BU.length - 1 );
			do {
				bChecked = false;
				strName = this.objData.Prop.BU[ intBU ].value;
				// loop through all sqqproductoptions
				intPO = ( this.objData.Prop.BU[ intBU ].PO.length - 1 );
				
				do {
					nodeElement = document.getElementById( strName + '_' + this.objData.Prop.BU[ intBU ].PO[ intPO ].name );
					nodeContainer = document.getElementById( strName + '_' + this.objData.Prop.BU[ intBU ].PO[ intPO ].name + '_Container' );
					
					if ( nodeElement || nodeContainer ) {
						// add event for when the radio button is checked
						this.addProductOptionsEvent( strName + '_' + this.objData.Prop.BU[ intBU ].PO[ intPO ].name, intPO );
						
						if ( nodeElement && nodeContainer ) {
							// if it came checked, display our form and save it
							// if the PO is > 0 then always hide if not checked, if the PO is 0 and an item is checked, hide it
							// otherwise leave it alone, because we're defaulting to it anyways
							if ( nodeElement.checked ) {
								bChecked = true;
								this.objData.Prop.BU[ intBU ].currentPO = intPO;
							} else if ( intPO > 0 || ( intPO === 0 && bChecked ) ) {
								nodeContainer.className = 'SQQProductOption hidden';
							}
						} else {
							bChecked = true;
							this.objData.Prop.BU[ intBU ].currentPO = intPO;
						}
					}
				} while ( intPO-- );
				
				// if no items came checked and we found our first product option, check it, display it, save it
				if ( !bChecked ) {
					// I was storing the name in a var, but the additional var checks, etc.
					// can't offer a good performance diff for sacrificing memory
					// only check if there's more than 1 -- meaning, if there actually is a radio button
					if ( this.objData.Prop.BU[ intBU ].PO.length > 1 ) {
						document.getElementById( strName + '_' + this.objData.Prop.BU[ intBU ].PO[ 0 ].name ).checked = true;
					}
					
					this.objData.Prop.BU[ intBU ].currentPO = 0;
				}
			} while ( intBU-- );
			
			break;
		case 'SQQBusinessUnit':
			var bSelected = false;
			
			// if we have multiple business units, below will return an object
			var nodeMulti = document.getElementById( 'SQQMultiBU' );
			
			// if our node is set, then add event to the combo box
			if ( typeof( nodeMulti ) != 'undefined' && nodeMulti !== null ) {
				this.addMultiBusinessUnitEvent();
				
				// loop through all sqqbusinessunits
				intBU = ( this.objData.Prop.BU.length - 1 );
				do {
					strName = this.objData.Prop.BU[ intBU ].value;
					nodeContainer = document.getElementById( strName + '_Container' );
					
					if ( nodeContainer ) {
						if ( nodeMulti.value == strName ) {
							bSelected = true;
							this.objData.Prop.currentBU = intBU;
						} else {
							nodeContainer.className = 'SQQBusinessUnit hidden';
						}
					}
				} while ( intBU-- );
				
				// if no item was selected, default to the first data
				if ( !bSelected ) {
					document.getElementById( this.objData.Prop.BU[ 0 ].value + '_Container' ).className = 'SQQBusinessUnit';
				}
			}
			
			// if no item was selected, default to the first data
			// this is also for non-multi BUs so we know what BU we're using wihout having to do multi checks
			if ( !bSelected ) {
				this.objData.Prop.currentBU = 0;
			}
			
			break;
		default:
			break;
	}
	
	return true;
};

// event adds
// handle events for multi business unit combo box
DisneyQuickQuote.prototype.addMultiBusinessUnitEvent = function() {
	var that = this;
	var nodeMulti = document.getElementById( 'SQQMultiBU' );
	
	this.addEvent( nodeMulti, 'change', function() { that.updateMultiBUSelection( 'change' ); }, false );
	this.addEvent( nodeMulti, 'keyup', function() { that.updateMultiBUSelection( 'keyup' ); }, false );
};

// handle events for product option radio buttons and submit button for form
// @param strElement string - element id for product option
// @param intPO integer - the index key of the BU where this PO is
DisneyQuickQuote.prototype.addProductOptionsEvent = function( strElement, intPO ) {
	var that = this;
	var nodeElement = document.getElementById( strElement );
	var nodeSubmit = document.getElementById( strElement + '_Submit' );
	
	// if there are multiple sqqproductoptions, we need to add event to radio button
	if ( nodeElement ) {
		// ie needs extra events since it won't fire "change" for key up and click events
		if ( document.all ) {
			// this is EXTREMELY ugly... but it was the ONLY way to get IE to cooperate.. so deal with it
			// the timeout call first corrects the behavior of the divs rendering BELOW the QQ (it actually looks exactly right if you're not hiding any other QQ)
			// the parent node is to correct the button location.. for some strange reason it couldn't show until you adjusted the height AFTER the 100ms
			// none of this works outside of the setTimeout, you have to give IE time to fix itself
			this.addEvent( nodeElement, 'click', function() {
				that.switchProductOptions( strElement, intPO, 'click' );
				setTimeout( function() {
					that.switchProductOptions( strElement, intPO, 'click' );
					document.getElementById( strElement + '_Submit' ).parentNode.style.height = '100%';
					document.getElementById( strElement + '_Submit' ).parentNode.style.height = 'auto';
				}, 1 );
			}, false );
			this.addEvent( nodeElement, 'keyup', function() { that.switchProductOptions( strElement, intPO, 'keyup' ); }, false );
		} else {
			// add event for radio switching
			this.addEvent( nodeElement, 'change', function() { that.switchProductOptions( strElement, intPO, 'change' ); }, false );
		}
	}
	
	// add event for submit button if it was found (it's optional)
	if ( nodeSubmit ) {
		this.addEvent( nodeSubmit, 'click', function() { that.submitProductOption( strElement, 'click' ); }, false );
	}
	
	return true;
};

// handle events for hiding/displaying grouping
// @param strName string - element id for sqqcomponent
DisneyQuickQuote.prototype.addGroupEvent = function( strName ) {
	var that = this;
	
	// add event to click, only 1, so I didn't want to make a var for the element
	this.addEvent( document.getElementById( strName + '_Label' ), 'click', function() { that.displayGroup( strName, 'click' ); }, false );
	
	if ( document.getElementById( strName + '_OpenedLabel') ) {
		this.addEvent( document.getElementById( strName + '_OpenedLabel' ), 'click', function() { that.displayGroup( strName, 'click' ); }, false );
	}
	
	return true;
};

// handle events for children count to display age container
// @param strParentName string - element id for parent element
// @param strName string - element id for sqqcomponent
DisneyQuickQuote.prototype.addPartyMixEvent = function( strParentName, strName ) {
	var that = this;
	var nodeChildren = document.getElementById( strParentName + '_' + strName + '_numChildren' );
	
	// combo boxes need change (all) and keyup (ie) events to update children age
	if ( document.all ) {
		// see the function: DisneyQuickQuote.prototype.addProductOptionsEvent for details on why we're doing this setTimeout
		this.addEvent( nodeChildren, 'change', function() {
			that.updateNumChildren( strParentName, strName, 'change' );
			setTimeout(function() {
				document.getElementById( strParentName + '_Submit' ).parentNode.style.height = '100%';
				document.getElementById( strParentName + '_Submit' ).parentNode.style.height = 'auto';
			}, 1 );
		}, false );
		this.addEvent( nodeChildren, 'keyup', function() {
			that.updateNumChildren( strParentName, strName, 'keyup' );
			setTimeout(function() {
				document.getElementById( strParentName + '_Submit' ).parentNode.style.height = '100%';
				document.getElementById( strParentName + '_Submit' ).parentNode.style.height = 'auto';
			}, 1 );
		}, false );
	} else {
		this.addEvent( nodeChildren, 'change', function() { that.updateNumChildren( strParentName, strName, 'change' ); }, false );
		this.addEvent( nodeChildren, 'keyup', function() { that.updateNumChildren( strParentName, strName, 'keyup' ); }, false );
	}
	
	return true;
};

// handle event for link to display disclaimer, only added if it exists
// @param strName string - element id for sqqcomponent
DisneyQuickQuote.prototype.addChildAgeDisclaimerEvent = function( strName ) {
	var that = this;
	
	// add event to display disclaimer, only 1, so I didn't want to make a var for the element
	this.addEvent( document.getElementById( strName ), 'click', function() { that.displayChildAgeDisclaimer( strName, 'click' ); }, false );
	return true;
};

// handle events for multi drop down selection changes
// @param nodeSelect object - first drop down element to attach events to
// @param strElement string - element id for 1st drop down
// @param strElement2 string - element id for 2nd drop down
DisneyQuickQuote.prototype.addDropDownMultiEvent = function( nodeSelect, intNode, strElement, strElement2 ) {
	var that = this;
	
	// combo boxes need change (all) and keyup (ie) events to update drop down multi selection
	this.addEvent( nodeSelect, 'change', function() { that.updateDropDownMultiSelection( intNode, strElement, strElement2, 'change' ); }, false );
	this.addEvent( nodeSelect, 'keyup', function() { that.updateDropDownMultiSelection( intNode, strElement, strElement2, 'keyup' ); }, false );
	return true;
};

// handle events for drop down dependency selection changes
// @param nodeSelect object - first drop down element to attach events to
// @param strParentName string - element id for parent element
// @param strName string - element id for sqqcomponent
DisneyQuickQuote.prototype.addDropDownEvent = function( nodeSelect, strName, strParentName, intNode ) {
	var that = this;
	
	// combo boxes need change (all) and keyup (ie) events to update drop down selection
	this.addEvent( nodeSelect, 'change', function() { that.updateDropDownSelection( strName, strParentName, intNode, 'change' ); }, false );
	this.addEvent( nodeSelect, 'keyup', function() { that.updateDropDownSelection( strName, strParentName, intNode, 'keyup' ); }, false );
	return true;
};

// handle events for textbox overlay label hide/display
// @param nodeInput object - textbox input
// @param nodeOverlay object - overlay span object
// @param strParentName string - element id for parent element
// @param strName string - element id for sqqcomponent
DisneyQuickQuote.prototype.addTextBoxOverlayEvent = function( nodeInput, nodeOverlay, strName, strParentName ) {
	var that = this;
	
	// focus is for hiding, blur is for showing
	this.addEvent( nodeInput, 'focus', function() { that.updateTextBoxOverlay( strName, strParentName, true, false, 'focus' ); }, false );
	this.addEvent( nodeOverlay, 'click', function() { that.updateTextBoxOverlay( strName, strParentName, true, true, 'overlay' ); }, false );
	this.addEvent( nodeInput, 'blur', function() { that.updateTextBoxOverlay( strName, strParentName, false, false, 'blur' ); }, false );
	return true;
};

// handle event for image link to display calendar
// @param nodeButton object - calendar button that displays the calendar
// @param objData object - reference of data object to duplicate
// @param intCal integer - index of what calendar we're dealing with
// @param bSetData boolean - if true, set our calendar data
DisneyQuickQuote.prototype.addDisplayCalendarEvent = function( nodeButton, objData, intCal, bSetData ) {
	var that = this;
	if ( bSetData ) {
		this.arrAttributes.qqCalendars[ intCal ] = objData;
	}
	
	this.addEvent( nodeButton, 'click', function() { that.displayCalendar( that.arrAttributes.qqCalendars[ intCal ], intCal, 'click' ); }, false );
	return true;
};

// handle events for all the combo boxes that modify travel dates
// @param strName string - element id of sqqcomponent
// @param strParentName string - element id of parent
// @param intCal integer - index of what calendar we're dealing with
DisneyQuickQuote.prototype.addTravelEvents = function( objArrival, objDeparture ) {
	var that = this;
	
	// we assume that they are the same
	if ( objArrival.singleTextField ) {
		// update arrival and departure inputs, refer to updateSingleTravelDate function for details
		// since each is only used once, we're not setting extra vars for it
		this.addEvent( document.getElementById( objArrival.name + 'Date' ), 'change', function() { that.updateSingleTravelDate( objArrival, false, 'change' ); }, false );
		this.addEvent( document.getElementById( objDeparture.name + 'Date' ), 'change', function() { that.updateSingleTravelDate( objDeparture, false, 'change' ); }, false );
		
		// add our function for when users click a date on the calendar to update our combo boxes (and force update is true)
		objArrival._fChange = function() {
			that.updateSingleTravelDate( objArrival, true, 'click' );
		};
		objDeparture._fChange = function() {
			that.updateSingleTravelDate( objDeparture, true, 'click' );
		};
	} else {
		var nodeArrivalMonth = document.getElementById( objArrival.name + 'Month' );
		var nodeArrivalDay = document.getElementById( objArrival.name + 'Day' );
		var nodeArrivalYear = document.getElementById( objArrival.name + 'Year' );
		var nodeDepartureMonth = document.getElementById( objDeparture.name + 'Month' );
		var nodeDepartureDay = document.getElementById( objDeparture.name + 'Day' );
		var nodeDepartureYear = document.getElementById( objDeparture.name + 'Year' );
		
		// update all arrival and departure selects, refer to updateTravelDate function for details
		this.addEvent( nodeArrivalMonth, 'change', function() { that.updateTravelDate( objArrival, false, 'change' ); }, false );
		this.addEvent( nodeArrivalMonth, 'keyup', function() { that.updateTravelDate( objArrival, false, 'keyup' ); }, false );
		this.addEvent( nodeArrivalDay, 'change', function() { that.updateTravelDate( objArrival, false, 'change' ); }, false );
		this.addEvent( nodeArrivalDay, 'keyup', function() { that.updateTravelDate( objArrival, false, 'keyup' ); }, false );
		this.addEvent( nodeArrivalYear, 'change', function() { that.updateTravelDate( objArrival, false, 'change' ); }, false );
		this.addEvent( nodeArrivalYear, 'keyup', function() { that.updateTravelDate( objArrival, false, 'keyup' ); }, false );
		this.addEvent( nodeDepartureMonth, 'change', function() { that.updateTravelDate( objDeparture, false, 'change' ); }, false );
		this.addEvent( nodeDepartureMonth, 'keyup', function() { that.updateTravelDate( objDeparture, false, 'keyup' ); }, false );
		this.addEvent( nodeDepartureDay, 'change', function() { that.updateTravelDate( objDeparture, false, 'change' ); }, false );
		this.addEvent( nodeDepartureDay, 'keyup', function() { that.updateTravelDate( objDeparture, false, 'keyup' ); }, false );
		this.addEvent( nodeDepartureYear, 'change', function() { that.updateTravelDate( objDeparture, false, 'change' ); }, false );
		this.addEvent( nodeDepartureYear, 'keyup', function() { that.updateTravelDate( objDeparture, false, 'keyup' ); }, false );
		
		// add our function for when users click a date on the calendar to update our combo boxes (and force update is true)
		objArrival._fChange = function() {
			that.updateTravelDate( objArrival, true, 'click' );
		};
		objDeparture._fChange = function() {
			that.updateTravelDate( objDeparture, true, 'click' );
		};
	}
	
	return true;
};

// add's event to document/window to check for our open calendar
DisneyQuickQuote.prototype.addOpenCalendarMouseCheckEvent = function() {
	var that = this;
	// add our event to check for mouse click, arguments[0] is equivilent to event
	if ( document.all ) {
		// ie uses document instead of window, it doesn't span across everything, but it's the only event that'll work correctly
		this.addEvent( document, 'click', function() { that.checkOpenCalendar( arguments[0], that ); }, false );
	} else {
		this.addEvent( window, 'click', function() { that.checkOpenCalendar( arguments[0], that ); }, false );
	}
	return true;
};

// event process
// updates multi business unit data (displays/hides divs)
// @param x string - name of event
DisneyQuickQuote.prototype.updateMultiBUSelection = function( x ) {
	var nodeMulti = document.getElementById( 'SQQMultiBU' );
	
	// if our container doesn't exist, stop, don't change
	if ( typeof( document.getElementById( nodeMulti.value + '_Container' ) ) == 'undefined' ) {
		return false;
	}
	
	// hide our current business unit and show the new one
	document.getElementById( this.objData.Prop.BU[ this.objData.Prop.currentBU ].value + '_Container' ).className = 'SQQBusinessUnit hidden';
	document.getElementById( nodeMulti.value + '_Container' ).className = 'SQQBusinessUnit';
	
	// see global rules, we're assuming selectedIndex is 1:1 with array index
	this.objData.Prop.currentBU = nodeMulti.selectedIndex;
};

// displays/hides div when product options are selected
// @param strElement string - element id of product option
// @param x string - name of event
DisneyQuickQuote.prototype.switchProductOptions = function( strElement, intPO, x ) {
	// we set this to a variable since it's used twice and the value being set is a little complex
	var strName = this.objData.Prop.BU[ this.objData.Prop.currentBU ].value + '_' + this.objData.Prop.BU[ this.objData.Prop.currentBU ].PO[ this.objData.Prop.BU[ this.objData.Prop.currentBU ].currentPO ].name;
	// hide our current product option from our current business unit
	document.getElementById( strName  + '_Container' ).className = 'SQQProductOption hidden';
	document.getElementById( strName + '_InputDisplay' ).className = 'SQQProductOptionOffContainer';
	document.getElementById( strElement + '_Container' ).className = 'SQQProductOption';
	document.getElementById( strElement + '_InputDisplay' ).className = 'SQQProductOptionOnContainer';
	
	this.objData.Prop.BU[ this.objData.Prop.currentBU ].currentPO = intPO;
	
	return true;
};

// hides/displays the grouping of elements
// @param strElement string - element id of product option
// @param x string - name of event
DisneyQuickQuote.prototype.displayGroup = function( strElement, x ) {
	var nodeElement = document.getElementById( strElement );
	var nodeOpened = document.getElementById( strElement + '_OpenedLabel' );
	var nodeClosed = document.getElementById( strElement + '_Label' );
	
	if ( nodeElement.className == 'SQQGrouping SQQGroupingHide' ) {
		nodeElement.className = 'SQQGrouping SQQGroupingDisplay';
		
		if ( nodeOpened && nodeClosed ) {
			nodeOpened.style.display = 'block';
			nodeClosed.style.display = 'none';
		}
	} else {
		nodeElement.className = 'SQQGrouping SQQGroupingHide';
		
		if ( nodeOpened && nodeClosed ) {
			nodeOpened.style.display = 'none';
			nodeClosed.style.display = 'block';
		}
	}
};

// submits the selected product option of the selected business unit
// @param strElement string - element id of product option
// @param x string - name of event
DisneyQuickQuote.prototype.submitProductOption = function( strElement, x ) {
	if ( !document.getElementById( strElement + '_Form' ) ) {
		return false;
	}
	
	// I wouldn't normally do this, but this function interacts with this set of data a LOT, it out-performances the usage of more memory
	var objBU = this.objData.Prop.BU[ this.objData.Prop.currentBU ];
	var objPO = objBU.PO[ objBU.currentPO ];
	var dtArrival;
	var dtDeparture;
	var intCount;
	var intMax;
	var nodeElement;
	var arrErrors = [];
	
	// make sure we're checking the one we're on
	// if we're somehow not on the same form than our JS thinks we are, we have no choice but to submit them
	if ( objBU.value + '_' + objPO.name != strElement ) {
		document.getElementById( strElement + '_Form' ).submit();
		return true;
	}
	
	// a sqqtraveldates must exist for either check
	if ( typeof( objPO.SQQTravelDates ) != 'undefined' ) {
		var bDropDown = false;
		var objTravel = objPO.SQQTravelDates;
		dtArrival = new Date();
		dtArrival.setToCalendarDate();
		dtDeparture = new Date( dtArrival );
		
		if ( typeof( objPO.SQQDropDown ) != 'undefined'  ) {
			var nodeDropDown;
			var nodeTarget;
			var strTarget = '';
			var intDropDown = ( objPO.SQQDropDown.length - 1 );
			
			do {
				// if the child does not have a dependency, there are no rules for it to affect sqqtraveldates, skip it
				// also ensure it has the child attached from our business rules processing
				if ( typeof( objPO.SQQDropDown[ intDropDown ].dependency ) == 'undefined' || typeof( objPO.SQQDropDown[ intDropDown ].child ) == 'undefined' ) {
					continue;
				}
				
				nodeDropDown = document.getElementById( strElement + '_' + objPO.SQQDropDown[ intDropDown ].xmlPointer );
				nodeTarget = document.getElementById( strElement + '_' + objPO.SQQDropDown[ intDropDown ].dependency );
				
				// does the drop down or target not exist
				if ( !nodeDropDown || !nodeTarget ) {
					continue;
				}
				
				// we assume this is the correct data, but for whatever strange reason, it MAY not, and this needs to compensate
				if ( this.objData.Groups[ objPO.SQQDropDown[ intDropDown ].xmlPointer ][ nodeDropDown.selectedIndex ].d == nodeDropDown.value ) {
					strTarget = this.objData.Groups[ objPO.SQQDropDown[ intDropDown ].xmlPointer ][ nodeDropDown.selectedIndex ].t;
				} else {
					intCount = ( this.objData.Groups[ objPO.SQQDropDown[ intDropDown ].xmlPointer ].length - 1 );
					do {
						if ( this.objData.Groups[ objPO.SQQDropDown[ intDropDown ].xmlPointer ][ intCount ].d == nodeDropDown.value ) {
							strTarget = this.objData.Groups[ objPO.SQQDropDown[ intDropDown ].xmlPointer ][ nodeDropDown.selectedIndex ].t;
							break;
						}
					} while ( intCount-- );
				}
				
				// if our target does not exist
				if ( !strTarget ) {
					continue;
				}
				
				// if this target has NO data relevent to dates, simply skip over it
				if ( typeof( this.objData.OptInfo[ strTarget ].travelStartDate ) == 'undefined' && typeof( this.objData.OptInfo[ strTarget ].travelStartMonth ) == 'undefined' && typeof( this.objData.OptInfo[ strTarget ].travelStartYear ) == 'undefined' && typeof( this.objData.OptInfo[ strTarget ].travelEndDate ) == 'undefined' && typeof( this.objData.OptInfo[ strTarget ].travelEndMonth ) == 'undefined' && typeof( this.objData.OptInfo[ strTarget ].travelEndYear ) == 'undefined' ) {
					continue;
				}
				
				// set our drop down boolean to true to stop the sqqtraveldates check, since we're doing the sqqdropdown check now
				bDropDown = true;
				
				// for some reason we have a few items without a day/date, so lets put it to 1
				if ( typeof( this.objData.OptInfo[ strTarget ].travelStartDate ) == 'undefined' || this.objData.OptInfo[ strTarget ].travelStartDate === null ) {
					this.objData.OptInfo[ strTarget ].travelStartDate = 1;
				}
				
				var nodeArrivalDate = document.getElementById( strElement + '_' + objTravel.name + '_arrivalDate' );
				var nodeDepartureDate = document.getElementById( strElement + '_' + objTravel.name + '_departureDate' );
				
				// pull our arrival/departure dates
				if ( objPO.SQQTravelDates.singleTextField ) {
					if ( dtArrival.validate( nodeArrivalDate.value ) ) {
						dtArrival.setTime( Date.parse( nodeArrivalDate.value ) );
					}
					
					if ( dtDeparture.validate( nodeDepartureDate.value ) ) {
						dtDeparture.setTime( Date.parse( nodeDepartureDate.value ) );
					}
				} else {
					dtArrival.setFullYear( document.getElementById( strElement + '_' + objTravel.name + '_arrivalYear' ).value, ( ( document.getElementById( strElement + '_' + objTravel.name + '_arrivalMonth' ).value * 1 ) - 1 ), document.getElementById( strElement + '_' + objTravel.name + '_arrivalDay' ).value );
					dtDeparture.setFullYear( document.getElementById( strElement + '_' + objTravel.name + '_departureYear' ).value, ( ( document.getElementById( strElement + '_' + objTravel.name + '_departureMonth' ).value * 1 ) - 1 ), document.getElementById( strElement + '_' + objTravel.name + '_departureDay' ).value );
				}
				
				objTravel = this.objData.OptInfo[ strTarget ];
				break;
			} while ( intDropDown-- );
		}
		
		// if no drop downs are affecting our data, lets pull the data from the SQQTravelDates instead
		if ( !bDropDown ) {
			nodeArrivalDate = document.getElementById( strElement + '_' + objTravel.name + '_arrivalDate' );
			nodeDepartureDate = document.getElementById( strElement + '_' + objTravel.name + '_departureDate' );
			
			if ( nodeArrivalDate && nodeDepartureDate ) {
				if ( dtArrival.validate( nodeArrivalDate.value ) ) {
					dtArrival.setTime( Date.parse( nodeArrivalDate.value ) );
				}
				
				if ( dtDeparture.validate( nodeDepartureDate.value ) ) {
					dtDeparture.setTime( Date.parse( nodeDepartureDate.value ) );
				}
			} else {
				dtArrival.setFullYear( document.getElementById( strElement + '_' + objTravel.name + '_arrivalYear' ).value, ( ( document.getElementById( strElement + '_' + objTravel.name + '_arrivalMonth' ).value * 1 ) - 1 ), document.getElementById( strElement + '_' + objTravel.name + '_arrivalDay' ).value );
				dtDeparture.setFullYear( document.getElementById( strElement + '_' + objTravel.name + '_departureYear' ).value, ( ( document.getElementById( strElement + '_' + objTravel.name + '_departureMonth' ).value * 1 ) - 1 ), document.getElementById( strElement + '_' + objTravel.name + '_departureDay' ).value );
			}
		}
		
		// if the arrival date is after the departure date
		if ( dtArrival > dtDeparture ) {
			if ( typeof( this.objData.Prop.listAllErrors ) != 'undefined' && this.objData.Prop.listAllErrors ) {
				arrErrors.push( this.objData.Prop.errors.strArriveAfterDepart );
			} else {
				return this.displaySubmitError( strElement, this.objData.Prop.errors.strArriveAfterDepart );
			}
		}
		
		var intDayDiff = Math.round( ( dtDeparture.getTime() - dtArrival.getTime() ) / ( 1000 * 60 * 60 * 24 ) );
		
		// if the date diff is less than minimum booking time
		// or if the date diff is greater than max booking time
		if ( intDayDiff < objTravel.minBookTime ) {
			if ( typeof( this.objData.Prop.listAllErrors ) != 'undefined' && this.objData.Prop.listAllErrors ) {
				arrErrors.push( this.objData.Prop.errors.strStayTooShort.replace( /\[N\]/gi, objTravel.minBookTime ) );
			} else {
				return this.displaySubmitError( strElement, this.objData.Prop.errors.strStayTooShort.replace( /\[N\]/gi, objTravel.minBookTime ) );
			}
		} else if ( intDayDiff > objTravel.maxBookTime ) {
			if ( typeof( this.objData.Prop.listAllErrors ) != 'undefined' && this.objData.Prop.listAllErrors ) {
				arrErrors.push( this.objData.Prop.errors.strStayTooLong.replace( /\[N\]/gi, objTravel.maxBookTime ) );
			} else {
				return this.displaySubmitError( strElement, this.objData.Prop.errors.strStayTooLong.replace( /\[N\]/gi, objTravel.maxBookTime ) );
			}
		}
		
		var dtMinMax = new Date();
		dtMinMax.setToCalendarDate();
		
		// if a travel date is specified from our data, see if it's in the future
		// we need a date range start
		if ( objTravel.travelStartYear > 0 && objTravel.travelStartMonth > 0 && objTravel.travelStartDate > 0 ) {
			var dtTravel = new Date( dtMinMax );
			dtTravel.setFullYear( objTravel.travelStartYear, ( objTravel.travelStartMonth - 1 ), objTravel.travelStartDate );
			
			// if the travel date is after than today's date, use that instead
			if ( dtMinMax.compare( dtTravel ) == -1 ) {
				dtMinMax = new Date( dtTravel );
			} else { // travel date is in the past, today + 1
				dtMinMax.setDate( ( dtMinMax.getDate() * 1 ) + 1 );
			}
			
			dtTravel = undefined;
		} else { // no travel date specified, today + 1
			dtMinMax.setDate( ( dtMinMax.getDate() * 1 ) + 1 );
		}
		
		// dtMinMax is currently today, they can't book before today
		if ( dtArrival < dtMinMax ) {
			if ( typeof( this.objData.Prop.listAllErrors ) != 'undefined' && this.objData.Prop.listAllErrors ) {
				arrErrors.push( this.objData.Prop.errors.strArriveIsBeforeAllowable );
			} else {
				return this.displaySubmitError( strElement, this.objData.Prop.errors.strArriveIsBeforeAllowable );
			}
		}
		
		dtMinMax.setFullYear( objTravel.travelEndYear, ( objTravel.travelEndMonth - 1 ), objTravel.travelEndDate );
		
		// dtMinMax is currently end of display year
		if ( dtDeparture > dtMinMax ) {
			if ( typeof( this.objData.Prop.listAllErrors ) != 'undefined' && this.objData.Prop.listAllErrors ) {
				arrErrors.push( this.objData.Prop.errors.strArriveIsAfterMaxDate );
			} else {
				return this.displaySubmitError( strElement, this.objData.Prop.errors.strArriveIsAfterMaxDate );
			}
		}
	}
	
	// if we have sqqtextbox, check if any of them are required
	if ( typeof( objPO.SQQTextBox ) != 'undefined' ) {
		intMax = objPO.SQQTextBox.length;
		intCount = 0;
		
		do {
			if ( typeof( objPO.SQQTextBox[ intCount ].isRequired ) != 'undefined' && objPO.SQQTextBox[ intCount ].isRequired === true ) {
				nodeElement = document.getElementById( strElement + '_' + objPO.SQQTextBox[ intCount ].name + '_Text' );
	
				if ( nodeElement && ( typeof( nodeElement.value ) == 'undefined' || ( typeof( nodeElement.value ) != 'undefined' && nodeElement.value.length < 1 ) ) ) {
					if ( typeof( objPO.SQQTextBox[ intCount ].requiredError ) != 'undefined' ) {
						if ( typeof( this.objData.Prop.listAllErrors ) != 'undefined' && this.objData.Prop.listAllErrors ) {
							arrErrors.push( objPO.SQQTextBox[ intCount ].requiredError );
						} else {
							return this.displaySubmitError( strElement, objPO.SQQTextBox[ intCount ].requiredError );
						}
					} else {
						if ( typeof( this.objData.Prop.listAllErrors ) != 'undefined' && this.objData.Prop.listAllErrors ) {
							arrErrors.push( 'A required field was left blank.' );
						} else {
							return this.displaySubmitError( strElement, 'A required field was left blank.' );
						}
					}
				}
				
				++intCount;
			}
		} while ( intCount < intMax );
	}
	
	// if we have sqqdropdown, check if any of them are required
	if ( typeof( objPO.SQQDropDown ) != 'undefined' ) {
		intMax = objPO.SQQDropDown.length;
		intCount = 0;
		
		do {
			if ( typeof( objPO.SQQDropDown[ intCount ].isRequired ) != 'undefined' && objPO.SQQDropDown[ intCount ].isRequired === true ) {
				nodeElement = document.getElementById( strElement + '_' + objPO.SQQDropDown[ intCount ].xmlPointer );
	
				if ( nodeElement && ( typeof( nodeElement.value ) == 'undefined' || ( typeof( nodeElement.value ) != 'undefined' && nodeElement.value.length < 1 ) ) ) {
					if ( typeof( objPO.SQQDropDown[ intCount ].requiredError ) != 'undefined' ) {
						if ( typeof( this.objData.Prop.listAllErrors ) != 'undefined' && this.objData.Prop.listAllErrors ) {
							arrErrors.push( objPO.SQQDropDown[ intCount ].requiredError );
						} else {
							return this.displaySubmitError( strElement, objPO.SQQDropDown[ intCount ].requiredError );
						}
					} else {
						if ( typeof( this.objData.Prop.listAllErrors ) != 'undefined' && this.objData.Prop.listAllErrors ) {
							arrErrors.push( 'A required field was left blank.' );
						} else {
							return this.displaySubmitError( strElement, 'A required field was left blank.' );
						}
					}
				}
			}
			
			++intCount;
		} while ( intCount < intMax );
	}
	
	// if we have sqqpartymix, check if any of them are required
	if ( typeof( objPO.SQQPartyMix ) != 'undefined' ) {
		if ( typeof( objPO.SQQPartyMix.maxGuests ) != 'undefined' && objPO.SQQPartyMix.maxGuests > 0 ) {
			var intGuests = 0;
			
			nodeElement = document.getElementById( strElement + '_' + objPO.SQQPartyMix.name + '_numAdults' );
			if ( nodeElement && nodeElement.value ) {
				intGuests += ( nodeElement.value * 1 );
			}
			
			nodeElement = document.getElementById( strElement + '_' + objPO.SQQPartyMix.name + '_numChildren' );
			if ( nodeElement && nodeElement.value ) {
				intGuests += ( nodeElement.value * 1 );
			}
			
			if ( intGuests > objPO.SQQPartyMix.maxGuests ) {
				if ( typeof( this.objData.Prop.listAllErrors ) != 'undefined' && this.objData.Prop.listAllErrors ) {
					arrErrors.push( this.objData.Prop.errors.strTooManyGuests.replace( /\[N\]/gi, objPO.SQQPartyMix.maxGuests ) );
				} else {
					return this.displaySubmitError( strElement, this.objData.Prop.errors.strTooManyGuests.replace( /\[N\]/gi, objPO.SQQPartyMix.maxGuests ) );
				}
			}
		}
	}
	
	if ( typeof( this.objData.Prop.listAllErrors ) != 'undefined' && this.objData.Prop.listAllErrors ) {
		if ( arrErrors && arrErrors.length > 0 ) {
			return this.displaySubmitError( strElement, arrErrors.join( '<br />' ) );
		}
	}
	
	// at this point all data is valid, process ready-to-submit
	// if the product option supports tracking and the functions exist (internal only), fire it off
	if ( typeof( objPO.trackingLinkId ) != 'undefined' && objPO.trackingLinkId !== null ) {
		if ( typeof( s_wdpro ) != 'undefined' && typeof( s_wdpro.trackLink) != 'undefined' ) {
			s_wdpro.trackLink( document.getElementById( strElement + '_Submit' ), objPO.trackingLinkId );
		}
	}
	
	
			// call segmentation if YUI exists
			if ( typeof( YAHOO ) != 'undefined' && typeof( YAHOO.util ) != 'undefined' && typeof( YAHOO.util.Connect ) != 'undefined' ) {
				// manually create our query since YUI's Connect.setForm isn't helpful for custom fields
				// even when manually setting the 4th param
				var strQuery = '';
				
				// all of our assumptions is that our objects exist, due to prior checks
				if ( dtArrival ) {
					strQuery = strQuery + '&arrivingOn=' + ( dtArrival.getMonth() + 1 ) + '/' + dtArrival.getDate() + '/' + dtArrival.getFullYear();
				}
				
				if ( dtDeparture ) {
					strQuery = strQuery + '&leavingOn=' + ( dtDeparture.getMonth() + 1 ) + '/' + dtDeparture.getDate() + '/' + dtDeparture.getFullYear();
				}
				
				if ( objPO.SQQPartyMix ) {
					var nodeAdults = document.getElementById( strElement + '_' + objPO.SQQPartyMix.name + '_numAdults' );
					if ( nodeAdults ) {
						setQuery = strQuery + '&numAdults=' + nodeAdults.options[nodeAdults.selectedIndex].value;
					}
					
					var nodeChildren = document.getElementById( strElement + '_' + objPO.SQQPartyMix.name + '_numChildren' );
					if ( nodeChildren ) {
						setQuery = strQuery + '&numChildren=' + nodeChildren.options[nodeChildren.selectedIndex].value;
						
						if ( ( nodeChildren.options[nodeChildren.selectedIndex].value * 1 ) > 0 ) {
							var nodeChildAge;

							for ( intCount = 1; intCount < nodeChildren.options[nodeChildren.selectedIndex].value; ++intCount ) {
								nodeChildAge = document.getElementById( strElement + '_' + objPO.SQQPartyMix.name + '_child' + intCount );
								
								if ( nodeChildAge ) {
									strQuery = strQuery + '&child' + intCount + '=' + nodeChildAge.options[nodeChildAge.selectedIndex].value;
								}
							}
						}
					}
				}
				
				if ( strQuery ) {
					var segmentEvent = YAHOO.util.Connect.asyncRequest( 'POST', '/event/quickQuote?explicit_segmentation_event_Id=theGreatestSongInTheWorld', null, strQuery.substr(1) );
				}
			}
			
	
	document.getElementById( strElement + '_Form' ).submit();
	return true;
};
// update the amount of child age combo boxes displayed from the number of children
DisneyQuickQuote.prototype.updateNumChildren = function( strParentName, strName, strEvent, intOverrideBU, intOverridePO ) {
	var intBU = ( ( typeof( intOverrideBU ) == 'undefined' ) ? this.objData.Prop.currentBU : intOverrideBU );
	var intPO = ( ( typeof( intOverridePO ) == 'undefined' ) ? this.objData.Prop.BU[ this.objData.Prop.currentBU ].currentPO : intOverridePO );
	var nodeChildren = document.getElementById( strParentName + '_' + strName + '_numChildren' );
	var intChildren = nodeChildren.options[ nodeChildren.selectedIndex ].value;
	
	// if the number of children matches what we currently show, do not update
	if ( this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQPartyMix.currentChildren == intChildren ) {
		return false;
	}
	
	// save our count
	this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQPartyMix.currentChildren = intChildren;
	var nodeContainer = document.getElementById( strParentName + '_' + strName + '_childContainer' );
	
	// if at least 1 child is coming, display the container, otherwise hide it
	if ( intChildren > 0 ) {
		// take the last value we have, this is supposed to be the highest value (e.g. 6)
		var intCount = nodeChildren.options[ ( nodeChildren.options.length - 1 ) ].value;
		
		// loop through our containers based on our count we just got, then hide/display based on what they selected
		do {
			if ( typeof( document.getElementById( strParentName + '_' + strName + '_ageContainer' + intCount ) ) != 'undefined' ) {
				document.getElementById( strParentName + '_' + strName + '_ageContainer' + intCount ).className = ( ( intCount > intChildren ) ? 'SQQPartyMixChildAgeCount SQQPartyMixChildAgeCountHide' : 'SQQPartyMixChildAgeCount SQQPartyMixChildAgeCountDisplay' );
			}
		} while ( --intCount );
		
		nodeContainer.className = 'SQQPartyMixChildAgeContainer';
	} else {
		nodeContainer.className = 'SQQPartyMixChildAgeContainer hidden';
	}
	
	return true;
};
// generates the popup/message for "why is this required?" usually
// @param strName string - element id of child disclaimer
// @param strEvent string - the event that fired this function
DisneyQuickQuote.prototype.displayChildAgeDisclaimer = function ( strName, strEvent ) {
	// pull the body and head from the HTML that is generated for non-JS users
	this.displayMessage( document.getElementById( strName + 'Body' ).innerHTML, document.getElementById( strName + 'Head' ).innerHTML, this.objData.Prop.errors.strCloseLabel );
	
	return true;
};
// hides any element, essentially
// currently used for the child age disclaimer and submit/validation errors
// @param strName string - element id of popup
// @param strEvent string - the event that fired this function
DisneyQuickQuote.prototype.hidePopup = function ( strName, strEvent ) {
	
	if ( typeof( document.body.style.maxHeight ) == 'undefined' ) {
		this.loopElementsWithCallback( document.getElementById( this.arrAttributes.qqElement ).getElementsByTagName( 'select' ), function( node ) {
			node.style.visibility = '';
		} );
	}
	
	if (document.getElementById( strName )) {
		document.getElementById( strName ).style.display = 'none';
	}
		
	return true;
};

// action function to load drop down data, always returns true
// @param nodeElement object - object referencing the select element
// @param arrData array - array of objects that associate "l" and "d" for the values of the drop down
DisneyQuickQuote.prototype.loadDropDown = function( nodeElement, arrData ) {
	// remove all items before populating
	if ( nodeElement.length > 0 ) {
		do {
			nodeElement.remove( 0 );
		} while ( nodeElement.length );
	}
	
	// make sure our data exists and has a length
	if ( arrData && arrData.length > 0 ) {
		// loop through our array and grab options
		var nodeOption;
		var intCount = 0;
		var intTotal = arrData.length;
		
		// we need to add in order so we cannot use our efficient decrement loops
		do {
			// add the node data to our record
			nodeOption = document.createElement( 'option' );
			nodeOption.text = arrData[ intCount ].l.replace( /&amp;/gi, '&' );
			nodeOption.value = ( ( typeof( arrData[ intCount ].d ) != 'undefined' ) ? arrData[ intCount ].d : '' );
			
			// ie catch, firefox, safari, etc. first
			try {
				nodeElement.add( nodeOption, null );
			} catch ( e ) {
				nodeElement.add( nodeOption );
			}
			
			++intCount;
		} while ( intCount < intTotal );
	}
	
	return true;
};

// this event is only attached to multidropdown's who have set "targetSecond" to true
// this updates the second combo/drop down based on the value of the first
// @param intNode integer - the item corresponding to the current BU/PO
// @param strElement1 string - element id of first select
// @param strElement1 string - element id of second select
// @param strEvent string - the event that fired this function
DisneyQuickQuote.prototype.updateDropDownMultiSelection = function ( intNode, strElement1, strElement2, strEvent, intOverrideBU, intOverridePO ) {
	var nodeElement1 = document.getElementById( strElement1 );
	var intBU = ( ( typeof( intOverrideBU ) == 'undefined' ) ? this.objData.Prop.currentBU : intOverrideBU );
	var intPO = ( ( typeof( intOverridePO ) == 'undefined' ) ? this.objData.Prop.BU[ this.objData.Prop.currentBU ].currentPO : intOverridePO );
	
	// see if our first combo actually has a 2nd value, separated by the '|' char
	var intLoc = nodeElement1.options[ nodeElement1.selectedIndex ].value.indexOf( '|' );
	
	// if the 2nd value exists, get all the text after the '|' char
	if ( intLoc == -1 ) {
		return false;
	}
	
	var strNewValues = nodeElement1.options[ nodeElement1.selectedIndex ].value.substr( ( intLoc + 1 ) );
	var nodeElement2 = document.getElementById( strElement2 );
	
	// if there was any text after the '|', continue with the second combo box, and does the data exist
	if ( strNewValues || typeof( this.objData.Groups[ strNewValues ] ) != 'undefined' ) {
		// if the second select data is what we're already using, don't reprocess
		if ( strNewValues == this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDownMulti[ intNode ].xmlPointer2 ) {
			nodeElement2.parentNode.style.display = 'block';
			return true;
		}
		
		// set our record 
		this.objData.Prop.BU[ intBU ].PO[ intPO ].SQQDropDownMulti[ intNode ].xmlPointer2 = strNewValues;
		
		// load all drop down data
		this.loadDropDown( nodeElement2, this.objData.Groups[ strNewValues ] );
		
		// wait until all the DOM edition is added before displaying the combo box again
		nodeElement2.parentNode.style.display = 'block';
	} else {
		// if there is nothing 
		nodeElement2.parentNode.style.display = 'none';
	}
};

// this function was developed to consolidate setting travel dates
// @param strName string - ID name we prepend
// @param bSingle boolean - true/false if the travel dates uses single text or not
// @param intMonth int - month we're setting
// @param intDay int - day we're setting
// @param intYear int - year we're setting
DisneyQuickQuote.prototype.updateTravelDates = function ( strName, bSingle, intMonth, intDay, intYear ) {
	if ( bSingle ) {
		document.getElementById( strName + 'Date' ).value = intMonth + '/' + intDay + '/' + intYear;
	} else {
		var nodeMonth = document.getElementById( strName + 'Month' );
		var nodeDay = document.getElementById( strName + 'Day' );
		var nodeYear = document.getElementById( strName + 'Year' );
		
		nodeMonth.value = intMonth;
		nodeYear.value = intYear;
		this.updateDaysInMonth( nodeMonth, nodeDay, nodeYear );
		nodeDay.value = intDay;
	}
	
	return true;
};

// this event is only attached to textbox's that have overlay labels
// will automatically hide/display if the content is null
// @param strName string - name of our textbox
// @param strParentName string - name of our parent
// @param bIsFocus boolean - true if this event is focus, false if blur
// @param bSetFocus boolean - true if this event should set focus, false if not
// @param strEvent string - the event that fired this function
DisneyQuickQuote.prototype.updateTextBoxOverlay = function ( strName, strParentName, bIsFocus, bSetFocus, strEvent ) {
	var nodeElement = document.getElementById( strParentName + '_' + strName + '_Text' );
	var nodeOverlay = document.getElementById( strParentName + '_' + strName + '_Overlay' );
	
	if ( bSetFocus ) {
		nodeElement.focus();
	}
	
	// always hide if being focused
	if ( bIsFocus ) {
		nodeOverlay.className = 'SQQTextBoxOverlayLabelHide';
	} else {
		if ( typeof( nodeElement.value ) != 'undefined'  ) {
			if ( nodeElement.value && nodeElement.value.length > 0 ) {
				nodeOverlay.className = 'SQQTextBoxOverlayLabelHide';
			} else {
				nodeOverlay.className = 'SQQTextBoxOverlayLabel';
			}
		} else {
			nodeOverlay.className = 'SQQTextBoxOverlayLabel';
		}
	}
	
	return true;
};

// this event is only attached to drop downs who have a dependency
// this updates the second drop down and travel dates
// @param strName string - name of our drop down
// @param strParentName string - name of our drop down
// @param strEvent string - the event that fired this function
DisneyQuickQuote.prototype.updateDropDownSelection = function ( strName, strParentName, intNode, strEvent, intOverwriteBU, intOverwritePO ) {
	var nodeElement = document.getElementById( strParentName + '_' + strName );
	var intBU = ( ( typeof( intOverwriteBU ) == 'undefined' ) ? this.objData.Prop.currentBU : intOverwriteBU );
	var intPO = ( ( typeof( intOverwritePO ) == 'undefined' ) ? this.objData.Prop.BU[ this.objData.Prop.currentBU ].currentPO : intOverwritePO );
	
	var objPO = this.objData.Prop.BU[ intBU ].PO[ intPO ];
	var nodeSelect = document.getElementById( strParentName + '_' + objPO.SQQDropDown[ objPO.SQQDropDown[ intNode ].child ].xmlPointer );
	var strDataName = strName;
	var objData;
	
	if ( typeof( objPO.SQQDropDown[ intNode ].targetData ) != 'undefined' && objPO.SQQDropDown[ intNode ].targetData ) {
		strDataName = objPO.SQQDropDown[ intNode ].targetData ;
	}
	
	// make sure our drop down has a value
	if ( !nodeElement.value ) {
		// if it's blank and it's child has a default value, lets send that data
		if ( !this.objData.Groups[ objPO.SQQDropDown[ objPO.SQQDropDown[ intNode ].child ].xmlPointer ] ) {
			return false;
		} else {
			objData = this.objData.Groups[ objPO.SQQDropDown[ objPO.SQQDropDown[ intNode ].child ].xmlPointer ];
			objPO.SQQDropDown[ objPO.SQQDropDown[ intNode ].child ].targetData = null;
		}
	} else {
		// does our data not exist or have no entries?
		var objGroup = this.objData.Groups[ strDataName ][ nodeElement.selectedIndex ];
		
		if ( !objGroup || objGroup.length < 1 || ( typeof( objGroup.a ) != 'undefined' && objGroup.a.length < 1 ) ) {
			nodeSelect.className = 'SQQDropDownSelect SQQDropDownSelectHidden';
			
			return false;
		}
		
		
		// dcl is special.. I don't know why
		if ( strDataName == 'DCLCruises' ) {
			objData = objGroup.a;
		} else if ( typeof( objGroup.t ) == 'undefined') { // if our opt info code doesn't exist, end it
			// well, the target data is null, lets just go back the default selection, if it exists
			if ( !this.objData.Groups[ objPO.SQQDropDown[ objPO.SQQDropDown[ intNode ].child ].xmlPointer ] ) {
				return false;
			} else {
				objData = this.objData.Groups[ objPO.SQQDropDown[ objPO.SQQDropDown[ intNode ].child ].xmlPointer ];
				objPO.SQQDropDown[ objPO.SQQDropDown[ intNode ].child ].targetData = null;
			}
		} else {
			if ( !this.objData.Groups[ objGroup.t ] && !this.objData.OptInfo[ objGroup.t ] ) {
				return false;
			}
			
			// "already shown" logic, if a selected item has the same target data, no need to refresh
			// no need to even force display to visible, because the data should already be visible if it was already changed
			if ( objPO.SQQDropDown[ objPO.SQQDropDown[ intNode ].child ].targetData == objGroup.t ) {
				return false;
			}
			
			objPO.SQQDropDown[ objPO.SQQDropDown[ intNode ].child ].targetData = objGroup.t; // moved here to save data
			
			if ( this.objData.Groups[ objGroup.t ] ) {
				objData = this.objData.Groups[ objGroup.t ];
			} else {
				// if an opt info code was found, lets change our data
				var objOptInfo = this.objData.OptInfo[ objGroup.t ];
				objData = objOptInfo.d;
				
				// does this PO have an SQQTravelDate ?
				if ( typeof( objPO.SQQTravelDates ) != 'undefined' ) {
					// check our calendars and create them if they haven't been created
					this.checkCalendar( this.arrAttributes.qqCalendars[ objPO.SQQTravelDates.arrival ], true );
					this.checkCalendar( this.arrAttributes.qqCalendars[ objPO.SQQTravelDates.departure ], true );
					
					var dtStart = new Date();
					dtStart.setToCalendarDate();
					var dtEnd = new Date( dtStart );
					
					// if our date is set and any month but today, then we can set it
					if ( ( typeof( objOptInfo.travelStartDate ) != 'undefined' && objOptInfo.travelStartDate !== null ) || ( typeof( objOptInfo.travelStartDate ) == 'undefined' && objOptInfo.travelStartMonth != ( dtStart.getMonth() + 1 ) ) ) {
						// lets put the date to 1, then change it if we have a date
						dtStart.setFullYear( objOptInfo.travelStartYear, ( ( objOptInfo.travelStartMonth * 1 ) - 1 ), 1 );
						
						if ( typeof( objOptInfo.travelStartDate ) != 'undefined' && objOptInfo.travelStartDate !== null ) {
							dtStart.setDate( objOptInfo.travelStartDate );
						}
					}
					
					// if our date is set and any month but today, then we can set it
					if ( ( typeof( objOptInfo.travelEndDate ) != 'undefined' && objOptInfo.travelEndDate !== null ) || ( typeof( objOptInfo.travelEndDate ) == 'undefined' && objOptInfo.travelEndMonth != ( dtEnd.getMonth() + 1 ) ) ) {
						// lets put the date to 1, then change it if we have a date
						dtEnd.setFullYear( objOptInfo.travelEndYear, ( ( objOptInfo.travelEndMonth * 1 ) - 1 ), 1 );
						
						if ( typeof( objOptInfo.travelEndDate ) != 'undefined' && objOptInfo.travelEndDate !== null ) {
							dtEnd.setDate( objOptInfo.travelEndDate );
						}
					}
					
					// we can't let them arrive on the last day, because then their departure date would be past the date range
					dtEnd.setDate( dtEnd.getDate() - objOptInfo.minBookTime );
					
					// update our travel dates and date ranges
					this.updateTravelDates( strParentName + '_' + objPO.SQQTravelDates.name + '_arrival', objPO.SQQTravelDates.singleTextField, ( dtStart.getMonth() + 1 ), dtStart.getDate(), dtStart.getFullYear() );
					this.arrAttributes.qqCalendars[ objPO.SQQTravelDates.arrival ].calendar.setDateFromInputs();
					this.arrAttributes.qqCalendars[ objPO.SQQTravelDates.arrival ].calendar.setDateRange( dtStart, dtEnd );
					this.arrAttributes.qqCalendars[ objPO.SQQTravelDates.arrival ].minBookTime = objOptInfo.minBookTime;
					
					// now departure
					var dtDisplay = new Date( dtStart );
					
					if (objPO.SQQTravelDates.displayDateRange >= objOptInfo.minBookTime) {
						dtDisplay.setDate( dtDisplay.getDate() + objPO.SQQTravelDates.displayDateRange );
					} else {
						dtDisplay.setDate( dtDisplay.getDate() + objOptInfo.minBookTime );
					}
					
					dtStart.setDate( dtStart.getDate() + objOptInfo.minBookTime );
					dtEnd.setDate( dtEnd.getDate() + objOptInfo.minBookTime );
					
					this.updateTravelDates( strParentName + '_' + objPO.SQQTravelDates.name + '_departure', objPO.SQQTravelDates.singleTextField, ( dtDisplay.getMonth() + 1 ), dtDisplay.getDate(), dtDisplay.getFullYear() );
					this.arrAttributes.qqCalendars[ objPO.SQQTravelDates.departure ].calendar.setDateFromInputs();
					this.arrAttributes.qqCalendars[ objPO.SQQTravelDates.departure ].calendar.setDateRange( dtStart, dtEnd );
				}
			}
		}
	}
	
	// consolidated loading drop down data
	nodeSelect.className = 'SQQDropDownSelect';
	this.loadDropDown( nodeSelect, objData );
	
	// does this child have another child? if so, lets setup that data too!
	if ( typeof( objPO.SQQDropDown[ objPO.SQQDropDown[ intNode ].child ].child ) != 'undefined' && objPO.SQQDropDown[ objPO.SQQDropDown[ intNode ].child ].child ) {
		return this.updateDropDownSelection( objPO.SQQDropDown[ objPO.SQQDropDown[ intNode ].child ].xmlPointer, strParentName, objPO.SQQDropDown[ intNode ].child, 'inherit', intBU, intPO );
	}
	
	return true;
};

// intializes a calendar for us
// @param objEntry object - Calendar object that we're checking
// @param bPreventAutoCheck boolean - If this is true, we do not check for arrival/departure
DisneyQuickQuote.prototype.checkCalendar = function( objEntry, bPreventAutoCheck ) {
	if ( typeof( objEntry.calendar ) == 'undefined' ) {
		// we should create the arrival calendar first, if it's not and not prevented
		if ( !objEntry.isArrival && !bPreventAutoCheck ) {
			this.checkCalendar( this.arrAttributes.qqCalendars[ objEntry.arrival ], true );
		}
		
		// is the entry a single text field or 3 combos
		if ( objEntry.singleTextField ) {
			objEntry.calendar = new Calendar( objEntry.name + 'Date', objEntry.config );
		} else {
			objEntry.calendar = new Calendar( objEntry.name + 'Month', objEntry.name + 'Day', objEntry.name + 'Year', objEntry.config );
		}
		
		objEntry.calendar.draw(); // draw our calendar into the DOM
		objEntry.calendar.hide(); // hide our calendar after drawing
		objEntry.config = undefined;
		// set our function inside the calendar
		/*
		we should be able to replac ethis bulkier code with setting the variable to the function instead
		objEntry.calendar._fChange = function() {
			objEntry._fChange();
		}*/
		objEntry.calendar._fChange = objEntry._fChange;
		
		// we should create the departure calendar last, if it's not and not prevented
		if ( objEntry.isArrival && !bPreventAutoCheck ) {
			this.checkCalendar( this.arrAttributes.qqCalendars[ objEntry.departure ], true );
		}
		
		return true;
	} else {
		return false;
	}
};

// displays the calendar based on element clicked and the # of which calendar to display
// @param strName string - component name
// @param strParentName string - component name of parents (BU & PO)
// @param strCalendar string - element id of calendar button
// @param intCal integer - key of what calendar is being referenced
// @param strEvent string - the event that fired this function
DisneyQuickQuote.prototype.displayCalendar = function ( objEntry, intCal, strEvent ) {
	// is a calendar already open?
	if ( this.arrAttributes.curOpenCalendar >= 0 ) {
		// if the calendar open is the one we just clicked on, lets close and skip this mess
		if ( this.arrAttributes.qqCalendars[ this.arrAttributes.curOpenCalendar ].name == objEntry.name ) {
			this.hideCal( objEntry );
			return true;
		}
		
		this.hideCal( this.arrAttributes.qqCalendars[ this.arrAttributes.curOpenCalendar ] );
	}
	
	// check our calendar and create it if it hasn't been created
	this.checkCalendar( objEntry );
	
	// if ie6, hide all selects for this product option except the ones we need
	if ( typeof( document.body.style.maxHeight ) == 'undefined' ) {
		if ( document.getElementById( 'SQQMultiBU' ) ) {
			document.getElementById( 'SQQMultiBU' ).style.visibility = 'hidden';
		}
		
		this.displayMessage( '', '', '', true );
		this.loopElementsWithCallback( document.getElementById( objEntry.parentName + '_Container' ).getElementsByTagName( 'select' ), function( node ) {
			if ( node.id != objEntry.name + 'Month' && node.id != objEntry.name + 'Day' && node.id != objEntry.name + 'Year' ) {
				node.style.visibility = 'hidden';
			} else {
				node.style.visibility = 'visible';
			}
		} );
	}
	
	// retrieve our calendar object and set up our top/left
	var nodeElement = document.getElementById( objEntry.name + 'CalendarBtn' );
	nodeElement.className = 'SQQTravelDatesCalendar SQQTravelDatesCalendarOpen';
	
	var objCoords = this.getCoords( nodeElement );
	
	this.arrAttributes.curOpenCalendar = intCal;
	objEntry.calendar._nodeCalendar.style.left = objCoords.right + 'px'; // we want the right hand side of our element so it will be right next to it
	objEntry.calendar._nodeCalendar.style.top = objCoords.top + 'px';
	objEntry.calendar.show();
	
	return true;
};
// hides the calendar with the # provided
DisneyQuickQuote.prototype.hideCal = function( objEntry ) {
	// no calendar is open = -1, don't want this to misfire
	if ( this.arrAttributes.curOpenCalendar < 0 ) {
		return false;
	}
	
	// hide the current open calendar, swipe the location
	document.getElementById( objEntry.name + 'CalendarBtn' ).className = 'SQQTravelDatesCalendar';
	objEntry.calendar.hide();
	this.arrAttributes.curOpenCalendar = -1;
};

// get top, right, bottom, left of a node on the page
DisneyQuickQuote.prototype.getCoords = function( nodeElement ) {
	var objCoords = {
		top: 0,
		right: 0,
		bottom: 0,
		left: 0
	};
	
	objCoords.right = nodeElement.offsetWidth;
	objCoords.bottom = nodeElement.offsetHeight;
	
	// get our element's offsets
	while ( nodeElement !== null ) {
		objCoords.top += nodeElement.offsetTop;
		objCoords.left += nodeElement.offsetLeft;
		nodeElement = nodeElement.offsetParent;
	}
	
	// set our button coords
	objCoords.bottom += objCoords.top;
	objCoords.right += objCoords.left;
	
	return objCoords;
};

// this function fires on a mouse click in the window (not document)
// it determines if a calendar is open, then tracks the mouse click coords
// using the coords it creates a padding around the calendar for a "safe zone"
DisneyQuickQuote.prototype.checkOpenCalendar = function( e, that ) {
	// no calendar is open = -1
	if ( that.arrAttributes.curOpenCalendar < 0 ) {
		return false;
	}
	
	// if the calendar open somehow has no Calendar() reference, set current to -1
	if ( typeof( that.arrAttributes.qqCalendars[ that.arrAttributes.curOpenCalendar ] ) == 'undefined' ) {
		that.arrAttributes.curOpenCalendar = -1;
		return false;
	}
	
	var objEntry = that.arrAttributes.qqCalendars[ that.arrAttributes.curOpenCalendar ];
		
	// for IE, set our event
	if ( !e ) {
		e = window.event;
	}
	
	// get coords of our calendar

	var objCoords = that.getCoords( objEntry.calendar._nodeCalendar );
	
	var intPosX = 0;
	var intPosY = 0;
	
	// add/subtract our padding around our calendar
	objCoords.bottom += ( that.arrAttributes.qqCalendarPadding );
	objCoords.right += ( that.arrAttributes.qqCalendarPadding );
	objCoords.top -= ( that.arrAttributes.qqCalendarPadding );
	objCoords.left -= ( that.arrAttributes.qqCalendarPadding );
	
	// ie/ff checking
	if ( typeof( e.pageX ) != 'undefined' && typeof( e.pageY ) != 'undefined' ) {
		intPosX = e.pageX;
		intPosY = e.pageY;
	} else if ( typeof( e.clientX ) != 'undefined' && typeof( e.clientY ) != 'undefined' ) {
		intPosX = ( e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft );
		intPosY = ( e.clientY + document.body.scrollTop + document.documentElement.scrollTop );
	}
	
	// if it's not in a safe zone of our calendar
	if ( !( intPosX > objCoords.left && intPosX < objCoords.right && intPosY > objCoords.top && intPosY < objCoords.bottom ) ) {
		// we want to add a safe zone from our "executer", e.g. the button that was clicked to bring this up
		var nodeBtn = document.getElementById( objEntry.name + 'CalendarBtn' );
		if ( nodeBtn ) {
			objCoords = that.getCoords( nodeBtn );
			
			// if the user is inside the button too, stop it
			if ( intPosX > objCoords.left && intPosX < objCoords.right && intPosY > objCoords.top && intPosY < objCoords.bottom ) {
				return false;
			}
		}
		
		// add a safe zone for the text field if it exists
		var nodeDate = document.getElementById( objEntry.name + 'Date' );
		if ( nodeDate ) {
			objCoords = that.getCoords( nodeDate );

			// if the user is inside the button too, stop it
			if ( intPosX > objCoords.left && intPosX < objCoords.right && intPosY > objCoords.top && intPosY < objCoords.bottom ) {
				return false;
			}
		}
		
		// if ie6, show all of our select's
		if ( typeof( document.body.style.maxHeight ) == 'undefined' ) {
			this.hidePopup( 'qqWarning', 'auto' );
			this.loopElementsWithCallback( document.getElementById( objEntry.parentName + '_Container' ).getElementsByTagName( 'select' ), function( node ) {
				node.style.visibility = 'visible';
			} );
		}
		
		this.hideCal( objEntry );
	}
	
	return true;
};

// handles updating the travel dates for a single text field
// @param objEntry object - Contains a reference to our calendar data object
// @param bFromCal boolean - This function was called from our calendar, special updating techniques for this
// @param strEvent string - Event that fired this function
DisneyQuickQuote.prototype.updateSingleTravelDate = function( objEntry, bFromCal, strEvent ) {
	// consolidate generic calendar items
	if ( bFromCal ) {
		// if ie6, show all of the select's for this product option
		if ( typeof( document.body.style.maxHeight ) == 'undefined' ) {
			this.hidePopup( 'qqWarning', 'click' );
			this.loopElementsWithCallback( document.getElementById( objEntry.parentName + '_Container' ).getElementsByTagName( 'select' ), function( node ) {
				node.style.visibility = 'visible';
			} );
		}
		
		this.hideCal( objEntry );
	} else {
		bCreated = this.checkCalendar( objEntry );
	}
	
	// we have extensive checks and processing for arrival dates, as it adversely affects our departure
	if ( objEntry.isArrival ) {
		var bUpdateDeparture = false;
		var dtDepart = new Date();
		dtDepart.setToCalendarDate();
		var dtLowest = new Date( dtDepart );
		var intSavedMonth = objEntry.calendar._dtSelected.getMonth();
		var intSavedDate = objEntry.calendar._dtSelected.getDate();
		var intSavedYear = objEntry.calendar._dtSelected.getFullYear();
		var nodeDepartureDate = document.getElementById( this.arrAttributes.qqCalendars[ objEntry.departure ].name + 'Date' );
		
		// forcing update or did they change the month and does our saved match departure month
		if ( bFromCal ) {
			dtDepart.setFullYear( intSavedYear, intSavedMonth, intSavedDate );
			dtDepart.setDate( dtDepart.getDate() + objEntry.displayDateRange );
			bUpdateDeparture = true;
		} else {
			var nodeArrivalDate = document.getElementById( objEntry.name + 'Date' );
			var dtNew = new Date( dtDepart );
			
			// validate the arrival and departure inputs
			if ( dtNew.validate( nodeArrivalDate.value ) ) {
				dtNew.setTime( Date.parse( nodeArrivalDate.value ) );
				
				if ( dtNew < objEntry.calendar._dtRangeStart ) {
					dtNew.setTime( objEntry.calendar._dtRangeStart.getTime() );
					nodeArrivalDate.value = ( dtNew.getMonth() + 1 ) + '/' + dtNew.getDate() + '/' + dtNew.getFullYear();
				}
				
				dtLowest.setTime( dtNew.getTime() );
			}
			
			if ( dtDepart.validate( nodeDepartureDate.value ) ) {
				dtDepart.setTime( Date.parse( nodeDepartureDate.value ) );
			}
			
			if ( dtNew > dtDepart ) {
				dtDepart.setTime( dtNew.getTime() );
				bUpdateDeparture = true;
			}
			
			dtLowest.setDate( dtLowest.getDate() + objEntry.minBookTime );
			if ( dtLowest > dtDepart ) {
				dtDepart.setTime( dtLowest.getTime() );
				bUpdateDeparture = true;
			} else {
				// if the month is different
				if ( dtNew.getMonth() != intSavedMonth ) {
					dtDepart.setMonth( dtNew.getMonth() );
					dtDepart.setDate( dtNew.getDate() );
					bUpdateDeparture = true;
				} else if ( dtNew.getMonth() == dtDepart.getMonth() && dtNew.getDate() != intSavedDate && dtNew.getDate() >= dtDepart.getDate() ) {
					// if the month is the same and the day is different and the departure date is less than our new arrival date
					// we don't want to update our departure date if they have a different month selected
					dtDepart.setMonth( dtNew.getMonth() );
					dtDepart.setDate( dtNew.getDate() );
					bUpdateDeparture = true;
				} else if ( dtNew.getFullYear() != intSavedYear ) {
					// if the year is different
					dtDepart.setFullYear( dtNew.getFullYear() );
					bUpdateDeparture = true;
				}
				
				if ( bUpdateDeparture ) {
					dtDepart.setDate( dtDepart.getDate() + objEntry.displayDateRange );
				}
			}
			
			// set our arrival calendar object to what we have now
			objEntry.calendar.setDateFromInputs();
		}
		
		// if we updated our departure date, set its calendar object and days in month
		if ( bUpdateDeparture ) {
			nodeDepartureDate.value = ( dtDepart.getMonth() + 1 ) + '/' + dtDepart.getDate() + '/' + dtDepart.getFullYear();
			this.arrAttributes.qqCalendars[ objEntry.departure ].calendar.setDateFromInputs();
		}
		
		// we need to update our date ranges regardless if departure has changed; it's not called in displayCalendar anymore
		this.arrAttributes.qqCalendars[ objEntry.departure ].calendar.setDateRange( dtLowest, this.arrAttributes.qqCalendars[ objEntry.departure ].calendar._dtRangeEnd );
	} else if ( !bFromCal ) { // departures
		// simply update our calendar date objects
		// we do not need to update date range or arrival at all
		objEntry.calendar.setDateFromInputs();
	}
	
	return true;
};

// handles updating the travel dates
// @param objEntry object - Contains a reference to our calendar data object
// @param bFromCal boolean - This function was called from our calendar, special updating techniques for this
// @param strEvent string - Event that fired this function
DisneyQuickQuote.prototype.updateTravelDate = function( objEntry, bFromCal, strEvent ) {
	var bCreated = false;
	
	// consolidate generic calendar items
	if ( bFromCal ) {
		// if ie6, show all of the select's for this product option
		if ( typeof( document.body.style.maxHeight ) == 'undefined' ) {
			this.hidePopup( 'qqWarning', 'click' );
			this.loopElementsWithCallback( document.getElementById( objEntry.parentName + '_Container' ).getElementsByTagName( 'select' ), function( node ) {
				node.style.visibility = 'visible';
			} );
		}
		
		this.hideCal( objEntry );
	} else {
		bCreated = this.checkCalendar( objEntry );
	}
	
	// we have extensive checks and processing for arrival dates, as it adversely affects our departure
	if ( objEntry.isArrival ) {
		var nodeArrivalMonth = document.getElementById( objEntry.name + 'Month' );
		var nodeArrivalDay = document.getElementById( objEntry.name + 'Day' );
		var nodeArrivalYear = document.getElementById( objEntry.name + 'Year' );
		var nodeDepartureMonth = document.getElementById( this.arrAttributes.qqCalendars[ objEntry.departure ].name + 'Month' );
		var nodeDepartureDay = document.getElementById( this.arrAttributes.qqCalendars[ objEntry.departure ].name + 'Day' );
		var nodeDepartureYear = document.getElementById( this.arrAttributes.qqCalendars[ objEntry.departure ].name + 'Year' );
		
		var intSavedMonth = ( objEntry.calendar._dtSelected.getMonth() + 1 );
		var intSavedDate = objEntry.calendar._dtSelected.getDate();
		var intSavedYear = objEntry.calendar._dtSelected.getFullYear();
		
		var dtNew = new Date();
		dtNew.setToCalendarDate();
		var bUpdateDeparture = false;
		
		// forcing update or did they change the month and does our saved match departure month
		if ( bFromCal ) {
			this.updateDaysInMonth( nodeArrivalMonth, nodeArrivalDay, nodeArrivalYear );
			nodeArrivalDay.value = objEntry.calendar._dtSelected.getDate();
			
			dtNew.setFullYear( intSavedYear, ( intSavedMonth - 1 ), intSavedDate );
			dtNew.setDate( dtNew.getDate() + objEntry.displayDateRange );
			
			nodeDepartureMonth.value = ( dtNew.getMonth() + 1 );
			nodeDepartureYear.value = dtNew.getFullYear();
			this.updateDaysInMonth( nodeDepartureMonth, nodeDepartureDay, nodeDepartureYear );
			nodeDepartureDay.value = dtNew.getDate();
			
			bUpdateDeparture = true;
		} else  {
			// set our new date to what we have in our combo boxes, then add our minimum travel length; used to update departure
			dtNew.setFullYear( nodeArrivalYear.value, ( ( nodeArrivalMonth.value * 1 ) - 1 ), nodeArrivalDay.value );
			
			if ( dtNew.compare(objEntry.calendar._dtRangeEnd) == 1 ) { // date is too far away, reset it
				dtNew.setTime( objEntry.calendar._dtRangeEnd.getTime() );
				
				nodeArrivalYear.value = dtNew.getFullYear();
				nodeArrivalMonth.value = ( dtNew.getMonth() + 1 );
				this.updateDaysInMonth( nodeArrivalMonth, nodeArrivalDay, nodeArrivalYear );
				nodeArrivalDay.value = dtNew.getDate();
			}
			
			var intNewDay = -1;
			
			// dtDisplay is only used when changing month/day, if changing year we don't need this, see comment below where the year is checked
			var dtDisplay = new Date( dtNew );
			dtDisplay.setDate( dtDisplay.getDate() + objEntry.displayDateRange ); 
			dtNew.setDate( dtNew.getDate() + objEntry.minBookTime );
			
			if ( bCreated ) {
				intSavedMonth = -1;
			}
			
			// if the month is different
			if ( ( nodeArrivalMonth.value != intSavedMonth ) || ( nodeArrivalMonth.value == nodeDepartureMonth.value && ( nodeArrivalDay.value * 1 ) != intSavedDate && ( nodeArrivalDay.value * 1 ) >= ( nodeDepartureDay.value * 1 ) ) ) {
				// if the month is the same and the day is different and the departure date is less than our new arrival date
				// we don't want to update our departure date if they have a different month selected
				nodeDepartureMonth.value = ( dtDisplay.getMonth() + 1 );
				intNewDay = dtDisplay.getDate();
				bUpdateDeparture = true;
			} else if ( nodeArrivalYear.value != intSavedYear ) {
				// if the year is different
				// see we use dtNew for this, because since the date (read: day) isn't changing, we shouldn't accidently move the year 2 up if the dates near the end of December
				nodeDepartureYear.value = dtNew.getFullYear(); 
				bUpdateDeparture = true;
			}
			
			// if our month or year changed, check the days in the month we have (year because of leap year changes)
			if ( nodeArrivalMonth.value != intSavedMonth || nodeArrivalYear.value != intSavedYear ) {
				this.updateDaysInMonth( nodeArrivalMonth, nodeArrivalDay, nodeArrivalYear );
			}
			
			// we need to update our departure and then set our day if changes happened
			if ( bUpdateDeparture ) {
				this.updateDaysInMonth( nodeDepartureMonth, nodeDepartureDay, nodeDepartureYear );
				
				// if the months are different and the value is 1, updateDaysInMonth resetted it, so lets fix that
				if ( nodeDepartureMonth.value != nodeArrivalMonth.value && nodeArrivalDay.value == 1 ) {
					nodeDepartureMonth.value = nodeArrivalMonth.value;
					this.updateDaysInMonth( nodeDepartureMonth, nodeDepartureDay, nodeDepartureYear );
					dtNew.setMonth( nodeArrivalMonth.value - 1 ); // this is on purpose, we want the previous month (0-11)
				}
				
				if ( intNewDay > 0 ) {
					nodeDepartureDay.value = intNewDay;
					//dtNew.setDate( intNewDay ); // i don't think we use this anymore, since display takes over the intNewDay now
				}
			}
			
			// update our arrival calendar object with our new values
			objEntry.calendar.setDateFromInputs();
		}
		
		// if we updated our departure date, set its calendar object and days in month
		if ( bUpdateDeparture ) {
			this.arrAttributes.qqCalendars[ objEntry.departure ].calendar.setDateFromInputs();
		}
		
		// we need to update our date ranges regardless if departure has changed; it's not called in displayCalendar anymore
		this.arrAttributes.qqCalendars[ objEntry.departure ].calendar.setDateRange( dtNew, this.arrAttributes.qqCalendars[ objEntry.departure ].calendar._dtRangeEnd );
	} else {
		nodeDepartureMonth = document.getElementById( objEntry.name + 'Month' );
		nodeDepartureDay = document.getElementById( objEntry.name + 'Day' );
		nodeDepartureYear = document.getElementById( objEntry.name + 'Year' );
		
		if ( bFromCal ) {
			this.updateDaysInMonth( nodeDepartureMonth, nodeDepartureDay, nodeDepartureYear );
			nodeDepartureDay.value = objEntry.calendar._dtSelected.getDate();
		} else {
			dtNew = new Date();
			dtNew.setToCalendarDate();
			dtNew.setFullYear( nodeDepartureYear.value, ( ( nodeDepartureMonth.value * 1 ) - 1 ), nodeDepartureDay.value );
			
			if ( dtNew.compare(objEntry.calendar._dtRangeEnd) == 1 ) { // date is too far away, reset it
				nodeDepartureYear.value = objEntry.calendar._dtRangeEnd.getFullYear();
				nodeDepartureMonth.value = objEntry.calendar._dtRangeEnd.getMonth();
				this.updateDaysInMonth( nodeArrivalMonth, nodeArrivalDay, nodeArrivalYear );
				nodeDepartureDay.value = objEntry.calendar._dtRangeEnd.getDate();
			}
			// if the month or year changed, update the days accordingly
			if ( nodeDepartureMonth.value != ( objEntry.calendar._dtSelected.getMonth() + 1 ) || nodeDepartureYear.value != objEntry.calendar._dtSelected.getFullYear() ) {
				this.updateDaysInMonth( nodeDepartureMonth, nodeDepartureDay, nodeDepartureYear );
			}
			
			// update our departure calendar object with our new values
			objEntry.calendar.setDateFromInputs();
		}
	}
	
	return true;
};

// this function updates the days in a month based on the inputs we pass
// it will update the oDay object accordingly
// @param nodeMonth string - "month" select box
// @param nodeDay string - "day" select box
// @param nodeYear string - "year" select box
DisneyQuickQuote.prototype.updateDaysInMonth = function( nodeMonth, nodeDay, nodeYear ) {
	if ( nodeMonth.value === null || !( nodeMonth.value >= 1 && nodeMonth.value <= 12 ) ) {
		return false;
	}

	var arrDaysInMonth = Array( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 );
	var intDaysInMonth = arrDaysInMonth[ ( nodeMonth.value - 1 ) ];
	var intDays = ( nodeDay.options[ ( nodeDay.length - 1 ) ].value * 1 );
	
	if ( nodeMonth.value == 2 ) { // february, check leap year
		if ( ( ( ( nodeYear.value ) % 4 ) === 0 && ( ( nodeYear.value ) % 100 ) !== 0 ) || ( ( nodeYear.value ) % 400 ) === 0 ) {
			intDaysInMonth = 29;
		}
	}
	
	// only add/remove dates that we need, they match so stop
	if ( intDays == intDaysInMonth ) {
		return true;
	} else if ( intDays < intDaysInMonth ) { // if we have less days than we need, add more
		var nodeOption = null;
		++intDays; // start the day after we currently have
		
		// add all days beyond what we have
		do {
			nodeOption = document.createElement( 'option' );
			nodeOption.value = intDays;
			nodeOption.text = intDays;
			
			// ie catch, firefox, safari, etc. first
			try {
				nodeDay.add( nodeOption, null );
			} catch ( e ) {
				nodeDay.add( nodeOption );
			}
			
			++intDays;
		} while ( intDays <= intDaysInMonth );
	} else if ( intDays > intDaysInMonth ) { // if we have more days than we need, remove the ones we don't
		intDays = ( intDays - intDaysInMonth );
		
		do {
			nodeDay.remove( intDaysInMonth );
		} while ( --intDays );
	}
	
	return true;
};

// our event controlling function, this is used to add all events
// @param nodeElement object - reference to element to add event to
// @param strEvent string - event that we're attaching to our nodeElement (minus the "on")
// @param funcFunction function - attached (referenced) function when this event fires
// @param bCapture boolean - capturing the bubble or not
DisneyQuickQuote.prototype.addEvent = function( nodeElement, strEvent, funcFunction, bCapture ) {
	if ( nodeElement.addEventListener ) {
		nodeElement.addEventListener( strEvent, funcFunction, bCapture );
		return true;
	} else if ( nodeElement.attachEvent ) {
		var bReturn = nodeElement.attachEvent( 'on' + strEvent, funcFunction );
		return bReturn;
	} else {
		nodeElement[ 'on' + strEvent ] = funcFunction;
	}
};

// create the instance of quick quote we're using and load
qqModule = new DisneyQuickQuote();

// if the wdpro loader exists, attach to that instead, NextGen implementation
if ( typeof( WDPRO_LOADER ) != 'undefined' ) {
	WDPRO_LOADER.addCallback( function(){
		qqModule.startOnload();
	} );
} else {
	qqModule.addEvent( window, 'load', function() { qqModule.startOnload(); }, false );
}

// JavaScript: inputCalendar.js
// OriginalAuthor: Michael Gallagher
// Copywrite: 2008 Disney Interactive Media Group
// 
// Note: All methods and properties prefixed with an _ are concidered private and
// should not be accessed from outside the Calendar class.

// ** Helper functions **
// toElement(stringOrId)
// @param elmOrId - string ID or a reference to an Element 
// @Description: returns a reference to an element
function toElement( nodeElement ) {
	if ( typeof( nodeElement ) != 'object' ) {
		nodeElement = document.getElementById( nodeElement );
	}
	
	return nodeElement;
}

// **** Extend Date Class with methods used in calendar Class ****
// Date.setToNextMonth()
// @Description - Sets date to the 1st day of the previous month
Date.prototype.setToNextMonth = function() {
	this.setDate( 1 );
	this.setMonth( this.getMonth() + 1 );
};

// Date.setToNextMonth()
// @Description - Sets date to the 1st day of the next month
Date.prototype.setToPreviousMonth = function() {
	this.setDate( 1 );
	this.setMonth( this.getMonth() - 1 );
};

// Date.setToNextMonth()
// @Description - returns the number of days in a month
Date.prototype.getDaysInMonth = function() {
	// copy the object so that we may set dates without affecting the original (this is a get method not a set)
	var that = this;
	that.setDate( 1 );
	that.setMonth( that.getMonth() + 1 );
	that.setDate( that.getDate() - 1 );
	return that.getDate();
};

// Date.getFirstDayOfMonth()
// @Description - returns the day of week (zero based) on which the month begins (0 = sunday ...  6 = saturday)
Date.prototype.getFirstDayOfMonth = function() {
	var that = this;
	that.setDate( 1 );
	return that.getDay();
};

// Date.setToCalendarDate()
// @Description - removes time of day from the date
// usful for making it easier to compare dates
Date.prototype.setToCalendarDate = function() {
	this.setHours( 0 );
	this.setSeconds( 0 );
	this.setMinutes( 0 );
	this.setMilliseconds( 0 );
};


// Date.getCalendarDate()
// @Description - removes time of day from the date
// same as setToCalendarDate but instead of modifing the date object it returns a new one.
Date.prototype.getCalendarDate = function() {
	var t = new Date( this );
	t.setToCalendarDate();
	return t;
};

// Date.validate()
// @Description - validates a given text input, returns true/false
Date.prototype.validate = function( strInput ) {
	var bSet = false;
	
	try {
		bSet = ( typeof( strInput ) == 'string' && strInput.match(/^(0?[1-9]|1[012])[\.\-\/](0?[1-9]|[12]?[0-9]|3[01])[\.\-\/](\d\d)?\d\d$/) !== null );
	} catch( e ) {
		bSet = false;
	}
	
	return bSet;
};

// Compare a date to another date in order to be equivilent both date objects must match to the MS
// Use setToCalendarDate before calling this method to ensure that both dates' times are in sync
// d1.compare(d2)
// if d1 is lt d2 returns -1
// if d1 is eq d2 returns 0
// if d1 is gt d2 returns 1
Date.prototype.compare = function( dtCompare ) {
	var intReturn = null;
    var intCompareTime = dtCompare.getTime();
	var intThisTime = this.getTime();
	
    if ( intThisTime > intCompareTime ) {
		intReturn = 1;
	} else if ( intThisTime == intCompareTime ) {
		intReturn = 0;
	} else {
		intReturn = -1;
	}
	
	return intReturn;
};

// **** Calendar Class ****
// @constructor - Calendar()
// @param * - if using text field, up to 2 arguments, optional 2nd is config object
//          - if using combo boxes (or multiple text fields), up to 4 arguments, optional 4th is config object
// methods and params starting with _ are private and should not be accessed directly from outside the class
function Calendar( varA, varB, varC, varD ) {
	// init private vars
	this._arrDayLabels = ['S','M','T','W','T','F','S'];
	this._arrMonthLabels = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
	this._arrCalendarDays = [];		// Array of references to td elements used for calendar days
	this._dtNow = new Date();					// Todays date
	this._dtNow.setToCalendarDate();			// Remove time from date
	this._dtCurrentMonth = new Date(this._dtNow);	// Current month in view 
	this._dtCurrentMonth.setDate(1);
	this._dtRangeStart = null;					// starting date range
	this._dtRangeEnd = null;					// ending date range
	this._dtSelected = new Date(this._dtNow);		// Selected date
	this._fChange = null;						// function called on "_setValue()" if hiding the calendar
	this._nodeCalendar = null;					// Reference to calendar element.
	this._nodeTarget = null;
	this._nodeMonthYear = null;  				// Reference to element used for month / year label
	this._nodeSelectedDateCell = null;			// Reference to table cell for selected day
	this._nodeSelectInputDay = null;
	this._nodeSelectInputMonth = null;
	this._nodeSelectInputYear = null;
	this._nodeShow = false;						// If set to true, shows the element after it draws
	this._nodeTextInput = null;
	this._strID = null;
	
	// txtInpt can either be an id of or reference to an input of type text
	// init from param, if 3+ params, they're specifying multiple inputs/select
	var that = this;
	if ( arguments.length >= 3 ) {
		this._nodeSelectInputMonth = toElement( varA );
		this._nodeSelectInputDay = toElement( varB );
		this._nodeSelectInputYear = toElement( varC );
		
		// if we have a config object
		if ( arguments.length == 4 ) {
			this.setConfig(varD);
		}
	} else if ( arguments.length >= 1 ) { // 1+ param, only 1 input
		this._nodeTextInput = toElement( varA );
		
		// if we have a config object
		if ( arguments.length == 2) {
			this.setConfig(varB);
		}
		
		if ( this._dtSelected.validate( this._nodeTextInput.value ) ) {
			this._dtSelected.setTime( Date.parse( this._nodeTextInput.value ) );
			this._dtCurrentMonth = this._dtSelected;
			this._dtCurrentMonth.setDate(1);
		} else {
			// init text input to current date
			this._setValue();
		}
	}
}
Calendar.prototype.addEvent = function( nodeElement, strEvent, funcFunction, bCapture ) {
	if ( nodeElement.addEventListener ) {
		nodeElement.addEventListener( strEvent, funcFunction, bCapture );
		return true;
	} else if ( nodeElement.attachEvent ) {
		var bReturn = nodeElement.attachEvent( 'on' + strEvent, funcFunction );
		return bReturn;
	} else {
		nodeElement[ 'on' + strEvent ] = funcFunction;
	}
};
// Calendar.setConfig()
// @Description - initializes private members from config object
Calendar.prototype.setConfig = function(objConfig) {
	// if a select input is used then we need to limit to the available years
	if ( this._nodeSelectInputYear !== null ) {
		this._dtRangeStart = new Date('January 01, ' + this._nodeSelectInputYear.options[0].value); 
		this._dtRangeEnd = new Date('December 31, ' + this._nodeSelectInputYear.options[this._nodeSelectInputYear.options.length - 1].value);
	}
	
	// get our calendar id
	if ( objConfig.id !== null ) {
		this._strID = objConfig.id;	
	}
	
	// get our target object
	if ( objConfig.target !== null ) {
		this._nodeTarget = toElement( objConfig.target );
	}
	
	// get our starting date range
	if ( objConfig.dateRangeStart !== null ) {
		this._dtRangeStart = new Date( objConfig.dateRangeStart );
		this._dtRangeStart.setToCalendarDate();
	}
	
	// get our ending date range
	if ( objConfig.dateRangeEnd !== null ) {
		this._dtRangeEnd = new Date( objConfig.dateRangeEnd );
		this._dtRangeEnd.setToCalendarDate();
	}
	
	// get our "on change date" function
	if ( objConfig.onChangeDate !== null ) {
		this._fChange = objConfig.onChangeDate;
	}
	
	// get whether or not we're showing the input
	if ( objConfig.showInput !== null ) {
		this._nodeShow = objConfig.showInput;
	}
	
	// get our day labels
	if ( objConfig.dayLabels !== undefined ) {
		this._arrDayLabels = objConfig.dayLabels.split( ',' );
	}
	
	// get our month labels
	if ( objConfig.monthLabels !== null ) {
		this._arrMonthLabels = objConfig.monthLabels.split( ',' );
	}
};

// Calendar.setDateFromInputs()
// @Description - sets the calendar to a new date if the combo boxes have changed
Calendar.prototype.setDateFromInputs = function() {
	if ( this._nodeTextInput !== null ) {
		if ( this._dtSelected.validate( this._nodeTextInput.value ) ) {
			this._dtSelected = new Date( this._nodeTextInput.value );
		}
	} else {
		this._dtSelected = new Date( this._nodeSelectInputMonth.value + '/' + this._nodeSelectInputDay.value + '/' + this._nodeSelectInputYear.value );
	}
	
	this._dtSelected.setToCalendarDate();
	this._dtCurrentMonth = new Date( this._dtSelected );
	this._dtCurrentMonth.setDate( 1 );
	this._populateMonth();
};

// Calendar.getDateSelected()
// @Description - returns a copy of the currently selected calendar date
Calendar.prototype.getDateSelected = function(){
	return new Date( this._dtSelected );
};

// Calendar.draw()
// @Description - draws the calendar
Calendar.prototype.draw = function() {
	if ( this._nodeCalendar === null ) {
		// outermost wrapper for calendar calendar
		var nodeContainer = document.createElement('div');
		nodeContainer.className = 'DisneyCal';
		
		if ( this._strID !== null ) {
			nodeContainer.id = this._strID;
		}
		
		// reference to self for use in onclick events
		var that = this;
		
		// create the navigation and month elements
		var nodeHead = nodeContainer.appendChild(document.createElement('div'));
		nodeHead.className = 'DisneyCalHead';
		
		var nodeChild = nodeHead.appendChild(document.createElement('div'));
		nodeChild.className = 'DisneyCalTLNav';
		
		var nodeData = nodeChild.appendChild(document.createElement('a'));
		nodeData.innerHTML = '&lt;';
		nodeData.href = 'javascript:void(0);';
		this.addEvent( nodeData, 'click', function() { that.setToPreviousMonth(); }, false );
		
		nodeChild = nodeHead.appendChild(document.createElement('span'));
		nodeChild.className = 'DisneyCalMonth';
		this._nodeMonthYear = nodeChild;
		
		nodeChild = nodeHead.appendChild(document.createElement('div'));
		nodeChild.className = 'DisneyCalTRNav';
		
		nodeData = nodeChild.appendChild(document.createElement('a'));
		nodeData.href = 'javascript:void(0);';
		nodeData.innerHTML = '&gt;';
		
		this.addEvent( nodeData, 'click', function() { that.setToNextMonth(); }, false );
		
		// create the table row and cell elements used for the calendar 
		nodeHead = nodeContainer.appendChild(document.createElement('table'));
		nodeHead.className = 'DisneyCalTable';
		
		// create day labels in the thead
		nodeChild = nodeHead.appendChild(document.createElement('thead'));
		nodeChild = nodeChild.appendChild(document.createElement('tr'));
		
		// write the day labels
		var intDaysInWeek = 7;
		var i = 0;
		do{
			nodeData = nodeChild.appendChild(document.createElement('th'));
			nodeData.innerHTML = this._arrDayLabels[i];
			i++;
		} while (--intDaysInWeek);
		
		// day numbers in the tbody
		nodeHead = nodeHead.appendChild(document.createElement('tbody'));
		var intWeeksInMonth = 6;
		do {
			intDaysInWeek = 7;
			nodeChild = nodeHead.appendChild(document.createElement('tr'));
			
			do {
				nodeData = nodeChild.appendChild(document.createElement('td'));
				this._addHandleClick(nodeData);
				this._arrCalendarDays.push(nodeData);
			} while (--intDaysInWeek);
		} while (--intWeeksInMonth);
		
		// insert the calendar just before the form field it controls
		// init cal
		if ( this._nodeTarget ) {
			if ( this._nodeTarget.childNodes.length > 0 ) {
				this._nodeCalendar = this._nodeTarget.insertBefore( nodeContainer, this._nodeTarget.childNodes[0] );
			} else {
				this._nodeCalendar = this._nodeTarget.appendChild( nodeContainer );
			}
		} else {
			if ( this._nodeTextInput !== null ) {
				this._nodeCalendar = this._nodeTextInput.parentNode.insertBefore(nodeContainer, this._nodeTextInput);
			} else {
				this._nodeCalendar = this._nodeSelectInputMonth.parentNode.insertBefore(nodeContainer, this._nodeSelectInputMonth);
			}
		}
		// fill calendar with days for the current  month
		this.setDateFromInputs();
		
		if ( ! this._nodeShow ) {
			if ( this._nodeTextInput !== null ) {
				this._nodeTextInput.style.display = 'none';
			} else if ( this._nodeSelectInputMonth !== null && this._nodeSelectInputDay !== null && this._nodeSelectInputYear !== null) {
				this._nodeSelectInputMonth.style.display = 'none';
				this._nodeSelectInputDay.style.display = 'none';
				this._nodeSelectInputYear.style.display = 'none';
			}
		}
		
		this._nodeCalendar.style.display = 'block';
	}
};

// Calendar._addHandleClick( node )
// @Param nodeData (type Object) - the object to add the click event to
Calendar.prototype._addHandleClick = function( nodeData ) {
	var that = this;
	this.addEvent( nodeData, 'click', function() { that._handleClick( nodeData ); }, false );
};

// Calendar.setDateRange(s, e)
// @Param s (type Date)- date for the start of the range
// @Param e (type Date)- date for the end of the range
// @Param bReset (type Boolean); optional - if set to true, it will not reset the date if it is out of range
// Restrict dates between a set of dates
// When initialized ensure that the selected value is not out of bounds by resetting it to the nearest boundary
// Then set the month view to the month of the selected date
Calendar.prototype.setDateRange = function(dtStart, dtEnd, bStopReset) {
	this._dtRangeStart = new Date(dtStart);
	this._dtRangeEnd = new Date(dtEnd);
	this._dtRangeStart.setToCalendarDate();
	this._dtRangeEnd.setToCalendarDate();
	
	if (this._dtRangeStart.compare(this._dtRangeEnd) == 1) {
		var e = new Error('setDateRange: second Date may not occur before first Date:' + this._dtRangeStart + ' - ' + this._dtRangeEnd);
		throw(e);	
	}
	
	// if either the date is before the range start or after the range end, reset it
	if (this._dtSelected.compare(this._dtRangeStart) == -1 || this._dtSelected.compare(this._dtRangeEnd) == 1) {
		this._dtSelected = new Date(this._dtRangeEnd);
		this._dtSelected.setToCalendarDate();
		this._setValue();
	}
	
	this._dtCurrentMonth = new Date(this._dtSelected);
	this._dtCurrentMonth.setDate(1);
	this._dtCurrentMonth.setToCalendarDate();
	this._populateMonth();
};

// Calendar.show()
// @Description - show the calendar
Calendar.prototype.show = function() {
	this._nodeCalendar.style.display = 'block';
	
};

// Calendar.hide()
// @Description - hide the calendar
Calendar.prototype.hide = function() {
	this._nodeCalendar.style.display = 'none';	
};

// Calendar.toggleVisibility()
// @Description - toggle between display block and display none
Calendar.prototype.toggleVisibility = function() {
	if (this._nodeCalendar.style.display != 'block') {
		this._nodeCalendar.style.display ='block';
	} else {
		this._nodeCalendar.style.display = 'none';
	}
};

// Calendar.setToNextMonth()
// @Description - moves the calendar to the next month
Calendar.prototype.setToNextMonth = function() {
	this._dtCurrentMonth.setToNextMonth();
	this._populateMonth();
};

// Calendar.setToPreviousMonth()
// @Description - moves the calendar to the previous month
Calendar.prototype.setToPreviousMonth = function() {
	this._dtCurrentMonth.setToPreviousMonth();
	this._populateMonth();
};
// Calendar._handleClick()
// @Description - Handles the click event and checks if the date clicked is inside this month
Calendar.prototype._handleClick = function( nodeData ) {
	if ( nodeData.className.indexOf( 'DisneyCalDateEnabled' ) > -1 || nodeData.className.indexOf( 'DisneyCalDateSelected' ) > -1 ) {
		this._selectDate( nodeData );
		this._setValue();
	}
};

// Calendar._populateMonth()
// @Description - populates calendar with days in currently viewed month
Calendar.prototype._populateMonth = function() {
	// set that = this. Used in the onclick event of various calendar elements.
	// This is nessisary to keep the onclick from refering to its parent
	// element and instead make it refer back to this original calendar object
	var that = this;
	var strClassName = '';
	var bOutOfBounds = false;

	// set current date at the begining of the month
	var dtCurrent = new Date(this._dtCurrentMonth);
	dtCurrent.setToCalendarDate();
	dtCurrent.setDate(1);

	// get the first day  (0 - 6) in the month
	var intFirstDay = dtCurrent.getFirstDayOfMonth();
	
	// subtract the first day from the first date to get the date at
	// begining of the week even if it occurs within in the previous month
	dtCurrent.setDate( dtCurrent.getDate() - intFirstDay );
	this._nodeMonthYear.innerHTML = this._arrMonthLabels[this._dtCurrentMonth.getMonth()] + ' ' + this._dtCurrentMonth.getFullYear();
	
	// loop through  callendar day elements to populated the month
	// increment the current date by 1 on each pass through
	var i = 0;
	var arrCalDayLength = this._arrCalendarDays.length;
	this._dtSelected.setToCalendarDate();
	
	while (i < arrCalDayLength) {
		bOutOfBounds = false;
		strClassName = '';
		
		// clear the calendar cell
		this._arrCalendarDays[i].innerHTML = dtCurrent.getDate();
		
		if (dtCurrent.getMonth() == this._dtCurrentMonth.getMonth() && dtCurrent.getFullYear() == this._dtCurrentMonth.getFullYear()) {
			// filter out invalid dates based on range if range is defined
			if (dtCurrent.compare(this._dtNow) == -1) {
				// date occurred in the past
				strClassName += ' DisneyCalDatePast';
			} else if (dtCurrent.compare(this._dtNow) === 0) {
				// date is today
				strClassName += ' DisneyCalDateToday';
			}

			if (this._dtRangeStart !== null && dtCurrent.compare(this._dtRangeStart) == -1) {
				// out of lower range
				strClassName += ' DisneyCalDateOutOfBounds';
				bOutOfBounds = true;
			}

			if (this._dtRangeEnd !== null && dtCurrent.compare(this._dtRangeEnd) == 1) {
				// out of upper range
				strClassName += ' DisneyCalDateOutOfBounds';
				bOutOfBounds = true;
			}
			
			if (!bOutOfBounds) {
				// if the date is not out of bounds they should be enabled or selected
				if (dtCurrent.compare(this._dtSelected) === 0) {
					// currently selected date
					// set the reference to selected cell element
					strClassName += ' DisneyCalDateSelected ';
					this._nodeSelectedDateCell = this._arrCalendarDays[i];
				} else {
					// clickable active dates
					strClassName += ' DisneyCalDateEnabled ';
				}
			}
		} else {
			// date occurs outside of the active month
			strClassName = 'DisneyCalDateDisabled';
		}
		
		this._arrCalendarDays[i].className = strClassName;
		dtCurrent.setDate(dtCurrent.getDate() + 1);
		i++;
	}
};

// Calendar._setValue()
// @Description - sets the form value to the current selected date
Calendar.prototype._setValue = function() {
	if ( this._nodeTextInput !== null ) {
		this._nodeTextInput.value = this._dtSelected.getMonth() + 1 + '/' + this._dtSelected.getDate() + '/'  + this._dtSelected.getFullYear();
	} else {
		this._resetSelect(this._nodeSelectInputMonth);
		this._resetSelect(this._nodeSelectInputDay);
		this._resetSelect(this._nodeSelectInputYear);
		this._nodeSelectInputMonth.options[this._dtSelected.getMonth()].selected = true;
		
		if ( typeof( this._nodeSelectInputDay.options[this._dtSelected.getDate() - 1] ) != 'undefined' ) {
			this._nodeSelectInputDay.options[this._dtSelected.getDate() - 1].selected = true;
		}
		
		var strYear = this._dtSelected.getFullYear();
		for ( var i = 0; ( nodeChild = this._nodeSelectInputYear.options[i] ); ++i ) {
			if (nodeChild.value == strYear) {
				nodeChild.selected = true;
				break;	
			}
		}
	}

	if ( typeof( this._fChange ) == 'function' ) {
		this._fChange();
	}
};

// Calendar._resetSelect(elm)
// @Param elm - element of a select input used for date information (ie month, day, or year) 
// @Description - sets all option childnodes to deselected
Calendar.prototype._resetSelect = function(nodeElement) {
	for ( var i = 0; ( nodeChild = nodeElement.options[i]); ++i ) {
		nodeChild.selected = false;
	}
};

// Calendar._selectDate(elm)
// @Param elm - reference to a TD element in the calendar
// @Description - sets selected date to the value indicated by the contents of a clicked td
Calendar.prototype._selectDate = function(nodeElement) {
	this._dtSelected = new Date(this._dtCurrentMonth);
	this._dtSelected.setDate(nodeElement.innerHTML);
	this._populateMonth();
};
