
/// <reference path="../../../../../jQuery/1.3.2/jquery-1.3.2-vsdoc.js" />


/*
 *****************************************************************
 * QuickSearch
 *****************************************************************
 *
 * Provides functionality to the quickserach control, including the hover state changes, and click propogation
 *
 * Author : Rob Earlam
 */

// Check that namespace into which the Class definition will be creates has been defined & if not then create
if (!manheim.global.isNamespaceDefined("manheim.portfolio.lexus.display.controls")) manheim.global.createNamespace("manheim.portfolio.lexus.display.controls", "1.0");


manheim.portfolio.lexus.display.controls.QuickSearch = Object.subClass(
	{
		/*
		 =============================
		 CONSTANTS
		 =============================
		 */
			CONST_CLASS_NAME_UI_DROP_DOWN : "ui-drop-down-menu",
			CONST_CLASS_NAME_UI_DROP_DOWN_OPEN : "ui-drop-down-menu-open",
	
	
		/*
		 =============================
		 CONSTRUCTOR
		 =============================
		 */
			init : function ()
			{
				//scope pointer
				var _this = this;
				
				//setup the hover functionality
				_this._configureHoverFunctionality();
				
				//setup the click functionality
				_this._configureClickFunctionality();
			},
		
		
		
		/*
		 =============================
		 METHODS USED TO HANDLE THE PROPAGATION OF THE CHECKBOX CLICKS
		 =============================
		 */
			//bind the click events
			_configureClickFunctionality : function ()
			{
				//get the local vars
				var _this = this;
				var container = $('div.quick-search-models');		
				
				//bind the click event to all checkbox change events
				container.find('input.check').click(function(event) {
					event.stopPropagation();
					_this._checkbox_OnClick($(this));
				});
				
				//bind the click event to the checkbox container div's but stop the propogation to stop the event being called twice
				//if the user clicks directly on the checkbox
				container.find('div.active-checkbox-container').click(function(event) {
					event.stopPropagation();
					var checkbox = $(this).find('input:first');
					if (checkbox.attr('checked')) {
						checkbox.removeAttr('checked');
					}
					else {
						checkbox.attr('checked', 'true');
					}
					_this._checkbox_OnClick(checkbox);
				});
				
				// Find all 'a.explore-model-range' links and swallow click event 
				// otherwise when clicked the event propogates up the DOM and triggers '_checkbox_OnClick' on the range level checkbox as fires top-level parent 'div.active-checkbox-container' click event
				container.find("a.explore-model-range").click(function(event)
				{
					event.stopPropagation();
				});
				
			},	
			
			
			
			//checkbox click event handler
			_checkbox_OnClick : function (checkbox)
			{
				//get the checkboxes container
				var container = checkbox.closest('div.active-checkbox-container');
				var selected = checkbox.attr('checked');	//indicates whether we're selecting or deselecting
			
				//if this is a model check box set the selected status of all child checkboxes
				
				if(checkbox.hasClass('derivative'))
				{ 
					var parentModelId = '#' + checkbox.attr('name').replace('cb-is-f-', 'cb-2-cur-');				
					var parentmodelCheckbox = container.parent().find(parentModelId);
					if(container.find('input.derivative:checked').length > 0)
						parentmodelCheckbox.attr('checked', 'true');
					else
						parentmodelCheckbox.removeAttr('checked');	
				}
				else
				{
					container.find('input').each(function() {
						if(selected)
							container.find('input:not(:checked)').attr('checked', 'true');
						else
							container.find('input:checked').removeAttr('checked');
					});		
				}

				//if this is a model selection then we need to update to range level
				container.parents('div.active-checkbox-container').each(function() {
					//get the range checkbox and range container
					var rangeContainer = $(this);
					var rangeCheckbox = rangeContainer.find('input.range');
					var modelCheckboxContainer = rangeContainer.find('div.ui-treelist-level-2-container');
					var derivativeCheckboxContainer = modelCheckboxContainer.find('div.derivatives-container')
					var allCheckbox = modelCheckboxContainer.find('input.check-all');
										
					//handle the selection of the all checkbox
					if(checkbox.val() == 'all') {
						if (selected)
							modelCheckboxContainer.find('input:not(:checked)').attr('checked', 'true');
						else
							modelCheckboxContainer.find('input:checked').removeAttr('checked');
					}
					else {
						//now if we have selected all manually then check the 'all models' checkbox
						if(modelCheckboxContainer.find('input:not(:checked)').length == 1)				
							allCheckbox.attr('checked', 'true');
						else
							allCheckbox.removeAttr('checked');
					}
					
					var derivativeParentInput = derivativeCheckboxContainer.parent('div.active-checkbox-container');
					if(derivativeCheckboxContainer.find('input:checked').length > 0)
						derivativeParentInput.find('input.model').attr('checked', 'true');
					else
						derivativeParentInput.find('input.model').removeAttr('checked');
						
					
					//if we have any children checked then this must be checked
					if (modelCheckboxContainer.find('input:checked').length > 0)
						rangeCheckbox.attr('checked', 'true');
					else
						rangeCheckbox.removeAttr('checked');
				});
				

				//update the 'Please Select', 'Selected Models' label
				var selectedModelCount = $("div.quick-search-models > div.ui-treelist-container > div.ui-treelist-level-1-container > div.level-1-panel-body > div.model-item > div.model-item-body > input.check:checked").length;
				var defaultLabel = $('h6.default-text');
				if (selectedModelCount > 0) {
					defaultLabel.html(selectedModelCount + ' selected');
				}
				else {
					defaultLabel.html('Please select');
				}

				//update the selected derivativeIds
				var globalContainer = $('div.summary-quick-search, div.panel-quick-search');
				var selectedDerivativesInput = globalContainer.find('input.selected-models');
				var selectedDerivatives = '';
				globalContainer.find('input.derivative:checked').each(function() {
					selectedDerivatives = selectedDerivatives + $(this).val() + ',';
				});							
				selectedDerivativesInput.val(selectedDerivatives);				
			},			
		
		
		
		
		
		/*
		 =============================
		 METHODS USED TO GIVE THE HOVER FUNCTIONALITY
		 =============================
		 */
			_configureHoverFunctionality : function ()
			{
				var _this = this;
				
				$("div.ui-drop-down-menu > div.quick-search-summary").click(
					function(event) {
						_this._toggleHoverState($(this).parent("div.ui-drop-down-menu"));
					}
				);
					
				$("div.quick-search").hover(
					function() { },
					function() {
						_this._closeHoverState($(this));
					}
				);		
			},
			
			
			_toggleHoverState : function (container) 
			{
				var _this = this;
				if (container.hasClass(_this.CONST_CLASS_NAME_UI_DROP_DOWN_OPEN)) {
					container.removeClass(_this.CONST_CLASS_NAME_UI_DROP_DOWN_OPEN);
				}
				else {
					container.addClass(_this.CONST_CLASS_NAME_UI_DROP_DOWN_OPEN)
				}		
			},


			_closeHoverState: function(container)
			{
				var _this = this;
				container.removeClass(_this.CONST_CLASS_NAME_UI_DROP_DOWN_OPEN);
			}
	}
);

/*
**************
* IMPORTANT :: All runtime instance declarations MUST be bound to document 'js-class-setup' event
**************
*/

$(document).bind("js-class-setup", function() {
	// Setup runtime namespace if doesn't exist
	if (!manheim.global.isNamespaceDefined("manheim.portfolio.runtime.display.controls")) manheim.global.createNamespace("manheim.portfolio.runtime.display.controls", "1.0");

	// Create instance
	manheim.portfolio.runtime.display.controls.QuickSearch = new manheim.portfolio.lexus.display.controls.QuickSearch();
});

/// <reference path="../../../../jQuery/1.3.2/jquery-1.3.2-vsdoc.js" />

/**
*
* mp-search-configuration
*
* This class manages the search criterion on the server enviroment
*
* Hooks up the change event on mp-control-data control, via ajax:
*	- Validates search criteria selection.
*	- Re-binds user search on the their session on the server.
*	- Responds with a stock count of their current search crition selection.
*	- Refreshs ui diplay with stock count.
*
* Author : Marc Lancashire
*/

	// Check that namespace into which the Class definition will be creates has been defined & if not then create

	if (!manheim.global.isNamespaceDefined("manheim.portfolio.common.display")) manheim.global.createNamespace("manheim.portfolio.common.display", "1.0");

	// Class definition : 

	manheim.portfolio.common.display.SearchConfiguration = Object.subClass
	(
		{
			/*
			=============================
			CONSTANTS
			=============================
			*/
			DEBUG								: false,

			ARGUMENT_WORKFLOW					: "wflw",
			
			WORKFLOW_ACTION						: "_re_pr",
			
			MODE_ALLWAYS_BIND					: true,
			
			SELECTOR_FORM						: "form.mp-search-count",
			SELECTOR_BIND_INPUTS				: "form.mp-search-count input.mp-control-data, form.mp-search-count select.mp-control-data",
			SELECTOR_DATA_INPUTS				: "input:text.mp-control-data, select.mp-control-data, input:checked.mp-control-data, input:selected.mp-control-data, input[type = 'hidden'].mp-control-data",
			SELECTOR_DATACOUNTERS				: "#mp-stock-count",
			SELECTOR_FORM_SUBMITS				: ".validatePostcode",

			ASYNC_WORK_FLOW_TIMER				: 0,
			SEARCH_SYNC_DELAY					: 500,
			
			DEFAULT_INPUT_VALIDATION_RESULT		: true,
			DEFAULT_STATE						: "...",

			/*
			=============================
			CONSTRUCTOR
			=============================
			*/
			init: function() {
				
			},


			/*
			=============================
			PUBLIC MEMBERS
			=============================
			*/
			
			// bind an entire containers data elements
			"bind": function(jqContainer)
			{
				var __this = this;
				
				if (jqContainer.find(this.SELECTOR_FORM).length == 0)
				{
					jqContainer = jqContainer.closest(this.SELECTOR_FORM).parent();
				}
				
				jqContainer.find(this.SELECTOR_BIND_INPUTS).bind("change.stock-count", null , function(e) { __this.OnDataElementChange(e); });
				jqContainer.find(this.SELECTOR_BIND_INPUTS).bind("clear", null , function(e) { __this.clearDataRequestTimeout(e); });
			},
			
			// bind a single data element
			"bindDataElement": function(jqDataElement)
			{
				var __this = this;
				
				jqDataElement.bind("change.stock-count", null , function(e) { __this.OnDataElementChange(e); });
				jqDataElement.bind("clear", null , function(e) { __this.clearDataRequestTimeout(e); });
			},
			
			// carries out a search criteria change event
			OnDataElementChange: function(event) {
				
				this._debugtrace("OnDataElementChange");

				dataElement = $(event.target);

				if (this.MODE_ALLWAYS_BIND || this.ValidateInput(dataElement,false))
				{
					this.GetStockCount(dataElement);
				}
				else
				{
					this.OnInvalidInput(null, dataElement);
				}
			},
			
			
			clearDataRequestTimeout : function  (e)
			{
				clearTimeout(this.ASYNC_WORK_FLOW_TIMER);
			},
			
			
			// carries out a search form submit event
			OnSearchFormSubmit: function(event)
			{
				this._debugtrace("OnSearchFormSubmit");
				
				jqDataElement = ($(event.target).is("form"))? $(event.target) : $(event.target).closest("form"); // this should be a form
				
				var isValid = this.ValidateInput(jqDataElement, true);
				
				if (!isValid)
				{
					this.OnInvalidInput(jqDataElement, null, true);
				}
				else
				{
					jqDataElement.trigger("submit");
				}
				
				return isValid;
			},
			
			
			// validates the users search criteria input
			ValidateInput: function(jqDatalement, throwError) {

				this._debugtrace("ValidateInput");

				return this.DEFAULT_INPUT_VALIDATION_RESULT;
			},

			// called when the users search criteria is invalid, called from form submission and criteria change
			OnInvalidInput: function(jqFormElement, jqDataElement, throwError) {

				this._debugtrace("Invalid Input");

			},

			// carries out a delayed stock count and search criteria re-sync
			GetStockCount: function(jqDataElement) {

				this._debugtrace("GetStockCount");

				clearTimeout(this.ASYNC_WORK_FLOW_TIMER);

				// scope
				var currentScope = this;

				this.ASYNC_WORK_FLOW_TIMER = setTimeout(function() { currentScope._syncSearchCriteria(jqDataElement) }, this.SEARCH_SYNC_DELAY);
			},
			
			// carries out an imedate stock count and search criteria re-sync
			GetStockCountNow: function(jqDataElement)
			{
				this._syncSearchCriteria(jqDataElement);
			},

			// raised on change of the stock count
			OnStockCountChange: function(stockCount) {

				this._debugtrace("Stock Count = " + stockCount + ".");

			},

			/*
			=============================
			PUBLIC SYNC METHODS
			=============================
			*/

			OnSyncBefore: function() {

				this._debugtrace("OnSyncBefore");

				$(this.SELECTOR_DATACOUNTERS).html(this.DEFAULT_STATE);
			},

			OnSyncError: function(XMLHttpRequest, textStatus, errorThrown) {

				this._debugtrace("OnSyncError");
				
				return;
			},

			OnSyncSuccess: function(p_response) {

				this._debugtrace("OnSyncSuccess:{" + p_response + "}");

				var result = eval(p_response);
				
				this.callbackUtilities._processResultControls(result);

				this.OnStockCountChange(p_response);

				return;
			},


			/*
			=============================
			PRIVATE MEMBERS
			=============================
			*/

			// 
			_syncSearchCriteria: function(dataElement) {

				this._debugtrace("_syncSearchCriteria");

				// get parent form
				var formElement = dataElement.parents(this.SELECTOR_FORM);

				// get work flow key from mp-sync-key data item in form
				var wflw = this._workflowKey(formElement);

				// setup ajax call
				$.ajaxManager.clearArguments();

				$.ajaxManager.ajaxSettings.arguments.add(this.ARGUMENT_WORKFLOW, wflw);

				// add search criteria arguments to ajax call
				formElement.find(this.SELECTOR_DATA_INPUTS).each(
					function() {
						var inputElement = $(this);
						$.ajaxManager.ajaxSettings.arguments.add(inputElement.attr("name"), inputElement.val());
					}
				)

				// set url
				$.ajaxManager.updateUrl($.ajaxManager.ajaxSettings.arguments.getString("&"));

				var currentScope = this;

				// bind before send
				$.ajaxManager.onBeforeSend = function() { currentScope.OnSyncBefore() };

				// bind error
				$.ajaxManager.onError = function(XMLHttpRequest, textStatus, errorThrown) { currentScope.OnSyncError(XMLHttpRequest, textStatus, errorThrown) };

				// bind success
				$.ajaxManager.onSuccess = function(p_response) { currentScope.OnSyncSuccess(p_response) };

				// fire ajax request
				$.ajaxManager.makeRequest();
			},

			_workflowKey: function(formElement, workflowAction)
			{
				var wfa = workflowAction;
				if (!wfa)
				{
					wfa = this.WORKFLOW_ACTION;
				}
				
				return manheim.portfolio.global.Utilites.getScopedWorkflowKey(formElement, wfa);
			},

			_debugtrace: function(message, override) {

				if (this.DEBUG || override) {
					alert("[Search Configuration] " + message);
				}
			}

		}
	);

	//alert("manheim.portfolio.common.display.SearchConfiguration");



/// <reference path="../../../../jQuery/1.3.2/jquery-1.3.2-vsdoc.js" />

/**
 *
 * SearchConfiguration
 *
 * This class manages the search configuration status within the client environment
 *
 * Setups up search configuration elements such as sliders, image controls, validation, server search criteria update
 * and dynamic stock count.
 *
 * Author : Marc Lancashire
 */

	// Check that namespace into which the Class definition will be creates has been defined & if not then create
	
	if (!manheim.global.isNamespaceDefined("manheim.portfolio.lexus.display")) manheim.global.createNamespace("manheim.portfolio.lexus.display", "1.0");

	// Class definition : 

	manheim.portfolio.lexus.display.SearchConfiguration = manheim.portfolio.common.display.SearchConfiguration.subClass
	(
		{
			/*
			=============================
			CONSTANTS
			=============================
			*/
			
				"DATA_CATEGORY_PRICE"			: "DATA_CATEGORY_PRICE",
				"DATA_CATEGORY_MILEAGE"			: "DATA_CATEGORY_MILEAGE",
				"DATA_CATEGORY_FUELTYPE"		: "DATA_CATEGORY_FUELTYPE",
				"DATA_CATEGORY_TRANSMISSION"	: "DATA_CATEGORY_TRANSMISSION",
				
				"QUICKSEARCH_FORM_ID"			: "QuickSearchForm",
				
				"SELECTOR_PRICE"			: "div.priceto select.mp-control-data",
				"SELECTOR_MILEAGE"			: "div.odometerto select.mp-control-data",
				"SELECTOR_FUELTYPE"			: "div.transmission input.mp-control-data",
				"SELECTOR_TRANSMISSION"		: "div.fueltype input.mp-control-data",
				
				"EVENT_GRAPH_SELECTION_CHANGE"	: "change.graph-selection-change",
				
				
				"SELECTOR_FORM_SUBMITS"		: "div.validatePostcode",
				"SELECTOR_STOCK_COUNT"		: "#ctl00_spnCount",
				
				"SELECTOR_SEARCH_LOCATION_CONTAINER" : "form#SearchCriteria > div.search-location-panel-container fieldset.search-location-fieldset",
				
				"SELECTOR_INPUT_POSTCODE" : "div.postcode input.postcode",
			
				"SELECTOR_SELECT_DISTANCE" : "div.distance select.mp-control-data",
			
			
			
			
			/*
			 =============================
			 CONSTRUCTOR
			 =============================
			 */
				"init" : function (instanceReferenceString)
				{
					this.instanceString = instanceReferenceString;
				},
			
			
			
			/*
			 =============================
			 CONFIGURATION PROPERTIES (instance configuration)
			 =============================
			 */
				"instanceString" : undefined,
				
				"callbackUtilities" : {},
				
			
			/*
			=============================
			PUBLIC MEMBERS
			=============================
			*/
				
				"bind" : function(jqContainer, containerTargetString, loadEnhancerClassInstance)
				{
					this._super(jqContainer); // call base bind
					
					var __this = this;
					
					var containerTargetString = ((containerTargetString != null) ? containerTargetString : "body");
					
					if (loadEnhancerClassInstance)
					{
						var formContainers		= jqContainer.filter("form");
						
						var nonFormContainers	= jqContainer.filter(":not(form)");
						
						formContainers.bind("submit", function (e){__this._displayLoadingState(e, loadEnhancerClassInstance)});
						
						nonFormContainers.each(
							function (i)
							{
								item = $(this);
								var closestParentForm = item.closest("form");
								closestParentForm.bind("submit", function (e){ __this._displayLoadingState(e, loadEnhancerClassInstance) });
							}
						);
						
					}
					
					
					// Add form submit click functionality to search button
					
					var buttons = jqContainer.find(this.SELECTOR_FORM_SUBMITS);

//						
// [ sIFR button ] activation
//					
//					if ($.browser.msie)
//					{
//						// Create form reference storage array
//						this.jQueryFormObjects = [];
//						
//						// Format link string fragment
//						var linkStringFragment = "javascript:" + this.instanceString + ".handleSifrLinkInternalClick(";
//						
//						// Process buttons
//						buttons.each 
//						(
//							function (i)
//							{
//								var ___this = $(this);
//								
//								// Find child link
//								var link	= ___this.find("a");
//								
//								// Find parent form
//								//var parentForm = ___this.parents("form:first");
//								var parentForm = ___this.closest("form");
//								
//								// Store parent form in reference array
//								__this.jQueryFormObjects.push(parentForm);
//								
//								// Attach href
//								link.attr("href", (linkStringFragment + i + ");"));
//							}
//						)
//					}
					
					
					
					//jqContainer.find(this.SELECTOR_FORM_SUBMITS).bind("click.form-submit", null, function(e) { __this.OnSearchFormSubmit(e); });
					buttons.bind("click", null, function(e) { __this.OnSearchFormSubmit(e); });
					
//
// [ sIFR button ] styling
//					
//					// Style any buttons [ nb: 'this.SELECTOR_FORM_SUBMITS' is actually targeting for buttons tagged as (".validatePostcode") ]
//					sIFR.runDelayedButtonStyling(containerTargetString + " " + this.SELECTOR_FORM_SUBMITS + " " + sIFR.styles.DEFAULT_BUTTON_STYLE_TARGET_STRING_INTERNAL_PATH);
					
					
					
					// add lexus graph item selection change binds
					
					// price
					if (window.json_priceData_level_1)
					{
						jqContainer.find(this.SELECTOR_PRICE).bind(this.EVENT_GRAPH_SELECTION_CHANGE, {hasSummary:true,levelSource:json_priceData_level_1}, function(e){ __this._changeDataDisplaySelection(__this.DATA_CATEGORY_PRICE,e); });
					}
					
					// mileage
					if (window.json_odometer_level_1)
					{
						jqContainer.find(this.SELECTOR_MILEAGE).bind(this.EVENT_GRAPH_SELECTION_CHANGE, {hasSummary:true,levelSource:json_odometer_level_1}, function(e){ __this._changeDataDisplaySelection(__this.DATA_CATEGORY_MILEAGE,e); });
					}
					
					// fuel type
					if (window.json_fuelType_level_1)
					{
						jqContainer.find(this.SELECTOR_FUELTYPE).bind(this.EVENT_GRAPH_SELECTION_CHANGE, {hasSummary:false,levelSource:json_fuelType_level_1}, function(e){ __this._changeDataDisplaySelection(__this.DATA_CATEGORY_FUELTYPE,e); });
					}
					
					// transmission type
					if (window.json_transmissionData_level_1)
					{
						jqContainer.find(this.SELECTOR_TRANSMISSION).bind(this.EVENT_GRAPH_SELECTION_CHANGE, {hasSummary:false,levelSource:json_transmissionData_level_1}, function(e){ __this._changeDataDisplaySelection(__this.DATA_CATEGORY_TRANSMISSION,e); });
					}
				},
				
				
				
					/*
					=============================
					IE 6 : Sifr'd link click handling method
					=============================
					*/
						"jQueryFormObjects" : undefined,
						
						
						"handleSifrLinkInternalClick" : function (id)
						{
							var form = this.jQueryFormObjects[id];
							
							// Escape if no form
							if (!form) return;
							
							// Create event object
							var e		= new jQuery.Event("click"); 
							e.target	= e.currentTarget = form[0];
							
							// Run method
							this.OnSearchFormSubmit(e)
						},
				
				// override base adding bind of postcode
				"bindDataElement" : function(jqDataElement)
				{
					this._super(jqDataElement); // call base bind
					
					var __this = this;
					
					jqDataElement.bind("change.map-refresh", null, function (e) { __this._handlePostcodeChange(e); });
				},
				
				
				"bindLocationMapFeature" : function (locationMapInstance)
				{
					// Store internal reference
					this._locationMapInstance = locationMapInstance;
					
					// Local instance 'hook' reference
					var __this = this;
					
					// Find postcode container
					var container = $(this.SELECTOR_SEARCH_LOCATION_CONTAINER);
					
					//
					// USE 'Change' events as these will be fired when input loses focus AFTER IT HAS BEEN CHANGED
					//
					// Find "postcode input" within "postcode container"
					var pInput = container.find(this.SELECTOR_INPUT_POSTCODE);
					// Bind to change event
					pInput.bind("change.map-refresh", null, function (e) { __this._handlePostcodeChange(e); });
					
					// Find slider control within "postcode container"
					var sDistance = container.find(this.SELECTOR_SELECT_DISTANCE);
					// Bind to change event
					sDistance.bind("change.map-refresh", null, function (e) { __this._handleDistanceChange(e); });
				},

				"ValidateInput" : function(jqDataElement, throwError)
				{
					// validate the postcode
					var isValid = this.ValidatePostcode(jqDataElement, throwError);
					
					// now we've validated the postcode field we need to ensure that there is a model selected, first we need to see what state we're in tho
					if ((jqDataElement[0].id == this.QUICKSEARCH_FORM_ID) && (jqDataElement.find('input:checked').length == 0)) {
						isValid = false;
					}	
					
					// check for the hidden selected models field, if this is present but empty then stop the search from progressing
					var input = $('input.selected-models');
					if((input.length > 0) && (input.val() == '')) {
						isValid = false;
					}
					
					return isValid;
				},
				
				"ValidatePostcode" : function(jqDataElement, throwError)
				{
					// validate the postcode
					var isValid = true;
					var formElement = (jqDataElement.is("form"))? jqDataElement : jqDataElement.closest(this.SELECTOR_FORM);
					var postcodes = formElement.find("input.postcode");

					if (postcodes.length > 0 && manheim.portfolio.global.Utilites.validatePostcode)
					{
						// has postcode
						var postcode = postcodes.val();
						var formattedPostcode = manheim.portfolio.global.Utilites.validatePostcode(postcode)
						isValid = (formattedPostcode != null);
						
						if(isValid)
						{
							//postcodes.unbind();
							
							postcodes.val(formattedPostcode);
							
							var __this = this;
							
							//this.bindDataElement(postcodes);
						}
					}

					return isValid;
				},
				
				// carries out a search criteria change event
				"OnDataElementChange": function(event)
				{
					if (!$(event.currentTarget).hasClass("postcode"))
					{
						this._super(event); // call base
					}
				},
				
				// called when the users search criteria is invalid, called from form submission and criteria change
				"OnInvalidInput": function(jqFormElement, jqDataElement, throwError)
				{
					var _this = this;
					
					this._super(jqFormElement, jqDataElement, throwError); // call base
					
					var containerTargetString = '.ui-lightbox-container div#dvInvalidSearchWarning';
					
					if (throwError)
					{
						// Launch error msg the lightbox
						uiBox_Trigger("#?go=go&width=300&height=160&target=divUvlContainer&source=dvInvalidSearchWarning&displayPosition=viewableCentre");
						
						// Bind the continue button
						var dialogContainer = $(containerTargetString);
						
						var continueButton = dialogContainer.find("div.button-continue");
						
						continueButton.click( function (e) { _this._handleDialogueButtonClick(); } );

//
// [ sIFR button ] activation / styling
//
//
//						// If ie then add href attribute to each buttons internal <a> tag
//						if ($.browser.msie)
//						{
//							var continueLink	= continueButton.find("a");
//							
//							continueLink.attr("href", "javascript:" + this.instanceString + "._handleDialogueButtonClick();");
//						}
//						
//						// Style buttons
//						sIFR.runDelayedButtonStyling(containerTargetString + " " + "div.button-style-1" + " " + sIFR.styles.DEFAULT_BUTTON_STYLE_TARGET_STRING_INTERNAL_PATH);
						
					}
				},
				
				
				"OnStockCountChange" : function(stockCount)
				{
					this._super(stockCount); // call base
					
					//rebind sIFR result count
					/* not required yet, only if we start binding the header result count, at the moment it on changes on change of result tool set.
				    if (sIFR && sIFR.styleResultsListResultsCount)
				    {
						sIFR.styleResultsListResultsCount();
					}
					*/
				},
				
				
			
			
			/*
			=============================
			INTERNAL MEMBERS
			=============================
			*/
				
				"_locationMapInstance" : undefined,
				
			
				/*
				 =============================
				 INTERNAL EVENT HANDLERS
				 =============================
				 */
					"_handleDialogueButtonClick" : function ()
					{
						uiBox_Hide();
					},
					
					
					"_handlePostcodeChange" : function (e)
					{
						
						var inputControl = $(e.target);
						
						// validate postcode
						var isValidPostcode = this.ValidatePostcode(inputControl, false);
						
						// alert("Postcode updated....... isValidPostcode = " + isValidPostcode);

						if (isValidPostcode)
						{
							// valid so ajax get new data set & update map feature
							
							/*######################## Force Bind Stock Count ########################*/
							// i think this needs moving into _handlePostcodeChangeSuccess
							this.GetStockCountNow(inputControl);
							/*######################## Below Should Go In A Function ########################*/
							
							// get parent form
							var formElement = inputControl.parents(this.SELECTOR_FORM);

							// get work flow key from mp-sync-key data item in form
							var wflw = this._workflowKey(formElement,"_lo_vi");

							// setup ajax call
							$.ajaxManager.clearArguments();

							$.ajaxManager.ajaxSettings.arguments.add(this.ARGUMENT_WORKFLOW, wflw);

							// add search criteria arguments to ajax call
							// set url
							$.ajaxManager.updateUrl($.ajaxManager.ajaxSettings.arguments.getString("&"));

							var currentScope = this;

							// bind before send
							//$.ajaxManager.onBeforeSend = function() { currentScope.OnSyncBefore() };

							// bind error
							$.ajaxManager.onError = function(XMLHttpRequest, textStatus, errorThrown) { currentScope.OnSyncError(XMLHttpRequest, textStatus, errorThrown) };

							// bind success
							$.ajaxManager.onSuccess = function(p_response) { currentScope._handlePostcodeChangeSuccess(p_response) };

							// fire ajax request
							$.ajaxManager.makeRequest();

						}
						else 
						{
							// invalid so update map with invalid status
							this._locationMapInstance.processInvalidLocationUpdate();
						}
					},
					
					"_handlePostcodeChangeSuccess" : function(p_response) {

							this._debugtrace("_handlePostcodeChangeSuccess:{" + p_response + "}");

							var result = eval(p_response);
							
							this.callbackUtilities._processResultControls(result);

							// imitate a data change
//							window.locationMapData.centreData[0].centreName = "Lexus Newcastle Updated";

							// update map feature
							this._locationMapInstance.processDataUpdate(window.locationMapData);

//							this.OnStockCountChange(p_response);
							
//							this._super(p_response);
														
							return;
						},

					"_handleDistanceChange" : function (e)
					{
						//alert("hello : Distance has changed.......");
						
						// Resolve select control
						var selectControl = $(e.target);
						
						// Find selected option
						var selectedOption = selectControl.find("option:selected:first");						
						
						// Get distance : read value from selected option
						var distance = selectedOption.val();
						
						// Pass new distance into mapFeatureInstance
						this._locationMapInstance.processDistanceUpdate(distance);
					},
				
			
			
				/*
				=============================
				HELPER METHODS
				=============================
				*/
					"_displayLoadingState" : function (e, loadEnhancerClassInstance)
					{
						var target = $(e.target);
						
						// To view loading state stop event propagation and hence stop the form submit
						// e.preventDefault();
						// e.stopPropagation();
						
						target.addClass("SEARCH-FORM-AUTO-LOADING-STATE");
						
						loadEnhancerClassInstance.createLoadingState(target);
					},
					
					
					
					"_changeDataDisplaySelection" : function(displayDataType,event)
					{
						// create empty summary if we don't need to
						var summaryData = this._createSummaryData(null, null, null, null, null);
						
						if (event.data.hasSummary == true && event.data.levelSource != null)
						{
							var dataElement = event.target;
							var currentMin;
							var currentMax;
							var selectedMax;
							var selectedMin;
							var selectableMax;
							var selectableMin;
							
							// find selectable min  and selectable max values for the x axis
							var levelData			= event.data.levelSource;
							var levelDataItems		= levelData.data;
							for (var i = 0; i < levelDataItems.length; i++)
							{
								var itemMin = levelDataItems[i].min;
								var itemMax = levelDataItems[i].max;
								currentMin = (currentMin)? Math.min(currentMin, itemMin) : itemMin;
								currentMax = (currentMax)? Math.max(currentMax, itemMax) : itemMax;
							}
							// get selected values from data field
							selectedMin = dataElement.options[0].value;
							selectedMax = dataElement.options[dataElement.selectedIndex].value;
							
							// calc the selectable min
							var selectableMin = Math.min(currentMin,selectedMin);
							selectedMin = selectableMin; // as we only have "to" fields selected min is always selectable min
							
							// calc the selectable max
							selectableMax = Math.max(currentMax,selectedMax);
							
							// create event data
							summaryData = this._createSummaryData(levelData.dataCategory, levelData.dataScope, levelData.dataSummary.id, selectableMin, selectableMax, selectedMin, selectedMax);
						}
						
						// use display manager so that new data is pushed into all control that are listerning for this update
						if (manheim.portfolio.runtime.display.displayManager)
						{
							//alert("sending event\ndc = " + summaryData.dataCategory + "\nds = " + summaryData.dataScope + "\nid = " + summaryData.dataId + "\nmin = " + summaryData.selectableMin + "\nmax = " + summaryData.selectableMax + "\nsmin = " + summaryData.selectedMin + "\nsmax = " + summaryData.selectedMax);
							manheim.portfolio.runtime.display.displayManager._broadcastValueSelectionUpdate(summaryData);
						}
					},
					
					"_createSummaryData" : function(dataCategory,dataScope,dataId,selectableMin,selectableMax,selectedMin,selectedMax)
					{
						var summaryEvent = {};
						
						summaryEvent.dataCategory	= dataCategory;
						summaryEvent.dataScope		= dataScope;
						summaryEvent.dataId			= dataId;
											
						summaryEvent.minValue		= selectedMin;
						summaryEvent.maxValue		= selectedMax;
						
						summaryEvent.selectableMin	= selectableMin;
						summaryEvent.selectableMax	= selectableMax;
						
						summaryEvent.selectedMin	= selectedMin;
						summaryEvent.selectedMax	= selectedMax;
						
						return summaryEvent;
					},
					
					"_stub" : "stub"
		}
	);


/// <reference path="../../../../jQuery/1.3.2/jquery-1.3.2-vsdoc.js" />

/*
 **************
 * IMPORTANT :: All runtime instance declarations MUST be bound to document 'js-class-setup' event
 * Author : Marc Lancashire
 **************
 */

	$(document).bind("js-class-setup", function ()
	{
		// Setup runtime namespace if doesn't exist
		if (!manheim.global.isNamespaceDefined("manheim.portfolio.runtime.display")) manheim.global.createNamespace("manheim.portfolio.runtime.display", "1.0");
		
		
		// Create instance
		manheim.portfolio.runtime.display.searchConfiguration = new manheim.portfolio.lexus.display.SearchConfiguration("manheim.portfolio.runtime.display.searchConfiguration");
		manheim.portfolio.runtime.display.searchConfiguration.callbackUtilities = manheim.portfolio.common.display.ajaxConditionalLinkManager;
		//manheim.portfolio.runtime.display.searchConfiguration.DEBUG = true;
		
		var loadEnhancerInstance = manheim.portfolio.lexus.runtime.utilities.LoadEnhancer;
		
		// Bind class events to the appropaite element events in body
		manheim.portfolio.runtime.display.searchConfiguration.bind($("body form.mp-form-search"), null, loadEnhancerInstance);
		
	});
	



