var framework = {
	id: "", 
	props: {
		slider: {
			animating: false, 
			currentSliderImage: 0, 
			currentSliderImageCount: 0, 
			currentSliderImageDelay: 5000, 
			currentSliderImageHeight: 422, 
			currentSliderImageAnimSpeed: 1250, 
			currentSliderImageTimer: -1, 
			currentMessageShowDelay: 55, 
			currentMessageHideDelay: 20, 
			currentMessageTimer: -1, 
			currentMessage: [], 
			currentMessageLine: 0, 
			currentMessageChar: 0
		}, 
		dropfees: [], 
		hours: []
	}, 
	fn: {
		datetime: {
			setMinReturnDate:
				function() {
					var dtPickupDate		= ((framework.id == "reservations-step1-change") ? $("fieldset.itinerary ul>li.dates>.datepicker.pickup").datepicker("getDate") : $(this).datepicker("getDate"));
					
					if (typeof(dtPickupDate) == "object") {
						var intDay				= dtPickupDate.getDate();
						var intMonth			= dtPickupDate.getMonth();
						var intYear				= dtPickupDate.getFullYear();
						
						$(((framework.id == "reservations-step1-change") ? "fieldset.itinerary ul>li.dates>.datepicker.return" : "#dtReturnDate")).datepicker("option", "minDate", new Date(intYear, intMonth, intDay + 1));
					}
				}, 
				
			setMinModalReturnDate:
				function() {
					var dtPickupDate		= $(".jqi .itinerary-modal ul>li.dates>.datepicker.pickup").datepicker("getDate");
					
					if (typeof(dtPickupDate) == "object") {
						var intDay				= dtPickupDate.getDate();
						var intMonth			= dtPickupDate.getMonth();
						var intYear				= dtPickupDate.getFullYear();
						
						$(".jqi .itinerary-modal ul>li.dates>.datepicker.return").datepicker("option", "minDate", new Date(intYear, intMonth, intDay + 1));
					}
				}
		}, 
		bullets: {
			showBulletPointContent:
				function() {
					var intCurID				= $(this).attr("rel");
					
					if ($("#additional-content>.right blockquote:eq(" + (intCurID - 1) + ")").hasClass("hidden")) {
						$("#additional-content>.right ul>li").removeClass("selected");
						$(this).parent("li").addClass("selected"); 
						
						$("#additional-content>.right blockquote:visible")
							.fadeOut(	function() { 
											$(this).addClass("hidden");
											
											$("#additional-content>.right blockquote:eq(" + (intCurID - 1) + ")")
												.css("opacity", 0)
												.css("display", "block")
												.removeClass("hidden")
												.animate({"opacity": 1}, 500);
										});
					}
				}
		}, 
		validation: {
			classes: {
				checkForm: 
					function() {
						return framework.fn.validation.classes.checkFields(true);
					}, 
					
				checkFields:
					function(boolShowAlert) {
						var boolFormValid		= true;
						var objElements			= $("input.validate, select.validate");
						
						if (objElements.length) {
							$(objElements).removeClass("error");
							
							for (var intCounter = 0; intCounter < objElements.length; intCounter++) {
								switch (objElements[intCounter].nodeName.toLowerCase()) {
									case "select" : 
										if (objElements[intCounter].selectedIndex == 0) {
											boolFormValid			= false;
											
											$(objElements[intCounter]).addClass("error");
										}
										break;
									
									case "input" : 
										if ($(objElements[intCounter]).val().length == 0) {
											boolFormValid			= false;
											
											$(objElements[intCounter]).addClass("error");
										}
										break;
								}
							}
						}
						
						if (!boolFormValid) {
							if (boolShowAlert) {
								alert("Please fill out all required fields.  The required fields you have not filled out yet are highlighted in red.");
							}
							
							return false;
						} else {
							return true;
						}
					}
			}, 
			init: 
				function(objElement) { 
					var strTitle			= $(objElement).attr("title");
					var txtHTML				= "<div class=\"validation-tooltip\" data-element=\"" + $(objElement).attr("id") + "\"><p><ins><del>*</del></ins><strong></strong></p></div>";
					var objNewElement		= $(txtHTML);
					var objContainer		= framework.fn.validation.getContainer(objElement);
					var boolSelectBox		= ($(objElement)[0].nodeName.toLowerCase() == "select") ? true : false;
					var dblWidth			= ((boolSelectBox) ? (($(objElement).siblings(".sbHolder").length) ? $(objElement).siblings(".sbHolder").width() : $(objElement).width()) : $(objElement).width()) + 10;
					
					if (strTitle.length) {
						// set string
						txtHTML						= txtHTML.replace("${MESSAGE}", strTitle);
						
						// add to DOM
						$(objNewElement)
							.css({	"right":		-dblWidth + "px", 
									"display":		"none"})
							.find("p>strong")
								.html(strTitle);
								
						$(objContainer).append(objNewElement);
					}
					
					$(objElement).bind("change", function() { framework.fn.validation.check($(this)); });
				}, 

			init_generic: 
				function(objElement) { 
					var txtHTML				= "<div class=\"validation-tooltip generic-tooltip\" data-element=\"" + $(objElement).attr("id") + "\"><p><ins><del>*</del></ins><strong></strong></p></div>";
					var objNewElement		= $(txtHTML);
					var objContainer		= framework.fn.validation.getContainer(objElement);
					var boolSelectBox		= ($(objElement)[0].nodeName.toLowerCase() == "select") ? true : false;
					var strPositionOverride	= $(objElement).attr("data-position");
					var dblWidth			= ((boolSelectBox) ? (($(objElement).siblings(".sbHolder").length) ? $(objElement).siblings(".sbHolder").width() : $(objElement).width()) : $(objElement).width()) + 10;
					
					if ((typeof(strPositionOverride) == "string") && (strPositionOverride.length > 0)) {
						dblWidth				= parseFloat(strPositionOverride);
					} else {
						dblWidth				= -dblWidth;
					}
					
					if ($(objContainer).find("div.validation-tooltip").length == 0) {
						// add to DOM
						$(objNewElement)
							.css({	"right":		dblWidth + "px", 
									"display":		"none"});
								
						$(objContainer).append(objNewElement);
					}
				}, 

			show: 
				function(objElement) { 
					var objContainer		= framework.fn.validation.getWrapper(objElement);
					
					$(objContainer).fadeIn();
				},

			show_generic: 
				function(objElement, strMessage) { 
					var objContainer		= framework.fn.validation.getWrapper(objElement);
					
					$(objContainer).find("p>strong").html(strMessage);
					$(objContainer).fadeIn();
				},
				
			check: 
				function(objElement) {
					var boolValid			= framework.fn.validation.isValid(objElement);
					
					if (boolValid) {
						framework.fn.validation.hide(objElement);
					} else {
						framework.fn.validation.show(objElement);
					}
				}, 
				
			hide: 
				function(objElement) { 
					var objContainer		= framework.fn.validation.getWrapper(objElement);
					
					$(objContainer).fadeOut();
				}, 
				
			validate:
				function() {
					var objElements				= $("input.validate, select.validate");
					var boolFormValid			= true;
					var objCurElement, objWrapper, boolValid;
					
					if (objElements.length) {
						for (var intCounter = 0; intCounter < objElements.length; intCounter++) {
							boolValid			= true;
							objCurElement		= $(objElements[intCounter]);
							objWrapper			= framework.fn.validation.getWrapper(objElements[intCounter]);
							
							boolValid			= framework.fn.validation.isValid(objElements[intCounter]);
							
							if (!boolValid) {
								boolFormValid		= false;
								
								$(objWrapper)
									.fadeIn();
							} else {
								$(objWrapper)
									.fadeOut();
							}
						}
					}
					
					if (boolFormValid) {
						return true;
					} else {
						return false;
					}
				}, 
				
			getContainer: 
				function(objElement) {
					var objContainer;
					
					// determine what type of node this is, and traverse up to the parent <li>
					if ($(objElement)[0].nodeName.toLowerCase() == "select") {
						objContainer			= $(objElement).parent("div").parent("li");
					} else {
						if ($(objElement).parent("li").length > 0) {
							objContainer			= $(objElement).parent("li");
						} else {
							objContainer			= $(objElement).parent("div").parent("li");
						}
					}
					
					return objContainer;
				}, 
			
			getWrapper:
				function(objElement) {
					var objWrapper;
					var boolSelectBox		= ($(objElement)[0].nodeName.toLowerCase() == "select") ? true : false;
					
					if (boolSelectBox) {
						objWrapper				= $(objElement).parent("div").parent("li").find(".validation-tooltip[data-element='" + $(objElement).attr("id") + "']");
					} else {
						if ($(objElement).parent("li").length > 0) {
							objWrapper				= $(objElement).parent("li").find(".validation-tooltip[data-element='" + $(objElement).attr("id") + "']");
						} else {
							objWrapper				= $(objElement).parent("div").parent("li").find(".validation-tooltip[data-element='" + $(objElement).attr("id") + "']");
						}
					}
					
					return objWrapper;
				}, 

			isValid:
				function(objElement) {
					var boolValid			= true;
					var boolSelectBox		= ($(objElement)[0].nodeName.toLowerCase() == "select") ? true : false;
					
					if (boolSelectBox) {
						if ($(objElement)[0].selectedIndex == 0) {
							boolValid			= false;
						}
					} else {
						if ($(objElement).val().length == 0) {
							boolValid			= false;
						}
					}
					
					return boolValid;
				}
		}, 
		viewchange: {
			loaderControl:
				function(boolShow) {
					if (boolShow) {
						$("#loader")
							.css({"opacity": 0, "display": "block"})
							.animate(	{"opacity": 1}, 
										500);
					} else {
						$("#loader")
							.animate(	{"opacity": 0}, 
										500, 
										function() {
											$(this).css("display", "none");
										});
					}
				}, 
				
			retrieve:
				function(strConfNum, strLastName, fncSuccess, fncFailure) {
					framework.fn.viewchange.loaderControl(true);
					
					$.post(	"/fetch/vcc/reservation/", 
							{
								"strConfNum":	strConfNum, 
								"strLastName":	strLastName
							}, 
							function(objData) {
								framework.fn.viewchange.parse(objData, fncSuccess, fncFailure);
							}, 
							"json");
				}, 
				
			parse:
				function(objData, fncCallback, fncFailure) {
					framework.fn.viewchange.loaderControl(false);
					
					if ((typeof(objData) == "object") && (objData.success == true)) {
						fncCallback(objData);
					} else {
						fncFailure();
					}
				}, 
				
			callbacks: {
				view: {
					success: 
						function(objData) {
							if ((typeof(objData) == "object") && (objData.success == true)) {
								if ($.template["tplView"] == undefined) {
									$.template("tplView", framework.templates.view);
								}
								
								$("#frmView div.slides>ol>li:last-child").html($.tmpl("tplView", objData));
								$("#frmView div.slides>ol")
									.animate(	{"left": "-337px"}, 
												500);
							} else {
								$("#frmView div.error").slideDown();
							}
						}, 
					failure: 
						function() {
							$("#frmView div.error").slideDown();
						}
				}, 
				change: {
					success: 
						function(objData) {
							if ((typeof(objData) == "object") && (objData.success == true)) {
								$("#frmVCCSubmit input[name='action']").val("change");
								$("#frmVCCSubmit input[name='strConfNum']").val(objData.confnum);
								$("#frmVCCSubmit input[name='strLastName']").val(objData.lastname);
								$("#frmVCCSubmit").submit();
							} else {
								$("#frmChange div.error").slideDown();
							}
						}, 
					failure: 
						function() {
							$("#frmChange div.error").slideDown();
						}
				}, 
				cancel: {
					success: 
						function(objData) {
							if ((typeof(objData) == "object") && (objData.success == true)) {
								//$("#frmVCCSubmit input[name='action']").val("cancel");
								$("#frmVCCSubmit input[name='action']").val("view");
								$("#frmVCCSubmit input[name='strConfNum']").val(objData.confnum);
								$("#frmVCCSubmit input[name='strLastName']").val(objData.lastname);
								$("#frmVCCSubmit").submit();
							} else {
								$("#frmCancel div.error").slideDown();
							}
						}, 
					failure: 
						function() {
							$("#frmCancel div.error").slideDown();
						}
				}
			}
		}, 
		reservations: {
			parseTime:
				function(strTime) {
					var arrParts;
					var intHours				= 0;
					var intMinutes				= 0;
					var boolMorning				= false;
					
					if ((strTime.indexOf(":") > 0) && (strTime.indexOf(" ") > 0)) {
						// split the am/pm suffix off (XX:XX PM) at the space
						arrParts					= strTime.split(" ");
						boolMorning					= ((arrParts[1].toLowerCase() == "pm") ? false : true);
						
						// split first part into an array (XX:XX) at the colon
						arrParts					= arrParts[0].split(":");
						
						if (arrParts.length == 2) {
							intHours					= parseInt(arrParts[0], 10);
							intMinutes					= parseInt(arrParts[1], 10);
							
							if (!boolMorning) {
								if (intHours != 12) {
									intHours					+= 12;
								}
							} else if (boolMorning) {
								if (intHours == 12) {
									intHours					= 0;
								}
							}
						}
					}
					
					return ((intHours < 10) ? ("0" + intHours) : intHours) + ":" + ((intMinutes < 10) ? ("0" + intMinutes) : intMinutes) + ":00";
				}, 
				
			getLocationHours:
				function(strLocationAbbrev, dtTargetTime) {
					var strOpenTime, strCloseTime;
					var boolOvernight			= false;
					var strOpenHour				= "";
					var strCloseHour			= "";
					var dtOpenTime				= new Date();
					var dtCloseTime				= new Date();
					var dtCloseTimePrevDay		= new Date();
					var dtOpenTimePrevDay		= new Date();
					
					for (var intCounter = 0; intCounter < framework.props.hours.length; intCounter++) {
						if (framework.props.hours[intCounter].abbrev == strLocationAbbrev) {
							for (var intHourCounter = 0; intHourCounter < framework.props.hours[intCounter].hours.length; intHourCounter++) {
								if (framework.props.hours[intCounter].hours[intHourCounter].day == dtTargetTime.getDay()) {
									strOpenTime				= dtTargetTime.getFullYear() + "-" + (dtTargetTime.getMonth() + 1) + "-" + dtTargetTime.getDate() + " " + ((framework.props.hours[intCounter].hours[intHourCounter].open < 10) ? ("0" + framework.props.hours[intCounter].hours[intHourCounter].open) : framework.props.hours[intCounter].hours[intHourCounter].open) + ":00:00";
									strCloseTime			= dtTargetTime.getFullYear() + "-" + (dtTargetTime.getMonth() + 1) + "-" + dtTargetTime.getDate() + " " + ((framework.props.hours[intCounter].hours[intHourCounter].close < 10) ? ("0" + framework.props.hours[intCounter].hours[intHourCounter].close) : framework.props.hours[intCounter].hours[intHourCounter].close) + ":00:00";

									dtOpenTime				= Date.parse(strOpenTime);
									dtCloseTime				= Date.parse(strCloseTime);
									
									// overnight?
									if (framework.props.hours[intCounter].hours[intHourCounter].close < 12) {
										// increment to the next day
										boolOvernight			= true;
										dtCloseTimePrevDay		= new Date(dtCloseTime.getTime());
										dtCloseTime.setDate(dtCloseTime.getDate() + 1);

										dtOpenTimePrevDay.setTime(dtOpenTime.getTime());
										dtOpenTimePrevDay.setDate(dtOpenTimePrevDay.getDate() - 1);
									}
									
									if (dtOpenTime.getHours() >= 12) {
										strOpenHour				= (dtOpenTime.getHours() - 12) + "PM";
									} else {
										strOpenHour				= ((dtOpenTime.getHours() == 0) ? "12" : dtOpenTime.getHours()) + "AM";
									}
									if (dtCloseTime.getHours() >= 12) {
										strCloseHour			= (dtCloseTime.getHours() - 12) + "PM";
									} else {
										strCloseHour			= ((dtCloseTime.getHours() == 0) ? "12" : dtCloseTime.getHours()) + "AM";
									}
									break;
								}
							}
						}
					}
					
					return {open: dtOpenTime, openprev: dtOpenTimePrevDay, close: dtCloseTime, closeprev: dtCloseTimePrevDay, openhour: strOpenHour, closehour: strCloseHour, overnight: boolOvernight};
				}, 
				
			checkHours:
				function() {
					var boolPickupAllowed	= false;
					var boolReturnAllowed	= false;
					var dtPickupTime		= new Date();
					var dtReturnTime		= new Date();
					var strPickupTime		= $("#dtPickupDate").val() + " " + framework.fn.reservations.parseTime($("#dtPickupTime").val());
					var strReturnTime		= $("#dtReturnDate").val() + " " + framework.fn.reservations.parseTime($("#dtReturnTime").val());
					var objPickupTimes;
					var objReturnTimes;
					var strPickupLocation	= $("#strPickupLocation").val();
					var strReturnLocation	= $("#strReturnLocation").val();
					
					if (strReturnLocation.length == 0) {
						strReturnLocation		= strPickupLocation;
					}
					
					if ((strPickupLocation.length) && (strReturnLocation.length)) {
						// set times
						dtPickupTime			= Date.parse(strPickupTime);
						dtReturnTime			= Date.parse(strReturnTime);
						
						objPickupTimes			= framework.fn.reservations.getLocationHours(strPickupLocation, dtPickupTime);
						objReturnTimes			= framework.fn.reservations.getLocationHours(strReturnLocation, dtReturnTime);
						
						if ((dtPickupTime >= objPickupTimes.open) && (dtPickupTime <= objPickupTimes.close)) {
							// valid
							framework.fn.validation.hide($("#dtPickupTime"));
							boolPickupAllowed		= true;
						} else {
							if ((objPickupTimes.overnight) && (dtPickupTime <= objPickupTimes.closeprev) && (dtPickupTime >= objPickupTimes.openprev)) {
								// valid
								boolPickupAllowed		= true;
								framework.fn.validation.hide($("#dtPickupTime"));
							} else {
								// invalid
								boolPickupAllowed		= false;
								framework.fn.validation.show_generic($("#dtPickupTime"), "Your chosen pick-up location is only open between the hours of " + objPickupTimes.openhour + " and " + objPickupTimes.closehour + ".");
							}
						}

						if ((dtReturnTime >= objReturnTimes.open) && (dtReturnTime <= objReturnTimes.close)) {
							// valid
							boolReturnAllowed		= true;
							framework.fn.validation.hide($("#dtReturnTime"));
						} else {
							if ((objReturnTimes.overnight) && (dtReturnTime <= objReturnTimes.closeprev) && (dtReturnTime >= objReturnTimes.openprev)) {
								// valid
								boolReturnAllowed		= true;
								framework.fn.validation.hide($("#dtReturnTime"));
							} else {
								// invalid
								boolReturnAllowed		= false;
								framework.fn.validation.show_generic($("#dtReturnTime"), "Your chosen return location is only open between the hours of " + objReturnTimes.openhour + " and " + objReturnTimes.closehour + ".");
							}
						}
					} else {
						// error, no locations selected
						boolPickupAllowed		= false;
						boolReturnAllowed		= false;
					}
					
					if ((!boolPickupAllowed) || (!boolReturnAllowed)) {
						return false;
					} else {
						return true;
					}
				}, 
				
			checkDropFees: 
				function(strPickupAbbrev, strReturnAbbrev) { 
					var objResponse				= {found: false, allowed: true, message: ""};
					var intCounter, intFeeCounter;
					
					if ((strPickupAbbrev.length) && (strReturnAbbrev.length > 0)) {
						for (intCounter = 0; intCounter < framework.props.dropfees.length; intCounter++) {
							if ((framework.props.dropfees[intCounter].abbrev == strPickupAbbrev) && (framework.props.dropfees[intCounter].fees.length)) {
								for (intFeeCounter = 0; intFeeCounter < framework.props.dropfees[intCounter].fees.length; intFeeCounter++) {
									if (framework.props.dropfees[intCounter].fees[intFeeCounter].abbrev == strReturnAbbrev) {
										objResponse.found		= true;

										if (framework.props.dropfees[intCounter].fees[intFeeCounter].allowed == 1) {
											objResponse.allowed		= true;
											
											if (framework.props.dropfees[intCounter].fees[intFeeCounter].fee > 0) {
												objResponse.message		= "You will be charged an additional $" + framework.props.dropfees[intCounter].fees[intFeeCounter].fee + " to return your vehicle to this location.";
											}
										} else {
											objResponse.allowed		= false;
										}
										break;
									}
								}
							}
						}
					}
					
					return objResponse;
				}, 
				
			viewChangeReservation:
				function() {
					var txtHTML			= $("#viewchange-modal").html();
					
					$.prompt(	txtHTML, 
								{
									show: "slideDown", 
									promptspeed: 1000, 
									overlayspeed: 50, 
									top: "0%", 
									buttons: {}, 
									opacity: 0.1, 
									focus: 1, 
									persistent: false
								});
				}, 

			changeItinerary:
				function() {
					var txtHTML			= $(".itinerary-modal-wrap").html();
					
					$.prompt(	txtHTML, 
								{
									show: "slideDown", 
									promptspeed: 1000, 
									overlayspeed: 50, 
									top: "0%", 
									buttons: {}, 
									opacity: 0.1, 
									focus: 1, 
									persistent: false, 
									loaded: function() { 
										var dtCurDate			= new Date();
										
										$(".jqi .itinerary-modal select")
											.selectbox({
												effect: "fade", 
												speed: 150
											});
										$(".jqi .itinerary-modal ul>li.dates>.datepicker.pickup")
											.datepicker({numberOfMonths: 2, showButtonPanel: false, altField: $(".jqi input[name='dtNewPickupDate']"), minDate: dtCurDate, defaultDate: $(".jqi input[name='dtNewPickupDate']").val(), onSelect: framework.fn.datetime.setMinModalReturnDate});
										$(".jqi .itinerary-modal ul>li.dates>.datepicker.return")
											.datepicker({numberOfMonths: 2, showButtonPanel: false, altField: $(".jqi input[name='dtNewReturnDate']"), minDate: new Date(dtCurDate.getTime() + 86400000), defaultDate: $(".jqi input[name='dtNewReturnDate']").val()});
										$(".jqi .loading").fadeOut();
										$(".jqi ul")
											.css({"opacity": 0, "visibility": "visible"})
											.animate({"opacity": 1}, 500);
									}
								});
				}, 
				
			toggleAddon: 
				function() {
					var intThisID			= parseInt($(this).attr("rel"));
					var objQuantity			= $("#intQuantity_" + intThisID);
					
					if ($("#chkService_" + intThisID).hasClass("required")) {
						var strReason			= $("#chkService_" + intThisID).attr("data-reason");
						
						$("#chkService_" + intThisID)
							.attr("checked", true);
						$(this)
							.removeClass("selected")
							.addClass("selected");
						
						// let's find out why this service is required
						if (strReason.length) {
							alert(strReason);
						} else {
							alert("This item is required and cannot be removed.");
						}
					} else {
						if ($("#chkService_" + intThisID).attr("checked")) {
							$("#chkService_" + intThisID)
								.attr("checked", false);
							$(this)
								.removeClass("selected");
								
							if (objQuantity.length) {
								$(this)
									.parents("div.controls")
									.siblings("div.qty")
									.find("select")
										.val("0");
								//$.uniform.update(objQuantity[0]);
							}
						} else {
							$("#chkService_" + intThisID)
								.attr("checked", true);
							$(this)
								.removeClass("selected")
								.addClass("selected");
							
							if ((objQuantity.length) && (parseInt($(objQuantity).val()) == 0)) {
								$(this)
									.parents("div.controls")
									.siblings("div.qty")
									.find("select")
										.val("1");
								//$.uniform.update(objQuantity[0]);
							}
						}
					}
					
					framework.fn.reservations.updateCosts();
				}, 
			
			dropdownToggle: 
				function() {
					if (parseInt($(this).val()) > 0) {
						$(this)
							.parents("div.qty")
							.siblings("div.controls")
							.find("input[type='checkbox']")
							.attr("checked", true)
							.siblings("a")
							.removeClass("selected")
							.addClass("selected");
					} else {
						$(this)
							.parents("div.qty")
							.siblings("div.controls")
							.find("input[type='checkbox']")
							.attr("checked", false)
							.siblings("a")
							.removeClass("selected");
					}
					
					framework.fn.reservations.updateCosts();
				}, 
				
			updateCosts:
				function() { 
					var objElements			= $("fieldset>ol>li>div.controls>input[type='checkbox']");
					var objQuantity;
					var objRequest			= {};
					var intServiceID		= 0;
					var boolEnabled			= 0;
					var intQuantity			= 0;
					
					for (var intCounter = 0; intCounter < objElements.length; intCounter++) {
						intServiceID			= parseInt($(objElements[intCounter]).val());
						boolEnabled				= ($(objElements[intCounter]).attr("checked") ? 1 : 0);
						objQuantity				= $("#intQuantity_" + intServiceID);
						
						if (objQuantity.length > 0) {
							intQuantity				= parseInt($(objQuantity).val());
						} else {
							intQuantity				= 0;
						}
						
						objRequest["service-id-" + intServiceID]			= intServiceID;
						objRequest["service-enabled-" + intServiceID]		= boolEnabled;
						
						if (intQuantity > 0) {
							objRequest["service-qty-" + intServiceID]			= intQuantity;
						}
					}
					
					$.post(	"/reservation/update/", 
							objRequest, 
							framework.fn.reservations.parseCosts, 
							"json");
				}, 
				
			parseCosts: 
				function(objData) {
					var txtHTML				= "";
					var dblRateDiscount		= 0;
					var boolShowCategory	= false;
					
					for (var strKey in objData["costs-types"]) {
						boolShowCategory		= false;
						
						for (var strSubKey in objData["costs"]) {
							if ((objData["costs"][strSubKey].attributes.type == objData["costs-types"][strKey].id) && (objData["costs"][strSubKey].attributes["rate-total"] > 0)) {
								boolShowCategory		= true;
								break;
							}
						}
						// failsafe
						if ((boolShowCategory == false) && (objData["costs-types"][strKey].base == 1)) {
							boolShowCategory		= true;
						}
						
						if (boolShowCategory) {
							txtHTML					+=	"<h3><span>$" + objData["costs-types"][strKey].total + "</span>" + objData["costs-types"][strKey].title + "</h3>\r\n";
							txtHTML					+=	"<ol class=\"costs\">\r\n";
							
							if (objData["costs-types"][strKey].base == 1) {
								txtHTML					+=	"\t<li>\r\n";
								txtHTML					+=	"\t\t<span>$" + objData.stage1.rates.total + "</span>" + objData.stage1.rates.duration + " Day Rental\r\n";
								
								/*
								txtHTML					+=	"\t\t<ol>\r\n";

								for (var intCounter = 0; intCounter < objData.stage1.rates.dates.length; intCounter++) {
									txtHTML					+=	"\t\t\t<li" + ((intCounter == (objData.stage1.rates.dates.length - 1)) ? " class=\"end\"" : "") + ">\r\n";
									txtHTML					+=	"\t\t\t\t" + ((objData.stage1.rates.dates[intCounter].weekly) ? ("Weekly Rate (" + objData.stage1.rates.dates[intCounter].date + ")") : ("Daily Rate (" + objData.stage1.rates.dates[intCounter].date + ")")) + ": <span>$" + objData.stage1.rates.dates[intCounter].rate + "</span>\r\n";
									txtHTML					+=	"\t\t\t</li>\r\n";
								}

								txtHTML					+=	"\t\t</ol>\r\n";
								*/
								
								if (parseFloat(objData.stage1.rates["discount-total"]) > 0) {
									txtHTML				+=	"\t\t<div class=\"discount-notice\">Your discount code has saved you <strong><u>$" + objData.stage1.rates["discount-total"] + "</u></strong> by granting you a discounted daily rate!</div>";
								}

								txtHTML					+=	"\t</li>\r\n";
							}
							for (var strSubKey in objData["costs"]) {
								if ((objData["costs"][strSubKey].attributes.type == objData["costs-types"][strKey].id) && (objData["costs"][strSubKey].attributes["selected"])) {
									txtHTML					+=	"\t<li" + ((objData["costs"][strSubKey].attributes["discounted"]) ? " class=\"discounted\"" : "") + ">\r\n";
									txtHTML					+=	"\t\t<span>" + ((objData["costs"][strSubKey].attributes["rate-total"] == 0) ? "FREE" : ("$" + objData["costs"][strSubKey].attributes["rate-total"])) + "</span>" + objData["costs"][strSubKey].title + (((objData["costs"][strSubKey].attributes["qty-enabled"] == 1) && (objData["costs"][strSubKey].attributes["selected-qty"] > 0)) ? (" (x" + objData["costs"][strSubKey].attributes["selected-qty"] + ")") : "") + "\r\n";
									
									if ((objData["costs"][strSubKey].attributes["discounted"]) && (objData["costs"][strSubKey].attributes["discount-rate"]) && (objData["costs"][strSubKey].attributes["discount-rate-total"])) {
										txtHTML					+= "\t\t<div class=\"discount-notice\">Your discount code has saved you a total of <strong><u>$" + objData["costs"][strSubKey].attributes["discount-rate"] + "</u></strong> off of this product, service or fee!</div>";
									}
									
									txtHTML					+=	"\t</li>\r\n";
								}
							}
							
							txtHTML					+=	"</ol>\r\n";
						}
					}
					
					// add in taxes
					for (var strKey in objData["taxes"]) {
						if (parseInt(objData["taxes"][strKey]) > 0) {
							switch (strKey.toLowerCase()) {
								case "tax-surcharge" : 
									txtHTML					+=	"<h3 class=\"no-group\"><span>$" + objData["taxes"][strKey] + "</span>Airport Surcharge (" + (objData["stage1"]["surcharge-pct"] * 100) + "%)</h3>\r\n";
									break;
	
								case "tax-sales-tax" : 
									txtHTML					+=	"<h3 class=\"no-group\"><span>$" + objData["taxes"][strKey] + "</span>Sales Tax (" + (objData["stage1"]["sales-tax-pct"] * 100) + "%)</h3>\r\n";
									break;
	
								case "tax-misc-tax2" : 
									txtHTML					+=	"<h3 class=\"no-group\"><span>$" + objData["taxes"][strKey] + "</span>Misc Tax #2</h3>\r\n";
									break;
	
								case "tax-misc-tax3" : 
									txtHTML					+=	"<h3 class=\"no-group\"><span>$" + objData["taxes"][strKey] + "</span>Misc Tax #3</h3>\r\n";
									break;
							}
						}
					}
					
					// add in grand total
					txtHTML						+=	"<h3 class=\"total\"><span>$" + objData["grand-total"] + "</span>Total Due</h3>\r\n";
					
					// add in costs
					$("#sidebar-costs").html(txtHTML);
				}
		}, 
		slider: {
			showSliderImage:
				function(intImageNum) {
					if (!framework.props.slider.animating) {
						framework.props.slider.animating				= true;
						framework.props.slider.currentSliderImage		= intImageNum;
						
						$("#slider-text>p>strong").remove();			// remove all text nodes, if any
						$("#slider-images")
							.animate(	{"top": -(framework.props.slider.currentSliderImageHeight * intImageNum) + "px"}, 
										framework.props.slider.currentSliderImageAnimSpeed, 
										"easeInOutExpo", 
										function() { 
											framework.fn.slider.showSliderMessage($("#slider-images>li:eq(" + framework.props.slider.currentSliderImage + ") img").attr("title")); 
										});
					}
				}, 
				
			showNextSliderImage:
				function() { 
					if (!framework.props.slider.animating) {
						if (framework.props.slider.currentSliderImage + 1 > (framework.props.slider.currentSliderImageCount - 1)) {
							framework.props.slider.currentSliderImage		= 0;
						} else {
							framework.props.slider.currentSliderImage++;
						}
						
						framework.fn.slider.hideSliderMessage(	function() { 
																	framework.fn.slider.showSliderImage(framework.props.slider.currentSliderImage) 
																});
					}
				}, 
				
			showSliderMessage: 
				function(txtMessage) {
					var arrMessageParts;
					
					if (txtMessage.indexOf("|") > -1) {
						arrMessageParts		= txtMessage.split("|");
					} else {
						arrMessageParts		= [txtMessage];
					}
					
					if (arrMessageParts.length) {
						framework.props.slider.currentMessage		= arrMessageParts;
						framework.props.slider.currentMessageLine	= 0;
						framework.props.slider.currentMessageChar	= 0;
						
						framework.fn.slider.showSliderMessageLine();
					}
				}, 
				
			showSliderMessageLine: 
				function() {
					var strLineText		= framework.props.slider.currentMessage[framework.props.slider.currentMessageLine];
					var strCurText		= "";
					if (framework.props.slider.currentMessageChar <= (strLineText.length - 1)) {
						if (framework.props.slider.currentMessageChar == 0) {
							$("#slider-text>p").append("<strong></strong>");
							strCurText			= "";
						} else {
							strCurText			= $($("#slider-text>p>strong")[framework.props.slider.currentMessageLine]).html();
						}
						
						$($("#slider-text>p>strong")[framework.props.slider.currentMessageLine]).html(strCurText + strLineText.substr(framework.props.slider.currentMessageChar, 1));
						
						framework.props.slider.currentMessageChar++;
						
						framework.props.slider.currentMessageTimer		= setTimeout(framework.fn.slider.showSliderMessageLine, framework.props.slider.currentMessageShowDelay);
					} else {
						if ((framework.props.slider.currentMessageLine + 1) <= (framework.props.slider.currentMessage.length - 1)) {
							framework.props.slider.currentMessageLine++;
							framework.props.slider.currentMessageChar		= 0;
							
							framework.fn.slider.showSliderMessageLine();
						} else {
							clearTimeout(framework.props.slider.currentSliderImageDelay);
							clearTimeout(framework.props.slider.currentMessageTimer);
							
							framework.props.slider.animating				= false;
							framework.props.slider.currentSliderImageTimer	= setTimeout(framework.fn.slider.showNextSliderImage, framework.props.slider.currentSliderImageDelay);
						}
					}
				}, 
				
			hideSliderMessage:
				function(fncCallback) { 
					var objElements		= $("#slider-text>p>strong");
					var intLongestLine	= 0;
					var intLongestIndex	= 0;
					
					if (objElements.length) {
						for (var intCounter = 0; intCounter < objElements.length; intCounter++) {
							if ($(objElements[intCounter]).html().length > intLongestLine) {
								intLongestLine		= $(objElements[intCounter]).html().length;
								intLongestIndex		= intCounter;
							}
						}
						
						for (var intCounter = 0; intCounter < objElements.length; intCounter++) {
							framework.fn.slider.hideSliderMessageLine(objElements[intCounter], ((intCounter == intLongestIndex) ? fncCallback : function() {}));
						}
					}
				}, 
				
			hideSliderMessageLine:
				function(objElement, fncCallback) {
					var strCurLine		= $(objElement).html();
					
					for (var intCounter = 0; intCounter < strCurLine.length; intCounter++) {
						if (intCounter == (strCurLine.length - 1)) {
							setTimeout(function() { framework.fn.slider.removeSliderMessageCharacter(objElement, true, fncCallback); }, framework.props.slider.currentMessageHideDelay * (intCounter + 1));
						} else {
							setTimeout(function() { framework.fn.slider.removeSliderMessageCharacter(objElement, false, function() {}); }, framework.props.slider.currentMessageHideDelay * (intCounter + 1));
						}
					}
				}, 
				
			removeSliderMessageCharacter:
				function(objElement, boolRemoveElement, fncCallback) {
					var strCurLine		= $(objElement).html();
					
					if (boolRemoveElement) {
						$(objElement).css("visibility", "hidden");
					} else {
						$(objElement).html(strCurLine.substr(0, strCurLine.length - 1));
					}
					
					fncCallback();
				}
		}
	}
};
