
/// <reference path="../../../../jQuery/1.3.2/jquery-1.3.2-vsdoc.js" />

/**
 *
 * DisplayManager
 *
 * This class manages the search configuration status within the client environment
 *
 * Managing status and communications between otherwise disparate page elements including:
 *	- Multiple, separate, flash display elements
 *	- Associated html display elements (checkbox links, html slider widgets etc) 
 *
 */

	// 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.DisplayManager = Object.subClass
	(
		{
			/*
			=============================
			CONSTANTS
			=============================
			*/
				SCOPE						: "scope",
				SCOPE_LEVEL_1				: "SCOPE_LEVEL_1",
				SCOPE_LEVEL_1_NO_PROPOGATION: "SCOPE_LEVEL_1_NO_PROPOGATION",
				SCOPE_LEVEL_2				: "SCOPE_LEVEL_2",
				SCOPE_LEVEL_3				: "SCOPE_LEVEL_3",
				SCOPE_ALL_LEVELS			: "SCOPE_ALL_LEVELS",

				CLASS_AUTO_DISABLE_DISPLAY	: "AUTO-DISABLE-DISPLAY",
				
				DEBUG						: false,


			/*
			=============================
			CONSTRUCTOR
			=============================
			*/
				init: function() 
				{
					/*
					 *********************************************
					 *********************************************
					 * TEMPORARY METHOD VALUE SELECTION SIMULATION
					 *********************************************
					 *********************************************
					 
						setTimeout(
							function ()
							{
								alert("2222222");
								var o = 
								{
									dataCategory: "DATA_CATEGORY_PRICE",
									minValue: "8000", //24915
									maxValue: "50000"//77953
								};

								manheim.portfolio.runtime.display.displayManager._broadcastValueSelectionUpdate(o);
								
							},
							12000
						);
					*/
					/*
					 *********************************************
					 *********************************************
					 *********************************************
					 *********************************************
					 */
					
					
					
				},



			/*
			=============================
			PUBLIC MEMBERS
			=============================
			*/
				/*
				=============================
				LISTENER REGISTRATION
				=============================
				*/
					/*
					* Swf Data display host instance registration
					*/
						registerSwfDataDisplayHost: function(scope, swfHostJsClass) 
						{
							if (scope == this.SCOPE_LEVEL_1) 
							{
								this._swfDataDisplaysScopeLevel1.push(swfHostJsClass);
							}
							else if (scope == this.SCOPE_LEVEL_2) 
							{
								this._swfDataDisplaysScopeLevel2.push(swfHostJsClass);
							}
							else throw new Error(("manheim.portfolio.common.display.DisplayManager.registerSwfDataDisplayHost() :: INVALID 'scope' == " + scope));
						},



					/*
					* JS Control Class instance registration
					*/
						registerListener: function(scope, jsControlClassInstance) 
						{
							if (scope == this.SCOPE_LEVEL_1) 
							{
								this._listenersLevel1.push(jsControlClassInstance);
							}
							else if (scope == this.SCOPE_LEVEL_2) 
							{
								this._listenersLevel2.push(jsControlClassInstance);
							}
							else if (scope == this.SCOPE_ALL_LEVELS) 
							{
								this._listenersAllLevels.push(jsControlClassInstance);
							}
							else throw new Error("manheim.portfolio.common.display.DisplayManager.registerListener() :: INVALID 'scope'");
						},



					/*
					* Register elements that are disabled when new data is loaded from the server via AJAX
					* 
					* The element itself is not REGISTERED
					* Instead unique jQuery 'selector' strings relating to the relevant element container nodes are stored
					*
					*
					* @param	jQuerySelectorString [String]		This is a string used in a jQuery i.e. $(disableTargetJQueryRef) will return the container element into which the disabling HTML content is added / appended
					*												THIS MUST BE A UNIQUE IDENTIFIER
					*/
						registerElementForDisableOnDataLoad: function(jQuerySelectorString) 
						{
							this._onDataLoadDisableSelectors.push(jQuerySelectorString);
						},



				/*
				=============================
				SELECTION UPDATE METHODS
				=============================
				*/
					updateSelection: function(e) 
					{
						var scope = e[this.SCOPE];

						switch (scope) {
							case this.SCOPE_LEVEL_1_NO_PROPOGATION:
								this.updateSelectionLevel1(e, false);
								break;

							case this.SCOPE_LEVEL_1:
								this.updateSelectionLevel1(e, true);
								break;

							case this.SCOPE_LEVEL_2:
								this.updateSelectionLevel2(e);
								break;

							case this.SCOPE_LEVEL_3:
								this.updateSelectionLevel3(e);
								break;
						}
					},



					/*
					* Process level 1 (range) selection
					*
					* This is called remotely by ANY element that facilitates addition / removal of ranges to users search
					*/
						updateSelectionLevel1: function(e, updateLevel2Selection) 
						{
							// EVENT FORMAT :: [test event matching internal test event params (coming straight from flash)]
							//exampleEvent = 
							//{
							//	type		: "ITEM_SELECTION_EVENT",
							//	scope		: "SCOPE_LEVEL_1",		// "SCOPE_LEVEL_1" || "SCOPE_LEVEL_2" :: This should only ever be "SCOPE_LEVEL_1" at this point
							//	select		: true,					// true || false
							//	level1Id	: 54,					// uint
							//	level2Id	: -1,					// uint
							//	level3Id	: -1					// uint
							//};

							this._alertEventUpdateSelection("updateSelectionLevel1",e);


							if (updateLevel2Selection) {
								// Pass event into all registered 'model scope' data display host instances
								// This generally causes a level 2 display to fully synch all level2 items to match level1 status if level1 ids match
								this.updateSelectionLevel2(e);
							}


							// PLEASE NOTE : 'LEVEL-1 : range scope' data display instances are recreated by host class once data returned from AJAX call
							// Configure AJAX call to generate NEW displays


							// Trigger all registered LEVEL-1 ('range scope') data display host instances to decouple, remove and destroy their swf instances 
							var a = this._swfDataDisplaysScopeLevel1;

							for (i = 0; i < a.length; i++) {
								a[i].enterLoadingState();
							}


							// Enter loading state
							this._enterDataLoadingState();


							// Pass update into non-swf-data display listeners who are listening for events at level 1
							a = this._listenersLevel1;
							for (var i = 0; i < a.length; i++) {
								a[i].handleItemSelectionUpdate(e);
							}


							//
							// TODO ::
							//
							// TRIGGER AJAX CALL - SEE SIMULATION FOR EVENT HANDLER EXAMPLE
							//
							//


							//
							//
							//
							//this._setupDataLoadedSimulation();
							//
							//
							//

						},



					/*
					* Process level 2 (model) selection
					*
					* This is called remotely by ANY element that facilitates addition / removal of models to users search
					*/
						updateSelectionLevel2: function(e) 
						{
							// EVENT FORMAT :: [test event matching internal test event params (coming straight from flash)]
							//exampleEvent = 
							//{
							//	type		: "ITEM_SELECTION_EVENT",
							//	scope		: "SCOPE_LEVEL_2",		// "SCOPE_LEVEL_1" || "SCOPE_LEVEL_2" :: This can be either as each will be handled correctly in swf - will be level_1 when called from 'updateSelectionLevel1()'
							//	select		: true,					// true || false
							//	level1Id	: 54,					// uint
							//	level2Id	: 2,					// uint
							//	level3Id	: -1					// uint
							//};

							this._alertEventUpdateSelection("updateSelectionLevel2",e);
							
							// Pass event into all registered SWF data display host instances
							var a = this._swfDataDisplaysScopeLevel2;
							for (var i = 0; i < a.length; i++) 
							{
								a[i].handleItemSelectionUpdate(e); // Test for JS created event: // a[i].handleItemSelectionUpdate(exampleEvent);
							}


							// Pass update into NON-SWF-data display listeners who are listening for events at level 2
							a = this._listenersLevel2;
							for (var i = 0; i < a.length; i++) 
							{
								a[i].handleItemSelectionUpdate(e);
							}


							// Pass update into non-swf-data display listeners who are listening for events at any level
							a = this._listenersAllLevels;
							for (var i = 0; i < a.length; i++) 
							{
								a[i].handleItemSelectionUpdate(e);
							}



							if (e.scope == this.SCOPE_LEVEL_2) 
							{
								//
								// TODO ::
								//
								// TRIGGER AJAX CALL - ONLY - IF e.scope = "SCOPE_LEVEL_2";
								//
								//
							}


						},



					/*
					* Process level 3 (derivative) selection
					*
					* This is called remotely by ANY element that facilitates addition / removal of derivatives to users search
					*
					* Simply updates user search setting on the server via AJAX - no need to update the UI or update any other elements
					*/
					updateSelectionLevel3: function(e) 
					{
						// EVENT FORMAT
						//exampleEvent = 
						//{
						//	type		: "ITEM_SELECTION_EVENT",
						//	scope		: "SCOPE_LEVEL_3",		// "SCOPE_LEVEL_3"
						//	select		: true,					// true || false
						//	level1Id	: 1,					// uint
						//	level2Id	: 2,					// uint
						//	level3Id	: 3						// uint
						//};

						this._alertEventUpdateSelection("updateSelectionLevel3",e);
						
						
						
						//
					},



			/*
			=============================
			PRIVATE MEMBERS
			=============================
			*/
				/*
				=============================
				REGISTERED LISTENER STORAGE COLLECTIONS
				=============================
				*/
					// swf data displays
					_swfDataDisplaysScopeLevel1: [],
					_swfDataDisplaysScopeLevel2: [],

					// jsControlClass instances
					_listenersAllLevels: [],
					_listenersLevel1: [],
					_listenersLevel2: [],

					// disable 'on data load'
					_onDataLoadDisableSelectors: [],



				/*
				=============================
				BROADCAST (to listener) METHODS
				=============================
				*/
					/*
					* Broadcast selection summary update
					*
					* Allows Level 2 displays to be updated once new Level 1 data has been loaded from server
					* - On range update selected status of the Level 2 displays is instantly updated via 'updateSelectionLevel1() calling updateSelectionLevel2()'
					* - This updates the Level 2 displays to reflect updated search parameters
					*/
						_broadcastSelectionSummaryUpdate: function(e) 
						{
							//exampleEvent = 
							//{
							//	dataCategory	: "DATA_CATEGORY_PRICE",
							//	dataScope		: "SCOPE_LEVEL_1",			// "SCOPE_LEVEL_1" || "SCOPE_LEVEL_2" || "SCOPE_LEVEL_3"
							//	dataId			: -1,						// For level 2 updates set to Range Id otherwise set to either 0 or -1 as ignored
							//	
							//	selectableMax	: 300000,
							//	selectableMin	: 50000,
							//	selectedMax		: 250000,
							//	selectedMin		: 15000
							//}
							
							//alert("> _broadcastSelectionSummaryUpdate <\n dataCategory = " + e["dataCategory"] + "\n dataScope = " + e["dataScope"] + "\n dataId = " + e["dataId"] + "\n selectableMin = " + e["selectableMin"] + "\n selectableMax = " + e["selectableMax"] + "\n selectedMax = " + e["selectedMax"] + "\n selectedMin = " + e["selectedMin"]);
							
							// Update ONLY Level-2 (model) scope items (Level-1 (range) scope totally regenerated)
							var a = this._swfDataDisplaysScopeLevel2;
							for (var i = 0; i < a.length; i++) 
							{
								a[i].handleSelectionSummaryUpdate(e);
							}
						},


					/*
					* Broadcast a ValueSelectionEvent into ALL registered swfDataDisplayHost JsClass instances (who in turn pass event into swf)
					*
					* @param e [ValueSelectionEvent (AS)]	e is an object whose form should mimic the associated AS class definition
					*/
						_broadcastValueSelectionUpdate: function(e) 
						{
							// Get all flash element host JsClass instances and update :: both range and model scope
							// Update each instance of 'manheim.portfolio.common.display.views.DataDisplay'

							var a;
							var i;

							a = this._swfDataDisplaysScopeLevel1;
							for (i = 0; i < a.length; i++) 
							{
								a[i].handleValueSelectionUpdate(e);
							}

							a = this._swfDataDisplaysScopeLevel2;
							for (i = 0; i < a.length; i++) 
							{
								a[i].handleValueSelectionUpdate(e);
							}
						},


					/*
					* Update Level 1 listeners with new display data
					*/
						_broadcastUpdatedDisplayDataLevel1: function(data) 
						{
							// Update LEVEL-1 listeners
							var a = this._swfDataDisplaysScopeLevel1;
							for (var i = 0; i < a.length; i++) 
							{
								a[i].handleDisplayDataUpdate(data);
							}
						},



				/*
				=============================
				DISPLAY CONTROL
				=============================
				*/
					/*
					* Add loading state elements to all resistered html elements 
					*/
						_enterDataLoadingState: function() 
						{
							// Put all registered elements into a disabled state

							var html = "<div class='png " + this.CLASS_AUTO_DISABLE_DISPLAY + "'></div>";

							var a = this._onDataLoadDisableSelectors;
							var i;

							for (i = 0; i < a.length; i++) 
							{
								var item = $(a[i]);
								item.append(html);
							}
						},



					/*
					* Remove all added loading state elements
					*/
						_exitDataLoadingState: function() 
						{
							// Re-enable all elements (remove added disable state html)
							$(("." + this.CLASS_AUTO_DISABLE_DISPLAY)).remove();
						},



				/*
				=============================
				INTERNAL DATA PROCESSING
				=============================
				*/

					/*
					* Process (new) Level 1 data loaded
					* 
					* This is the event handler for the ajax data call
					* - The data is formatted and passed to the appropriate update / process methods 
					*/
						_processDataLoadedLevel1: function(level1Data, selectionSummaryData) 
						{
							// Exit data loading state
							this._exitDataLoadingState();

							// Update level 1 listeners
							this._broadcastUpdatedDisplayDataLevel1(level1Data);

							// Process (broadcast) selection summary update
							this._broadcastSelectionSummaryUpdate(selectionSummaryData);
						},



				/*
				=============================
				INTERNAL EVENT HANDLERS
				=============================
				*/



				/*
				=============================
				INTERNAL UTILITIES
				=============================
				*/

					_alertEventUpdateSelection: function(eventName, e) 
					{
						var eventDesc = "called from " + eventName + "method." +
										"\n\n" +
										"type = " + e.type + ",\n" +
										"scope = " + e.scope + ",\n" +
										"select = " + e.select + ",\n" +
										"level1Id = " + e.level1Id + ",\n" +
										"level2Id = " + e.level2Id + ",\n" +
										"level3Id = " + e.level3Id + ",\n" +
										"source = " + e.source + ".";
						
						if(this.DEBUG)
						{
							alert(eventDesc);
						}
					},










			///////////////////////////
			// TEMP / TESTING
			///////////////////////////
				///////////////////////////
					///////////////////////////
						///////////////////////////
							///////////////////////////
								///////////////////////////
									///////////////////////////
										///////////////////////////
											///////////////////////////
												///////////////////////////


												testValueSelectionUpdate: function() 
												{
													alert("testValueSelectionUpdate :: DisplayManager");

													var o = 
													{
														dataCategory: "DATA_CATEGORY_PRICE",
														minValue: 8000, //24915
														maxValue: 50000//77953
													};

													this._broadcastValueSelectionUpdate(o);
												},



												testSelectionSummaryUpdate: function() 
												{
													alert("testSelectionSummaryUpdate :: DisplayManager");

													// FULL UPDATE
													/* */
													var o =
													{
														dataCategory: "DATA_CATEGORY_PRICE",
														selectableMax: 300000,
														selectableMin: 50000,
														selectedMax: 250000,
														selectedMin: 15000
													}

													// SELECTED ONLY UPDATE
													/*
													var o = 
													{
													dataCategory	: "DATA_CATEGORY_PRICE",
													selectableMax	: 120000,
													selectableMin	: 0,
													selectedMax		: 110588,	//77953
													selectedMin		: 15035		//24915
													}
													*/

													this.processSelectionSummaryUpdate(o);
												},



												_setupDataLoadedSimulation: function() 
												{
													setTimeout(manheim.portfolio.runtime.display.displayManager._setupDataLoadedSimulationHandler, 1000);
												},



												_setupDataLoadedSimulationHandler: function() 
												{
													//manheim.portfolio.runtime.display.displayManager._exitDataLoadingState();
													//////////
													//////////
													//////////
													//////////
													// Simulate new data loaded
													manheim.portfolio.runtime.display.displayManager._test_handleAjaxDataLoadedLevel1({ empty: "TEMP EXAMPLE - empty object" });
													//////////
													//////////
													//////////
													//////////
												},



											_test_new_level_1_data_a:
											{
												dataScope: "SCOPE_LEVEL_1",
												dataCategory: "DATA_CATEGORY_PRICE",
												externalDataIdentifier: "associated_external_data_element_ID",
												selectionSummary:
												{
													userDefinedSelection: true,
													selectedMin: 500,
													selectedMax: 35000,
													selectableMin: 500,
													selectableMax: 200000
												},
												dataSummary:
												{
													id: 0,
													min: 1000,
													max: 99999
												},
												data: [
													{
														title: "GS",
														id: 2033, 	//Model ID
														imageUrl: "http://www.lexus.ucl.dev.portfolio-europe.co.uk/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
														//imageUrl	: "http://www.lexus.adlington.staging.ebcentre2.net/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
														selected: false,
														min: 1000,
														max: 35000
													},


													/*
													 * OTHER MODELS
													 */
															{
																title: "IS",
																id: 2035,
																imageUrl: "http://www.lexus.ucl.dev.portfolio-europe.co.uk/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
																//imageUrl	: "http://www.lexus.adlington.staging.ebcentre2.net/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
																selected: false,
																min: 5000,
																max: 45000
															},
															{
																title: "LS",
																id: 2034,
																imageUrl: "http://www.lexus.ucl.dev.portfolio-europe.co.uk/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
																//imageUrl	: "http://www.lexus.adlington.staging.ebcentre2.net/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
																selected: false,
																min: 10000,
																max: 60000
															},
															{
																title: "RX",
																id: 2036,
																imageUrl: "http://www.lexus.ucl.dev.portfolio-europe.co.uk/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
																//imageUrl	: "http://www.lexus.adlington.staging.ebcentre2.net/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
																selected: false,
																min: 10000,
																max: 60000
															},
															{
																title: "SC",
																id: 2037,
																imageUrl: "http://www.lexus.ucl.dev.portfolio-europe.co.uk/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
																//imageUrl	: "http://www.lexus.adlington.staging.ebcentre2.net/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
																selected: false,
																min: 30000,
																max: 40000
															}
													]
												},



											_test_new_level_1_data_b:
											{
												dataScope: "SCOPE_LEVEL_1",
												dataCategory: "DATA_CATEGORY_TRANSMISSION",
												externalDataIdentifier: "associated_external_data_element_ID",
												dataSummary:
												{
													id: 0,

													gridDataCategories:
													[
														"Petrol",
														"Diesel",
														"Hybrid"
													]
												},
												data: [
													{
														title: "GS",
														id: 2033,
														imageUrl: "http://www.lexus.ucl.dev.portfolio-europe.co.uk/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
														//imageUrl	: "http://www.lexus.adlington.staging.ebcentre2.net/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
														selected: false,
														gridData:
														{
															"Petrol": 1044,
															"Diesel": null,
															"Hybrid": 50
														}
													},


													/*
													 * OTHER MODELS
													 */
														{
															title: "IS",
															id: 2035,
															imageUrl: "http://www.lexus.ucl.dev.portfolio-europe.co.uk/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
															//imageUrl	: "http://www.lexus.adlington.staging.ebcentre2.net/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
															selected: false,
															gridData:
															{
																"Petrol": 10,
																"Diesel": null,
																"Hybrid": null
															}
														},

															{
																title: "LS",
																id: 2034,
																imageUrl: "http://www.lexus.ucl.dev.portfolio-europe.co.uk/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
																//imageUrl	: "http://www.lexus.adlington.staging.ebcentre2.net/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
																selected: false,
																gridData:
																{
																	"Petrol": null,
																	"Diesel": 5,
																	"Hybrid": 100
																}
															},

															{
																title: "RX",
																id: 2036,
																imageUrl: "http://www.lexus.ucl.dev.portfolio-europe.co.uk/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
																//imageUrl	: "http://www.lexus.adlington.staging.ebcentre2.net/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
																selected: false,
																gridData:
																{
																	"Petrol": null,
																	"Diesel": 5,
																	"Hybrid": 100
																}
															},

															{
																title: "SC",
																id: 2037,
																imageUrl: "http://www.lexus.ucl.dev.portfolio-europe.co.uk/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
																//imageUrl	: "http://www.lexus.adlington.staging.ebcentre2.net/assets/images/range-data-display/TEMP_rangeDataDisplay_rangeImage.jpg",
																selected: false,
																gridData:
																{
																	"Petrol": null,
																	"Diesel": null,
																	"Hybrid": 100
																}
															}
												]

											},
											
											/*
											* Ajax data loaded handler : new Level 1 data
											* 
											* This is the event handler for the ajax data call
											* - The data is formatted and passed to the appropriate update / process methods 
											*/
											
											
											_test_handleAjaxDataLoadedLevel1: function(ajaxData) 
											{
												var dataLevel1_a = this._test_new_level_1_data_a;
												
												//////////////////////////////////////////////////////////////////////////////////
												// EVENT FORMATS UPDATED -- SEE 'process method'
												/////////////////////////////////////////////////////////////////////////////////

															// Generate new selection summary data object from data
															var example_selectionSummaryData_a = 
															{
																dataCategory	: dataLevel1_a.dataCategory,
																selectableMax	: dataLevel1_a.selectionSummary["selectableMax"],
																selectableMin	: dataLevel1_a.selectionSummary["selectableMin"],
																selectedMax		: dataLevel1_a.selectionSummary["selectedMax"],
																selectedMin		: dataLevel1_a.selectionSummary["selectedMin"]
															}

												// Process data
												this._processDataLoadedLevel1(dataLevel1_a, example_selectionSummaryData_a);



												var dataLevel1_b = this._test_new_level_1_data_b;
												
															// Generate new selection summary data object from data
															var example_selectionSummaryData_b =
															{
																dataCategory	: undefined,
																selectableMax	: undefined,
																selectableMin	: undefined,
																selectedMax		: undefined,
																selectedMin		: undefined
															}
												
												// Process data
												this._processDataLoadedLevel1(dataLevel1_b, example_selectionSummaryData_b);

											}
											


											///////////////////////////
										///////////////////////////
									///////////////////////////
								///////////////////////////
							///////////////////////////
						///////////////////////////
					///////////////////////////
				///////////////////////////
			///////////////////////////
			///////////////////////////


		}
	);



	//alert("manheim.portfolio.common.search.displayManager ::  Class definition successful");




/// <reference path="../jQuery/1.3.2/jquery-1.3.2-vsdoc.js" />


/*
 *****************************************************************
 * CLASS TEMPLATE
 *****************************************************************
 *
 * Class description :
 *
 * Author : 
 */


	//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");
	
	
	manheim.portfolio.common.display.SwfHost = Object.subClass(
		{
			/*
			 =============================
			 CONSTANTS
			 =============================
			 */
				DEFAULT_TARGET_FLASH_VERSION : "9.0.48",
				
				DEFAULT_REPLACEMENT_ID_FRAGMENT : "swfObjectInstanceID",
				
				DEFAULT_ALTERNATIVE_CONTENT :	"<div class='flash-alternative-content-container'>" + 
												"<h6>System requirements:</h6>" +
												"<p>To view this content it is necessary to have Flash Player version <strong>9.0.45</strong> or greater installed on your computer. Please ensure that you have the latest version of the Flash Player installed.</p>" + 
												"<p><a href='http://get.adobe.com/flashplayer/' target='_blank'>Click here</a> to download the latest version of the Flash Player from <a href='http://www.adobe.com' target='_blank'>www.adobe.com</a></p>" +
												"</div>"
												,
				
				
				FLASH_VAR_HOST_CLASS_INSTANCE : "hostJSClassInstanceID",
				
				
				
				
			/*
			 =============================
			 CONFIGURATION PROPERTIES (instance configuration)
			 =============================
			 */
			
			
			
			/*
			 =============================
			 CONSTRUCTOR
			 =============================
			 */
				init : function (classInstanceID, replacementTargetParentID, replacementTargetID, swfInstanceID, targetFlashVersion, swfAttributesObject, swfParametersObject, swfFlashVars, deferSwfSetup)
				{
					// Save class instance
					if (classInstanceID) this._classInstanceID	= classInstanceID;
					
					// Save replacement target parent id
					this._replacementTargetParentID	= replacementTargetParentID;
					
					// Save replacement target id (auto generate if !supplied)
					if (replacementTargetID) this._replacementTargetID = replacementTargetID;
					else
					{
						this._replacementTargetID = ((classInstanceID) ? classInstanceID : "") + this.DEFAULT_REPLACEMENT_ID_FRAGMENT;
					}
					
					// Save swf instance id 
					this._swfInstanceID = swfInstanceID;
					
					// Save target id
					if (targetFlashVersion) this._targetFlashVersion = targetFlashVersion;
					
					// Save attributes and parameters objects
					this._swfAttributesObject = swfAttributesObject;
					this._swfParametersObject = swfParametersObject;
					
					// Save any flash vars
					if (swfFlashVars) this._swfFlashVars = swfFlashVars;
					
					// Create swf
					if (!deferSwfSetup) this._setupSwfObject();
				},
			
			
			
			/*
			 =============================
			 INTERNAL RUN-TIME PROPERTIES
			 =============================
			 */
				_classInstanceID			: undefined,
				_replacementTargetParentID	: undefined,
				_replacementTargetID		: undefined,
				
				_swfInstanceID				: undefined,
				
				_targetFlashVersion			: undefined,
				_swfAttributesObject		: undefined,
				_swfParametersObject		: undefined,
				_swfFlashVars				: undefined,
				
				//reference to generated swf object for easy referencing
				_swfObject					: undefined,
			
			
			
			/*
			 =============================
			 PUBLIC METHODS
			 =============================
			 */
				 /*
				 -----------------------------
				 UTILITIES -- not currently in use - enable as required
				 -----------------------------
				 */
					/*
					alertFlashPlayerVersion : function ()
					{
						var playerVersion = swfobject.getFlashPlayerVersion();
						alert("manheim.portfolio.common.display.SwfExternalDataHost.alertFlashPlayerVersion() \nInstalled Flash player : \nmajorVersion = " + playerVersion.major + " // minorVersion = " + playerVersion.minor + " // releaseVersion = " + playerVersion.release);
					},
					*/
					
					isSwfObjectInstanceDefined : function ()
					{
						return (this.getSwfObject()) ? true : false;
					},
					
					
					getSwfObject : function ()
					{
						if (this._swfObject) return this._swfObject;
					},
					
			
			
			/*
			 =============================
			 INTERNAL METHODS
			 =============================
			 */
				/*
				 -----------------------------
				 SWF OBJECT CREATION
				 -----------------------------
				 */
					_setupSwfObject : function ()
					{
						//alert("manheim.portfolio.common.display.SwfExternalDataHost : _setupSwfObject");
						
						var version = (this._targetFlashVersion) ? this._targetFlashVersion : this.DEFAULT_TARGET_FLASH_VERSION;
						
						if (swfobject.hasFlashPlayerVersion(version))
						{
							this._generateSwfObject();
						}
						else 
						{
							// User doesn't have correct flash version therefore display alternative content
							var parent = $("#" + this._replacementTargetParentID);
							var target = parent.find("#" + this._replacementTargetID);
							
							// If target exists the remove it
							if (target.length > 0) target.remove();
							
							// Add alternative content to parent
							parent.append(this.DEFAULT_ALTERNATIVE_CONTENT);
						}
					},
					
					
					_generateSwfObject : function ()
					{
						// Test if targetID element exists in parent
						// If not then create an empty replacement target within the target Parent with the correct target ID
						
						var parent = "#" + this._replacementTargetParentID;
						var target = parent + " #" + this._replacementTargetID;
						
						if ($(target).length == 0)
						{
							$(parent).append("<div id='" + this._replacementTargetID + "'></div>")
						}
						
						// Add class namespace property to the swf object via flashvars property
						// This allows the flash object to target any ExternalInterface method calls to the correct Class instance
						
						// Generate flash vars 
						// Including (if supplied) the default class namespace property
						//
						var vars = "";
						if (this._classInstanceID) vars = this.FLASH_VAR_HOST_CLASS_INSTANCE + "=" + this._classInstanceID;
						if (this._swfFlashVars) vars += this._swfFlashVars;
						
						if (vars != "")
							this._swfParametersObject.flashvars = vars;
						
						// Create and store object
						this._swfObject = swfobject.createSWF(this._swfAttributesObject, this._swfParametersObject, this._replacementTargetID);
					},
			
					
					
					_removeSwfObject : function ()
					{
						swfobject.removeSWF(this._swfInstanceID);
						
						// Clear local reference 
						this._swfObject = undefined;
					}
					
			
				/*
				 =============================
				 SETUP
				 =============================
				 */
			
			
			
				/*
				 =============================
				 DISPLAY CREATION
				 =============================
				 */
			
			
			
				/*
				 =============================
				 DISPLAY CONTROL
				 =============================
				 */
			
			
			
				/*
				 =============================
				 INTERNAL EVENT HANDLERS
				 =============================
				 */
		}
	);




/*
	attributes.data			= ".swf";
	attributes.id			= "testFlashObject_1";
	attributes.name			= "testFlashObject_1";
	attributes.width		= "100%";
	attributes.height		= "100%";
	attributes.pluginspage	= "http://www.macromedia.com/go/getflashplayer";

	
	params.align				= "top";
	params.allowfullscreen		= true;
	params.allowscriptaccess	= "sameDomain";
	params.bgcolor				= "#0000ff";
	params.devicefont			= false;
	params.loop					= true;
	params.menu					= true;
	params.play					= true;
	params.quality				= "best";
	params.salign				= "tl";
	params.scale				= "default";
	params.wmode				= "transparent";
	
	
	************************************************************************************
	ATTRIBUTES
	************************************************************************************
	
		data		: swf url
		id			: NOTE: when undefined, the object element automatically inherits the id from the alternative content container element
		name		:
		width		:
		height		:
		pluginspage	: "http://www.macromedia.com/go/getflashplayer";
		
		styleclass	: (used instead of class, because this is also an ECMA4 reserved keyword) 
		align		: 
	
	************************************************************************************
	************************************************************************************
	
	************************************************************************************
	PARAMETERS
	************************************************************************************
	
		play				: true (d) || false
		loop				: true (d) || false
		menu				: true (d) || false
		quality				: low || autolow || autohigh || medium || high || best
		scale				: default (showall) || noorder || exactfit || noscale
		align**				: l || t || r || b										[ ** NOT SURE IF THIS PROPERTY IS SUPPORTED BY swfObject AS NOT MENTIONED IN DOCUMENTATION ]
		salign				: l || t || r || b || tl || tr || bl || br
		wmode				: window || opaque || transparent (may slow animation performance)
		bgcolor				: [hexadecimal RGB value]
		base				: or [base directory] or [URL]. Specifies the base directory or URL used to resolve all relative path statements in the Flash Player movie. This attribute is helpful when your Flash Player movies are kept in a different directory from your other files
		swliveconnect
		flashvars
		devicefont			: DON'T USE as all fonts should be internally defined -- NEVER RELY ON USER FONTS!!!
		allowscriptaccess	: never || sameDomain || always
		seamlesstabbing		: true (d) || false
		allowfullscreen		: true || false (d)
		allownetworking		: all (d) || internal || none							[see http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00001079.html]

	************************************************************************************
	************************************************************************************
	
	
	************************************************************************************
	FLASH PLAYER VERSIONS
	************************************************************************************
	
		see ( http://www.flexdeveloper.eu/forums/actionscript-3-0/flash-player-version-history/ )
		 
		- 10.0.12.36	- 15th October 2008 (Astro release - Adaptive streaming & Vector support)(Full release notes)
		- 9.0.151.0		- 6th November 2008 (Security update for those unable to upgrade to 10 - users of Microsoft Windows 98, Windows ME, Mac OS X 10.1 to 10.3 and Red Hat Enterprise Linux 3 and 4)
		- 9.0.124.0		- 9th April 2008
		- 9.0.115.0		- 3rd December 2007 (Movie-star release - H.264 support)
		- 9.0.48.0		- 22nd September 2007
		- 9.0.47.0		- 10th July 2007
		- 9.0.45.0		- 12th April 2007
		- 9.0.28.0		- 15th November 2006
		- 9.0.20.0		- 10th August 2006
		- 9.0.18.0		- 30th June 2006
		- 9.0.16.0		- 27th June 2006

		CURRENTLY TESTING FOR : [ 9.0.48.0 ]
	
	************************************************************************************
	************************************************************************************
	
*/





/// <reference path="../../../../jQuery/1.3.2/jquery-1.3.2-vsdoc.js" />
 
/**
 *
 * SwfExternalDataHost
 *
 * =========================================
 * THIS CLASS IS DESIGNED TO BE SUBCLASSED
 * =========================================
 *
 * Contains a swf instance, managing and encapsulating the 2-way communication between swf and itself.
 * 
 * The swf registers a series of common externally callable methods including:
 *		- triggerDataLoad()
 *
 * - Writes the flash element into the page replacing a specified page element, storing an internal reference to the object to facilitate communication
 *
 * - Provides core interface methods called by the swf element including
 *		- isPageLoaded()
 *		- retriveData() / getData()
 *		- setSwfReady()
 *
 * - Subclasses provide specific custom methods
 */
 
 
	//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");
	
	
	manheim.portfolio.common.display.SwfExternalDataHost = manheim.portfolio.common.display.SwfHost.subClass(
		{
			/*
			 =============================
			 CONSTRUCTOR
			 =============================
			 */
				init : function (classInstanceID, replacementTargetParentID, replacementTargetID, swfInstanceID, targetFlashVersion, swfAttributesObject, swfParametersObject, swfFlashVars, swfData, deferSwfSetup)
				{
					this._swfData = swfData;
					
					var deferSetup = (deferSwfSetup) ? true : false;
					
					// Call super class init()
					this._super(classInstanceID, replacementTargetParentID, replacementTargetID, swfInstanceID, targetFlashVersion, swfAttributesObject, swfParametersObject, swfFlashVars, deferSetup);
				},
			
			
			
			/*
			 =============================
			 INTERNAL RUN-TIME PROPERTIES
			 =============================
			 */
				// Swf data - requested by flash object when created
				_swfData : undefined,
				
				// Swf ready status flag
				_swfReady : false,
			
			
			
			
			/*
			 =============================
			 PUBLIC METHODS
			 =============================
			 */
				
				isPageLoaded : function ()
				{
					return manheim.global.isPageLoaded();
				},
			
				
				getSwfObjectReady : function ()
				{
					return this._swfReady;
				},
			
				
				setSwfObjectReady : function (b, swfObjectID)
				{
					this._swfReady = b;
				},
			
				
				getSwfData : function ()
				{
					return this._swfData;
				},
				
				
				remoteTrace : function (traceStatements)
				{
					setTimeout("alert('"+traceStatements+"')",1);
				},
			
			
			
			/*
			 =============================
			 INTERNAL / PRIVATE METHODS
			 =============================
			 */
				/*
				 ---------------------------
				 OVERRIDE REMOVE AND SET 'ready' STATUS
				 ---------------------------
				 */
				_removeSwfObject : function ()
				{
					//alert("manheim.portfolio.common.display.SwfExternalDataHost : _removeSwfObject");
					// Remove swf
					this.setSwfObjectReady(false);
					
					// Call super class
					this._super();
				}
			
		}
	)
	
	//alert("manheim.portfolio.common.display.SwfExternalDataHost ::  Class definition successful");



/// <reference path="../../../../../jQuery/1.3.2/jquery-1.3.2-vsdoc.js" />

/**
 *
 * RangeDataDisplay
 *
 */
	
	if (!manheim.global.isNamespaceDefined("manheim.portfolio.common.display.views")) manheim.global.createNamespace("manheim.portfolio.common.display.views", "1.0");
	
	
	manheim.portfolio.common.display.views.DataDisplay = manheim.portfolio.common.display.SwfExternalDataHost.subClass(
		{
			/*
			 =============================
			 CONSTANTS
			 =============================
			 */
				DISPLAY_MODE_ADVANCED_SEARCH	: "DISPLAY_MODE_ADVANCED_SEARCH",
				DISPLAY_MODE_RANGE_DETAILS		: "DISPLAY_MODE_RANGE_DETAILS",
				
				DISPLAY_TYPE_GRAPH				: "DISPLAY_TYPE_GRAPH",
				DISPLAY_TYPE_GRID				: "DISPLAY_TYPE_GRID",
				
				DISPLAY_W						: 430,
				DISPLAY_H_ADVANCED_SEARCH		: 220,
				DISPLAY_H_RANGE_DETAILS			: 265,
				
				RANGE_DETAILS_ITEM_HEIGHT_FACTOR	: 32,
				RANGE_DETAILS_DISPLAY_HEIGHT_EXTRA	: 110,
				
				JQ_TARGET_RANGE_DETAILS_ITEMS_CONTAINER	: "body > div.main-container > div.range-container > div.range-view-container > div.available-models-container div.model-items-container",
				JQ_TARGET_RANGE_DETAILS_ITEM			: "div.model-item",
				
				
				JQ_TARGET_RANGE_DATA_DISPLAY_STATE_CONTAINER	: "body > div.main-container > div.range-container > div.range-view-container > div.explore-range-container div.display-state-container",
				JQ_TARGET_RANGE_DATA_DISPLAY_STATE				: "div.display-state",
				
				
				SWF_DATA_DISPLAY				: "DataDisplay.swf",
				SWF_DATA_DISPLAY_GRAPH			: "DataDisplayGraph.swf",
				SWF_DATA_DISPLAY_GRID			: "DataDisplayGrid.swf",
				
				SWF_DATA_DISPLAY_BGND_COLOUR_DARK	: "#CCCCCC",
				SWF_DATA_DISPLAY_BGND_COLOUR_LIGHT	: "#EEEEEE",
				
				CLASS_LOADING_ICON_CONTAINER : "AUTO-DISABLE-DISPLAY-LOADING-ICON",
				
				
				DATA_LABEL_SCOPE				: "dataScope",
				DATA_LABEL_CATEGORY				: "dataCategory",
				DATA_LABEL_SELECTION_SUMMARY	: "selectionSummary",
				DATA_LABEL_DATA					: "data",
				DATA_LABEL_DATA_SUMMARY			: "dataSummary",
				DATA_LABEL_ID					: "id",
				DATA_LABEL_SELECTED				: "selected",
				
				
				DATA_VALUE_CATEGORY_PRICE			: "DATA_CATEGORY_PRICE",
				DATA_VALUE_CATEGORY_MILEAGE			: "DATA_CATEGORY_MILEAGE",
				DATA_VALUE_CATEGORY_FUEL_TYPE		: "DATA_CATEGORY_FUEL_TYPE",
				DATA_VALUE_CATEGORY_TRANSMISSION	: "DATA_CATEGORY_TRANSMISSION",
				
				DATA_VALUE_SCOPE_LEVEL_1			: "SCOPE_LEVEL_1",
				DATA_VALUE_SCOPE_LEVEL_2			: "SCOPE_LEVEL_2",
				DATA_VALUE_SCOPE_LEVEL_3			: "SCOPE_LEVEL_3",
				
				DATA_LABEL_SELECTED_MIN				: "selectedMin",
				DATA_LABEL_SELECTED_MAX				: "selectedMax",
				DATA_LABEL_SELECTABLE_MIN			: "selectableMin",
				DATA_LABEL_SELECTABLE_MAX			: "selectableMax",
				
				/* Item selection events */
				UPDATE_EVENT_DATA_LABEL_SCOPE		: "scope",
				UPDATE_EVENT_DATA_LABEL_SELECT		: "select",
				UPDATE_EVENT_DATA_LABEL_LEVEL1ID	: "level1Id",
				UPDATE_EVENT_DATA_LABEL_LEVEL2ID	: "level2Id",
				UPDATE_EVENT_DATA_LABEL_LEVEL3ID	: "level3Id",
				
				/* Selected Value & Selection Summary events */
				UPDATE_EVENT_DATA_LABEL_CATEGORY	: "dataCategory",
				UPDATE_EVENT_DATA_LABEL_VALUE_MIN	: "minValue",
				UPDATE_EVENT_DATA_LABEL_VALUE_MAX	: "maxValue",
			
				UPDATE_EVENT_DATA_LABEL_SELECTABLE_MIN	: "selectableMin",
				UPDATE_EVENT_DATA_LABEL_SELECTABLE_MAX	: "selectableMax",
				UPDATE_EVENT_DATA_LABEL_SELECTED_MIN	: "selectedMin",
				UPDATE_EVENT_DATA_LABEL_SELECTED_MAX	: "selectedMax",
			
			
			
			/*
			 =============================
			 CONSTRUCTOR
			 =============================
			 */
				init : function (displayManagerInstance, classInstanceID, replacementTargetParentID, replacementTargetID, swfInstanceID, swfData, displayMode, displayType, dataCategory, displayTitle, deferSwfCreation)
				{
					this._displayManager = displayManagerInstance;
					
					var height;
					
					if (displayMode == this.DISPLAY_MODE_RANGE_DETAILS)
					{
						// Set to default
						height = this.DISPLAY_H_RANGE_DETAILS;
						
						var _h;
						 
						// Find and count items (if found)
						var items = $(this.JQ_TARGET_RANGE_DETAILS_ITEMS_CONTAINER).find(this.JQ_TARGET_RANGE_DETAILS_ITEM);
						if (items.length > 0)
						{
							_h = (this.RANGE_DETAILS_ITEM_HEIGHT_FACTOR * items.length) + this.RANGE_DETAILS_DISPLAY_HEIGHT_EXTRA;
						}
						
						// Set html display state divs to match height
						var displayStateContainer	= $(this.JQ_TARGET_RANGE_DATA_DISPLAY_STATE_CONTAINER);
						var displayStates			= displayStateContainer.find(this.JQ_TARGET_RANGE_DATA_DISPLAY_STATE);
						
						displayStateContainer.height(_h);
						displayStates.height(_h);
						height = String(_h) + "px";
					}
					else height = this.DISPLAY_H_ADVANCED_SEARCH;
					
					
					var targetFlashVersion		= "9.0.48";
					//var targetFlashVersion		= "100";
					
					var swfAttributes			= {};
					/*swfAttributes.data			= "http://www.lexus.ucl.dev.portfolio-europe.co.uk/assets/flash/RangeDataDisplay.swf";*/
					swfAttributes.data			= "/assets/flash/" + ((displayType == this.DISPLAY_TYPE_GRAPH) ? this.SWF_DATA_DISPLAY_GRAPH : this.SWF_DATA_DISPLAY_GRID);
					swfAttributes.id			= swfInstanceID;
					swfAttributes.name			= swfInstanceID;
					swfAttributes.width			= this.DISPLAY_W;
					swfAttributes.height		= height;
					swfAttributes.pluginspage	= "http://www.macromedia.com/go/getflashplayer";
					
					var swfParameters				= {};
					swfParameters.align				= "top";
					swfParameters.allowfullscreen	= true;
					swfParameters.allowscriptaccess	= "sameDomain";
					swfParameters.base				= "../../";/*"http://www.lexus.ucl.dev.portfolio-europe.co.uk";*/
					swfParameters.bgcolor			= "#ff0000";//((displayMode == this.DISPLAY_MODE_RANGE_DETAILS) ? this.SWF_DATA_DISPLAY_BGND_COLOUR_DARK : this.SWF_DATA_DISPLAY_BGND_COLOUR_LIGHT);
					swfParameters.devicefont		= false;
					swfParameters.loop				= false;
					swfParameters.menu				= true;
					swfParameters.play				= true;
					swfParameters.quality			= "best";
					swfParameters.salign			= "tl";
					swfParameters.scale				= "noscale";
					swfParameters.wmode				= "transparent"; //opaque
					
					this._swfFlashVars = "&displayMode=" + displayMode + "&displayTitle=" + displayTitle + "&dataCategory=" + dataCategory;
					
					this._swfData = swfData;
					
					
					//
					// LOADING STATE ELEMENTS
					//
					
					// Unique flash replace ID for
					this._loadingDataClass			= "loading-data " + replacementTargetParentID + "-loading";
					this._loadingDataFlashReplaceID = replacementTargetID + "-loading-data-swf-replace-id";
					
					// Instance (created empty)
					this._loadingDataSwf	= null;
					this._loadingDataSwfID	= replacementTargetID + "-loading-data-swf";
					
					// Attributes / parameters
					this._loadingDataSwfAttributes				= {};
					this._loadingDataSwfAttributes.data			= "/assets/flash/DataLoadingDisplay.swf";
					this._loadingDataSwfAttributes.id			= this._loadingDataSwfID;
					this._loadingDataSwfAttributes.name			= this._loadingDataSwfID;
					this._loadingDataSwfAttributes.width		= "100px";
					this._loadingDataSwfAttributes.height		= "100px";
					this._loadingDataSwfAttributes.pluginspage	= "http://www.macromedia.com/go/getflashplayer";
					
					this._loadingDataSwfParameters						= {};
					this._loadingDataSwfParameters.align				= "top";
					this._loadingDataSwfParameters.allowfullscreen		= true;
					this._loadingDataSwfParameters.allowscriptaccess	= "sameDomain";
					this._loadingDataSwfParameters.base					= "../../";
					this._loadingDataSwfParameters.bgcolor				= "#0000ff";
					this._loadingDataSwfParameters.devicefont			= false;
					this._loadingDataSwfParameters.loop					= false;
					this._loadingDataSwfParameters.menu					= true;
					this._loadingDataSwfParameters.play					= true;
					this._loadingDataSwfParameters.quality				= "best";
					this._loadingDataSwfParameters.salign				= "tl";
					this._loadingDataSwfParameters.scale				= "noscale";
					this._loadingDataSwfParameters.wmode				= "transparent";
					
					
					var deferSwfSetup = (deferSwfCreation) ? true : false;
					
					// Call superclass constructor
					this._super(classInstanceID, replacementTargetParentID, replacementTargetID, swfInstanceID, targetFlashVersion, swfAttributes, swfParameters, this._swfFlashVars, swfData, deferSwfSetup);
				},
			
			
			
			/*
			 =============================
			 INTERNAL RUN-TIME PROPERTIES
			 =============================
			 */
				_displayManager				: undefined,
				
				_loadingDataClass			: undefined,
				_loadingDataFlashReplaceID	: undefined,
				_loadingDataSwf				: undefined,
				_loadingDataSwfID			: undefined,
				_loadingDataSwfAttributes	: undefined,
				_loadingDataSwfParameters	: undefined,
			
			
			
			/*
			 =============================
			 PUBLIC METHODS
			 =============================
			 */
				setSwfObjectReady : function (b, swfObjectID)
				{
					//alert("setSwfObjectReady : swfObjectID = " + swfObjectID);
					this._super(b, swfObjectID);
					if (b && this.isSwfObjectInstanceDefined()) this.getSwfObject().triggerDataLoad();
				},
				
				
				// Create swf object if not already created
				createDisplay : function ()
				{
					if (!this.isSwfObjectInstanceDefined())
					{
						this._setupSwfObject();
					}
				},
				
			
				
				
				
				
				/**
				 * Broadcasts update from swf instance upto Global JS displayManager 
				 *
				 * PLEASE NOTE : At this time only itemSelection events are broadcast by flash instances, therefore no need to have outbound event type filtering (e.g. to filter itemSelection events from valueSelection events). 
				 *
				 *	- Pass update event up to Global JS displayManager 'manheim.portfolio.runtime.global.displayManager'
				 *	- Global JS displayManager will process as required and pass event object to all associated flash host JS class instances which in turn pass through to their swf instances
				 *
				 * param	e	AS 'ItemSelectionEvent'. Should be treatable as simple object (Recast when passed back in)
				 */
					
					broadcastItemSelection : function (e)
					{
						this._displayManager.updateSelection(e);
					},
					
				
				
								//////////
								//////////
								//////////
								//////////
								//////////
								
								testValueSelectionUpdate : function ()
								{
									alert("testValueSelectionUpdate :: RangeDataDisplay");
									this._displayManager.testValueSelectionUpdate();
								},
								
								testSelectionSummaryUpdate : function ()
								{
									alert("testValueSelectionUpdate :: testSelectionSummaryUpdate");
									this._displayManager.testSelectionSummaryUpdate();
								},
								
								//////////
								//////////
								//////////
								//////////
								//////////
				
				
				
				
				/*
				 =============================
				 UPDATE METHODS
				 
				 - These are called by the Global JS displayManager
				 =============================
				 */
				 
					handleDataUpdate : function (e)
					{
						
					},
				 
					handleItemSelectionUpdate : function (e)
					{
						// [ -FF fix (start)- ] Update internal data to reflect update
						var scope	= e[this.UPDATE_EVENT_DATA_LABEL_SCOPE];
						var select	= e[this.UPDATE_EVENT_DATA_LABEL_SELECT];
						
						if (scope == this.DATA_VALUE_SCOPE_LEVEL_1)			this._updateAllDataItems(select);
						else if (scope == this.DATA_VALUE_SCOPE_LEVEL_2)	this._updateSingleDataItem(e[this.UPDATE_EVENT_DATA_LABEL_LEVEL2ID], select);
						// [ -FF fix (end)- ]
						
						// Update swf object (if ready)
						if (this.getSwfObjectReady()) this.getSwfObject().handleRemoteItemSelection(e);
					},
				
					
					
					handleValueSelectionUpdate : function (e)
					{
						// [ -FF fix (start)- ] Update internal data to reflect update
						this._updateSelectedData(e);
						// [ -FF fix (end)- ]
						
						// Update swf object (if ready [ -FF fix- ])
						if (this.getSwfObjectReady()) this.getSwfObject().handleRemoteValueSelection(e);
					},
					
					
					
					handleSelectionSummaryUpdate : function (e)
					{
						// [ -FF fix (start)- ] Update internal data to reflect update
						this._updateSelectionSummaryData(e);
						// [ -FF fix (end)- ]
						
						// Update swf object (if ready [ -FF fix- ])
						if (this.getSwfObjectReady()) this.getSwfObject().handleRemoteSelectionSummaryUpdate(e);
					},
					
					
					
					enterLoadingState : function ()
					{
					  this._removeSwfObject();
					  this._displayLoadingState();
					  //this.setupRecreate();
					},
					
					
					clearLoadingState : function ()
					{
						// Remove loading state
						this._removeLoadingState();
					},
					
					
					handleDisplayDataUpdate : function (data)
					{
						// If data category matches instance category then update
						if (data[this.DATA_LABEL_CATEGORY] == this._getDataCategory())
						{
							// Save new data
							this._swfData = data;
							
							// Remove loading state [ TODO :: Call remotely from displayManager before html destruction ]
							this.clearLoadingState();
							
							// Call remove again to ensure that the object was sucessfully removed (in certain instances not removed as timing means that not added to DOM B4 remove called)
							this._removeSwfObject();
							
							// Regenerate display
							this._setupSwfObject();
						}
					},
					
					
					
					/////////
					/////////
					/////////
						/*
						setupRecreate : function ()
						{
							setTimeout(manheim.portfolio.runtime.advancedSettings.dataDisplayPriceRange.testMethod, 2000);
						},
						
						testMethod : function ()
						{
							manheim.portfolio.runtime.advancedSettings.dataDisplayPriceRange._generateSwfObject();
						}
						*/
					/////////
					/////////
					/////////
			
			
			
			
			/*
			 =============================
			 INTERNAL METHODS
			 =============================
			 */
				/*
				 =============================
				 UTILITY METHODS
				 =============================
				 */
					/*
					 ***********
					 * DATA RETRIVAL
					 ***********
					 */
						/**
						 * [ -FF fix (method)- ]
						 */
						_getLevel1Id : function ()
						{
							var d = this._swfData[this.DATA_LABEL_DATA_SUMMARY];
							if (d) return d[this.DATA_LABEL_ID];
						},
						
						
						/**
						 * [ -FF fix (method)- ]
						 */
						_getDataCategory : function ()
						{
							return this._swfData[this.DATA_LABEL_CATEGORY];
						},
					
					
						/**
						 * [ -FF fix (method)- ]
						 */
						_getSelectionSummaryData : function ()
						{
							return this._swfData[this.DATA_LABEL_SELECTION_SUMMARY];
						},
						
					
					
					/*
					 ***********
					 * DATA MANIPULATION
					 ***********
					 */
						/**
						 * [ -FF fix (method)- ]
						 *
						 * Update single, targeted data item to selected state
						 * 
						 * @param	id		Target item ID
						 * @param	select	Desired selected state
						 */
						_updateSingleDataItem : function (id, select)
						{
							var a = this._swfData[this.DATA_LABEL_DATA];
							var i;
							
							for (i = 0; i < a.length; i++)
							{
								var item = a[i];
								if (item[this.DATA_LABEL_ID] == id) item[this.DATA_LABEL_SELECTED] = select;
							}
						},
						
						
						/**
						 * [ -FF fix (method)- ]
						 *
						 * Update all data items to selected state
						 * 
						 * @param	select	Desired selected state to apply to all data items
						 */
						_updateAllDataItems : function (select)
						{
							var a = this._swfData[this.DATA_LABEL_DATA];
							
							for (var i = 0; i < a.length; a++) { a[i][this.DATA_LABEL_SELECTED] = select; }
						},
					
					
						/**
						 * [ -FF fix (method)- ]
						 *
						 * Update data to store updated current selection values
						 * 
						 * @param	e	testValueSelectionUpdate Object
						 */
						_updateSelectedData : function (e)
						{
							var d = this._getSelectionSummaryData();
							
							//alert("_updateSelectedData : \n e[this.UPDATE_EVENT_DATA_LABEL_VALUE_MAX] = " + e[this.UPDATE_EVENT_DATA_LABEL_VALUE_MAX] + "\n e[this.UPDATE_EVENT_DATA_LABEL_VALUE_MIN] = " + e[this.UPDATE_EVENT_DATA_LABEL_VALUE_MIN]);
							
							if (d && (e[this.UPDATE_EVENT_DATA_LABEL_CATEGORY] == this._getDataCategory()))
							{
								d[this.DATA_LABEL_SELECTED_MAX] = e[this.UPDATE_EVENT_DATA_LABEL_VALUE_MAX];
								d[this.DATA_LABEL_SELECTED_MIN] = e[this.UPDATE_EVENT_DATA_LABEL_VALUE_MIN];
							}
						},
				
						
						/**
						 * [ -FF fix (method)- ]
						 *
						 * Update data to store updated selection summary data
						 * 
						 * @param	e	testValueSelectionUpdate Object
						 */
						_updateSelectionSummaryData : function (e)
						{
							var d = this._getSelectionSummaryData();
							
							if (d && (e[this.UPDATE_EVENT_DATA_LABEL_CATEGORY] == this._getDataCategory()))
							{
								d[this.DATA_LABEL_SELECTABLE_MIN] = e[this.UPDATE_EVENT_DATA_LABEL_SELECTABLE_MIN];
								d[this.DATA_LABEL_SELECTABLE_MAX] = e[this.UPDATE_EVENT_DATA_LABEL_SELECTABLE_MAX];
								
								d[this.DATA_LABEL_SELECTED_MIN] = e[this.UPDATE_EVENT_DATA_LABEL_SELECTED_MIN];
								d[this.DATA_LABEL_SELECTED_MAX] = e[this.UPDATE_EVENT_DATA_LABEL_SELECTED_MAX];
							}
						},
						
						
				
				/*
				 =============================
				 DISPLAY CONTROL / UPDATE
				 =============================
				 */
					_displayLoadingState : function ()
					{
						// Create swf container with internal replaceID'd element
						var parent = "#" + this._replacementTargetParentID;
						var target = parent + " #" + this._replacementTargetID;
						
						var replaceContent = "<div id='" + this._loadingDataFlashReplaceID + "'></div>";
						
						if ($(target).length == 0) $(parent).append("<div id='" + this._replacementTargetID + "' class='" + this.CLASS_LOADING_ICON_CONTAINER + "'>" + replaceContent + "</div>");
						else $(target).append(replaceContent);
						
						// Add loading class
						$(parent).addClass(this._loadingDataClass);
						
						// Add flash object
						this._loadingDataSwf = swfobject.createSWF(this._loadingDataSwfAttributes, this._loadingDataSwfParameters, this._loadingDataFlashReplaceID);
					},
					
					
					
					_removeLoadingState : function ()
					{
						// Remove loading class
						var parent = "#" + this._replacementTargetParentID;
						$(parent).removeClass(this._loadingDataClass);
						
						// Remove flash object
						swfobject.removeSWF(this._loadingDataSwfID);
						this._loadingDataSwf = null;
					}
			
			
			
			/*
			 =============================
			 INTERNAL EVENT HANDLERS
			 =============================
			 */
			
				
		}
	);
	
	//alert("manheim.portfolio.common.display.RangeDataDisplay ::  Class definition successful");




/// <reference path="../../../../../jQuery/1.3.2/jquery-1.3.2-vsdoc.js" />


/**
 *****************************************************************
 * CLASS TEMPLATE
 *****************************************************************
 *
 * Class description :
 *
 * Author : 
 */


	//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.SelectedModels = Object.subClass(
		{
			/*
			 =============================
			 CONSTANTS
			 =============================
			 */
			
				/* Item selection events */
				UPDATE_EVENT_DATA_LABEL_SCOPE		: "scope",
				UPDATE_EVENT_DATA_LABEL_SELECT		: "select",
				UPDATE_EVENT_DATA_LABEL_LEVEL1ID	: "level1Id",
				UPDATE_EVENT_DATA_LABEL_LEVEL2ID	: "level2Id",
				UPDATE_EVENT_DATA_LABEL_LEVEL3ID	: "level3Id",
				UPDATE_EVENT_DATA_LABEL_SELECT		: "select",
				
				DATA_VALUE_SCOPE_LEVEL_1			: "SCOPE_LEVEL_1",
				DATA_VALUE_SCOPE_LEVEL_2			: "SCOPE_LEVEL_2",
				DATA_VALUE_SCOPE_LEVEL_3			: "SCOPE_LEVEL_3",
			
			
			//PANEL
				//panel-selected-models
			
			
			//ITEMS CONTAINER
				//(Total items = 5)
				//(Total items = .find('div.selected-model-item-visible').length)
				
				//div.selected-model-items-scroll-container
				//total-selected-items-0
				//total-selected-items-0
				//total-selected-items-0
				//total-selected-items-0
				//total-selected-items-0
			
			
			//MODEL ITEMS:
				//selected-range-' + rangeId
				//selected-model-item
				//selected-model-item-visible
				
				CLASS_ITEMS_SCROLL_CONTAINER	: "selected-model-items-scroll-container",
				CLASS_ITEMS_CONTAINER			: "selected-model-items-container",
				CLASS_ITEM						: "selected-model-item",
				CLASS_ITEM_SELECTED				: "selected-model-item-visible",
				CLASS_TOTAL_SELECTED_FRAGMENT	: "total-selected-items-",
			
				CLASS_LINK_REMOVE				: "link-remove",
			
				CLASS_SCROLL_BUTTON_LAST		: "scroll-control-last",
				CLASS_SCROLL_BUTTON_NEXT		: "scroll-control-next",
			
				CLASS_SCROLL_BUTTON_LAST_DISABLED : "a-button-round-arrow-left-disabled",
				CLASS_SCROLL_BUTTON_NEXT_DISABLED : "a-button-round-arrow-right-disabled",
				
				SCROLL_DIRECTION_LEFT	: "SCROLL_DIRECTION_LEFT",
				SCROLL_DIRECTION_RIGHT	: "SCROLL_DIRECTION_RIGHT",
				
				
			
			/*
			 =============================
			 CONFIGURATION PROPERTIES (instance configuration)
			 =============================
			 */
			
			
			/*
			 =============================
			 CONSTRUCTOR
			 =============================
			 */
				init : function (jQueryTargetString, displayManager)
				{
					this._targetString		= jQueryTargetString;
					this._target			= $(jQueryTargetString);
					this._displayManager	= displayManager;
					
					this._scrollButtonLast = this._target.find("a." + this.CLASS_SCROLL_BUTTON_LAST);
					this._scrollButtonNext = this._target.find("a." + this.CLASS_SCROLL_BUTTON_NEXT);
					
					this._configureItems();
					this._configureDisplay();
					
				},
			
			
			
			/*
			 =============================
			 INTERNAL RUN-TIME PROPERTIES
			 =============================
			 */
				
				_targetString	: undefined,
				_target			: undefined,
				
				_displayManager : undefined,
				
				_scrollButtonNext : undefined,
				_scrollButtonLast : undefined,
			
				_standardItemWidth : undefined,
			
			
			/*
			 =============================
			 PUBLIC METHODS
			 =============================
			 */
				/*
				 =============================
				 UPDATE METHOD
				 
				 - Called by the Global JS displayManager
				 =============================
				 */
				 
					handleItemSelectionUpdate : function (e)
					{
						var scope			= e[this.UPDATE_EVENT_DATA_LABEL_SCOPE];
						var select			= e[this.UPDATE_EVENT_DATA_LABEL_SELECT];
						var updateLevel1Id	= e[this.UPDATE_EVENT_DATA_LABEL_LEVEL1ID];
						var updateLevel2Id	= e[this.UPDATE_EVENT_DATA_LABEL_LEVEL2ID];
						var updateLevel3Id	= e[this.UPDATE_EVENT_DATA_LABEL_LEVEL3ID];
					
						
						//alert(" SELECTED MODELS: \n scope = " + scope + "\n select = " + select + "\n updateLevel1Id = " + updateLevel1Id + "\n updateLevel2Id = " + updateLevel2Id + "\n updateLevel3Id = " + updateLevel3Id);
						
						
						// If Add :: extract rangeID and ALWAYS run added test, adding if not already added
						
						// If Remove :: ONLY if level1 remove if added
						
						var container = this._target.find("div." + this.CLASS_ITEMS_CONTAINER);
						
						var displayDirty = false;
						
						if (select)
						{
							// Get item via id and add
							var item = container.find("div#rge-" + updateLevel1Id);
							if (item.length > 0) 
							{ 
								this._setItemAdded(item, true);
								displayDirty = true;
							}
						}
						else if (scope == this.DATA_VALUE_SCOPE_LEVEL_1) 
						{
							// Get item via id and add
							var item = container.find("div#rge-" + updateLevel1Id);
							if (item.length > 0) 
							{
								this._setItemAdded(item, false);
								displayDirty = true;
							}
						}
						
						if (displayDirty) { this._configureDisplay(); }
						
					},
			
			
			/*
			 =============================
			 INTERNAL METHODS
			 =============================
			 */
				/*
				 =============================
				 EVENT HANDLERS
				 =============================
				 */
					_handleScrollButtonClick : function (direction)
					{
						this._animateDisplay(direction);
					},
				
				
				/*
				 =============================
				 UTILITIES
				 =============================
				 */
					_setItemAdded : function (itemJQueryObject, add)
					{
						var item = itemJQueryObject;
						
						if (add) { if (!item.hasClass(this.CLASS_ITEM_SELECTED)) item.addClass(this.CLASS_ITEM_SELECTED); }
						else if (item.hasClass(this.CLASS_ITEM_SELECTED)) item.removeClass(this.CLASS_ITEM_SELECTED);
					},
					
					
					_scrollDisplay : function ()
					{
						var scrollContainer_w	= this._target.find("div." + this.CLASS_ITEMS_SCROLL_CONTAINER).width();
						var itemsContainer_w	= this._target.find("div." + this.CLASS_ITEMS_CONTAINER).width();
						
						return ((scrollContainer_w < itemsContainer_w) ? true : false);
					},
					
					
					/* Is display scrolled to far to the right (as a result of item removal) */
					_displayOverscrolled : function ()
					{
						var container	= this._target.find("div." + this.CLASS_ITEMS_CONTAINER);
						var position	= container.position();
						var container_x	= position.left;
						var container_w	= container.width();
						var display_w	= this._target.find("div." + this.CLASS_ITEMS_SCROLL_CONTAINER).width();
						
						var overscrollAmount	= 0;
						var overscrolled		= false;
						
						if (container_x < 0)
						{
							overscrollAmount	= Math.max(0, (display_w - (container_w - Math.abs(container_x))))
							overscrolled		= (overscrollAmount > 0);
						}
						
						return { isOverscrolled : overscrolled, amount : overscrollAmount };
					},
					
					
					_getStandardItemWidth : function ()
					{
						if (this._standardItemWidth == 0)
						{
							this._standardItemWidth = this._target.find("div." + this.CLASS_ITEM + ":first").width();
						}
						
						return this._standardItemWidth;
					},
					
					
			
				/*
				 =============================
				 SETUP
				 =============================
				 */
					_configureDisplay : function ()
					{
						this._disabledScrollButtons();
						this._configureDisplayDimensions();
						this._configureDisplayScrolling();
					},
					
					
					
					_configureItems : function ()
					{
						// Configure item remove links
							// Remove default href link
							// Add click link that points to internal broadcast level 1 update
						
						var items = this._target.find("div." + this.CLASS_ITEM);
						
						var __this = this;
						items.each(function ()
						{
							var $this	= $(this);
							var id		= $this.attr("id").replace("rge-","");
							
							var removeLink = $this.find("a." + __this.CLASS_LINK_REMOVE);
							
							// Remove href
							removeLink.removeAttr("href");
							
							// Add new link
							removeLink.click(function ()
							{
								__this._removeItem(id);
							});
						});
						
						// Set default item width
						this._standardItemWidth = items.eq(0).width();
					},
			
			
			
				/*
				 =============================
				 DISPLAY CREATION
				 =============================
				 */
			
			
			
				/*
				 =============================
				 DISPLAY CONTROL
				 =============================
				 */
					_configureDisplayScrolling : function ()
					{
						//alert(" OVERSCROLL : " + "\n is = " + os.isOverscrolled + "\n amount = " + os.amount);
						
						//if (!os.isOverscrolled)
						if (this._scrollDisplay())
						{
							this._configureScrollButtons();
						}
						else 
						{
							this._disabledScrollButtons();
							
							var os = this._displayOverscrolled();
							if (os.isOverscrolled) this._runOverscrollResetAnimation(os.amount);
						}
					},
					
					
					_configureScrollButtons : function ()
					{
						// Setup / activate scroll buttons if required
						// Will need to re-run test every time loaded & range either added or removed
						if (!this._scrollDisplay())
						{
							this._disabledScrollButtons();
						}
						else
						{
							this._enableScrollButtons();
						}
					},
					
					
					_configureDisplayDimensions : function ()
					{
						var c			= this._target.find("div." + this.CLASS_ITEMS_SCROLL_CONTAINER);
						var items		= c.find("div." + this.CLASS_ITEM);
						var totalItems	= items.length;
						
						var selectedItems = c.find("div." + this.CLASS_ITEM_SELECTED);
						var totalSelected = selectedItems.length;
						
						// Remove all possible total selected classnames from container
						for (var i = 0; i <= totalItems; i++)
						{
							var cn = this.CLASS_TOTAL_SELECTED_FRAGMENT + i;
							if (c.hasClass(cn)) { c.removeClass(cn) }
						}
						
						// Add currently selected total classname
						c.addClass(this.CLASS_TOTAL_SELECTED_FRAGMENT + totalSelected);
					},
			
					
					_enableScrollButtons : function ()
					{
						//
						// THIS NEEDS TO CHANGE :: Temp measure
						//
							var a = this._scrollButtonNext;
							var b = this._scrollButtonLast;
							
							var container	= this._target.find("div." + this.CLASS_ITEMS_CONTAINER);
							var position	= container.position();
							var container_x	= position.left;
							var container_w	= container.width();
							var display_w	= this._target.find("div." + this.CLASS_ITEMS_SCROLL_CONTAINER).width();
							
							//alert("display_w = " + display_w + " // container_x : " + container_x);
							
							var __this = this;
							
							if (container_x != 0)
							{
								if (b.hasClass(this.CLASS_SCROLL_BUTTON_LAST_DISABLED)) { b.removeClass(this.CLASS_SCROLL_BUTTON_LAST_DISABLED); }
								
								// Attach clickEvent
								b.click( function ()
								{
									__this._handleScrollButtonClick(__this.SCROLL_DIRECTION_RIGHT);
								});
							}
							if ((container_w - Math.abs(container_x)) > display_w)
							{
								if (a.hasClass(this.CLASS_SCROLL_BUTTON_NEXT_DISABLED)) { a.removeClass(this.CLASS_SCROLL_BUTTON_NEXT_DISABLED); }
								// Attach clickEvent
								a.click( function ()
								{
									__this._handleScrollButtonClick(__this.SCROLL_DIRECTION_LEFT);
								});
							}
					},
					
					
					_disabledScrollButtons : function ()
					{
						var a = this._scrollButtonNext;
						var b = this._scrollButtonLast;
						if (!a.hasClass(this.CLASS_SCROLL_BUTTON_NEXT_DISABLED)) { a.addClass(this.CLASS_SCROLL_BUTTON_NEXT_DISABLED); }
						if (!b.hasClass(this.CLASS_SCROLL_BUTTON_LAST_DISABLED)) { b.addClass(this.CLASS_SCROLL_BUTTON_LAST_DISABLED); }
						
						// TODO :: Remove click
						a.unbind("click");
						b.unbind("click");
					},
					
					
					
					/*
					 =============================
					 ANIMATION
					 =============================
					 */
						
						//Settings
						ANIMATION_EASING		: "easeOutCubic",// "easeOutBounce" // "easeOutCubic" // "easeLinear"
						
						ANIMATION_RATE_MS_PP	: 25,
						
						
						_runOverscrollResetAnimation : function (amount)
						{
							this._disabledScrollButtons();
							
							var container	= this._target.find("div." + this.CLASS_ITEMS_CONTAINER);
							var position	= container.position();
							var container_x	= position.left;
							
							var target_x = Math.min(0, (container_x + amount));
							
							var anim_settings = { "left" : (target_x + "px")};
							
							//alert(" ANIMATE : \n container_x = " + container_x + "\n target_x = " + target_x + "\n duration = " + duration);
							
							var __this = this;
							container.animate(anim_settings, 800, this.ANIMATION_EASING, function (){ __this._handleDisplayScrollComplete() });
						},
						
						
						
						_animateDisplay : function (direction)
						{
							this._disabledScrollButtons();
							
							var d = (direction == this.SCROLL_DIRECTION_LEFT) ? true : false;
							
							var container	= this._target.find("div." + this.CLASS_ITEMS_CONTAINER);
							var position	= container.position();
							var container_x	= position.left;
							
							var itemWidth	= this._getStandardItemWidth();
							
							var delta		= (d) ? -itemWidth : itemWidth;
							
							var target_x	= container_x + delta;
							
							var anim_settings = { "left" : (target_x + "px")};
							
							var __this = this;
							container.animate(anim_settings, 800, this.ANIMATION_EASING, function (){ __this._handleDisplayScrollComplete() });
						},
						
						
						
						
						/*
						 =============================
						 ANIMATION EVENT HANDLERS
						 =============================
						 */
						 
						 _handleDisplayScrollComplete : function (e)
						 {
							this._configureScrollButtons();
						 },
						 
						
						/*					
						function handleAnimateHeightClose(target) 
						{
							var anim_settings = { "height":target_height_closed };
							
							$(target).animate(anim_settings, anim_duration, anim_easing, handleAnimateComplete);
						}
						
						
						function handleAnimateComplete() 
						{
							//alert("Animation complete!!");
						}
						*/
						
					
					
					
				/*
				 =============================
				 INTERNAL EVENT HANDLERS
				 =============================
				 */
					_removeItem : function (itemId)
					{
						//alert("removeItem : " + itemId);
						var updateEvent = 
						{
							type		: "ITEM_SELECTION_EVENT",
							scope		: this.DATA_VALUE_SCOPE_LEVEL_1,
							select		: false,
							level1Id	: itemId,
							level2Id	: -1,
							level3Id	: -1
						};
						
						if (this._displayManager) this._displayManager.updateSelection(updateEvent);
					}
		}
	);
	
	//alert("SelectedModels");


/// <reference path="../../../../jQuery/1.3.2/jquery-1.3.2-vsdoc.js" />

/**
 *
 * DisplayManager
 *
 * This class manages the search configuration status within the client environment
 *
 * Managing status and communications between otherwise disparate page elements including:
 *	- Multiple, separate, flash display elements
 *	- Associated html display elements (checkbox links, html slider widgets etc) 
 *
 */

	// 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.DisplayManager = manheim.portfolio.common.display.DisplayManager.subClass
	(
		{
			/*
			=============================
			CONSTANTS
			=============================
			*/
				MANAGED_INPUT_CLASS		:		"div.panel-selected-models input.selected-models",
				MANAGED_VALUE_LEVEL		:		2,
				FIELD_RANGE_LEVEL		:		0,
				FIELD_MODEL_LEVEL		:		1,
				FIELD_DERIVATIVE_LEVEL	:		2,
				FIELD					:		null, // this will be populated by a varible on the runtime instance
				DELIMITER				:		",",
				ARGUMENT_WORKFLOW		:		"wflw",
				SEARCH_CRITERIA_PANEL	:		"SearchCriteriaPanel",
				SELECTOR_FORM			:		"form.mp-search-count",
				
				DEBUG					:		false,
			
			/*
			=============================
			MEMBER VARIBLES
			=============================
			*/
				// public
				callbackUtilities : {},
				
				// private
				_utilities			:		manheim.portfolio.global.Utilites,
				_managedInput		:		null,
			
			/*
			=============================
			CONSTRUCTOR
			=============================
			*/
				init: function() 
				{
					this._super(); // call base init
					
					this._managedInput = $(this.MANAGED_INPUT_CLASS);
					
					if(this._managedInput.length < 1)
					{
						this._alertDebugMessage("Can not find the managed input");
					}
					
				},
			
			/*
			=============================
			SELECTION UPDATE METHODS
			=============================
			*/
			/* EVENT FORMAT
			//exampleEvent = 
				{
					type		: "ITEM_SELECTION_EVENT",
					scope		: "SCOPE_LEVEL_3",		// "SCOPE_LEVEL_3"
					select		: true,					// true || false
					level1Id	: 1,					// uint
					level2Id	: 2,					// uint
					level3Id	: 3						// uint
					source		: "SCOPE_LEVEL_3"		// "SCOPE_LEVEL_3"
				};
			*/
			/*
				Firing
				------
				This only fires an add when you add a single item that has other siblings that are not also selected.
				If all other siblings are selected then an update selection level above will fire adding the parent item.
				
				This only fires a remove when you remove a single item that has other siblings that are still selected.
				Otherwise if all siblings are are not selected then an update selection level above will fire removing the parent item.
				
				Control Data Sync
				-----------------
				The value on the control is sync with your select if we match the event source against the current method scope
				this ensures that we only carry out syncs on the lowest level and not bubbled events.
				The source attribute comes from the check box tree but not from the graphs therefore if the source is undefined then we should also
				sync the control value.
				
				Server Sync
				-----------
				Level 1 : Carries out a range/model/derivative ajax update via a criteria update which brings back the search criteria panel for us to replace.
				Level 2 : Carries out a model/derivarive ajax update via a stock count refresh.
				Level 3 : Carries out a derivarive ajax update via a stock count refresh.
			*/
			
				
				updateSelectionLevel1: function(e, updateLevel2Selection)
				{
					this._super(e, updateLevel2Selection); // call base
					
					if (this._validateManageListRequirement(e,e.level1Id,this.SCOPE_LEVEL_1))
					{
						this._manageList(e.select,e.level1Id,this.FIELD_RANGE_LEVEL);
						
						// this is carried out by the refresh range context not the stock count
						//this._managedInput.trigger("change");
					}
					
					var formElement = $(this.MANAGED_INPUT_CLASS).closest(this.SELECTOR_FORM);
					
					this._refreshRangeContext(e, formElement);
				},
				
				updateSelectionLevel2: function(e)
				{
					this._super(e); // call base
					
					if (this._validateManageListRequirement(e,e.level2Id,this.SCOPE_LEVEL_2))
					{
						this._manageList(e.select,e.level2Id,this.FIELD_MODEL_LEVEL);
						
						this._managedInput.trigger("change");	
					}
				},
				
				
				updateSelectionLevel3: function(e) 
				{
					this._super(e); // call base
					
					if (this._validateManageListRequirement(e,e.level3Id,this.SCOPE_LEVEL_3))
					{
						this._manageList(e.select,e.level3Id,this.FIELD_DERIVATIVE_LEVEL);
						
						this._managedInput.trigger("change");
					}
				},
				
				
			/*
			=============================
			PRIVATE HEPLER METHODS
			=============================
			*/
				
				_validateManageListRequirement: function(e, value, onScope)
				{
					var isRequired = false;
					
					if (
							(onScope == e.scope) &&
							(
								(onScope == e.source) || // if i am not a bubbled event
								(!e.source) // or if i have no source, i.e. i have come from a 
							) &&
							(value != -1)
						)
					{
						isRequired = true;
					}
					
					return isRequired;
				},
				
				_manageList: function(state,item,level)
				{
					var editedItems;
					
					// if we are already at our managed level then we can use the incoming item
					if(level == this.MANAGED_VALUE_LEVEL)
					{
						editedItems	= item;
					}
					else
					{
						// otherwise we need to work out what items to from our field
						editedItems = this._getItemsFromFieldForLevel(item,level);
					}
					
					var currentSelection = this._managedInput.val();
					
					this._alertDebugMessage('before count : ' + currentSelection.split(this.DELIMITER).length + '.\nbefore : ' + currentSelection + '.');
					
					var newList;
					
					if(state == true)
					{
						newList = this._utilities.mergeDataListsIntoUniqueList(this._managedInput.val(), editedItems, ",");
					}
					else
					{
						newList = this._utilities.removeValuesFromDataList(this._managedInput.val(), editedItems, ",");
					}
					
					this._managedInput.val(newList);
					
					this._alertDebugMessage('after count: ' + this._managedInput.val().split(this.DELIMITER).length + '\nafter: ' + this._managedInput.val() + '.');
				},
				
			/*
			=============================
			EXAMPLE FIELD
			Range[],Model[],Derivative[] etc...
			=============================
			[
				{
					"id": 2035,
					"title": "IS",
					"options": [
						{
							"id": 1791493,
							"title": "IS 220d Saloon 4-Door",
							"options": [
								{
									"id": 1791494,
									"title": "2.2TD"
								}
							]
						}
					]
				}
			]
			*/
				// this is the parent method to get options within a field on a speicfied level
				_getItemsFromFieldForLevel : function(item,level)
				{
					// we need field data to do this
					if (this.FIELD == null)
					{
						this._alertDebugMessage("Can not manage state as range,model,derviative field is null");
						throw new Error();
					}
					
					var currentLevel = 0;
					var requiredOptions =  new Array();
					
					for(var i = 0; i < this.FIELD.length; i++)
					{
						this._getFieldOptionsForLevel(requiredOptions, item, this.FIELD[i], currentLevel, level, this.MANAGED_VALUE_LEVEL);
					}
					
					this._alertDebugMessage('found: ' + requiredOptions.length + ' option matches\nfor item {' + item + '}\non level {' + level + '}.');
					
					var optionIds = this._delmitedOptionPropertyValue(requiredOptions, ",", "id");
					
					this._alertDebugMessage(optionIds);
					
					return optionIds;
				},
				
				// this is a recursive method to add matching options to the [matchedOptions] varible from the option and level that you have provided
				_getFieldOptionsForLevel : function(matchedOptions, item, option, traversedLevel, matchLevel, requiredLevel)
				{
					var matchFound = false;
					
					// if i have traversed to my match level then check the item against the option.id
					if(traversedLevel == matchLevel)
					{
						if (new String(option.id) == item || item == null)
						{
							// change the traverse option selector
							if (requiredLevel != null)
							{
								/* 
									Now get all options on the required level below this option.
									e.g.	for the matched model go get all the derivatives.
									e.g.	for the matched range go get all the derivatives.
									i.e.	match level = 1(model), required level = 2 (derivatives),
											so find the matching option on the correct level then get all options on the required level below.
								*/
								matchFound = this._getFieldOptionsForLevel(matchedOptions, null, option, traversedLevel, requiredLevel, null);
							}
							// add this matched option
							else
							{
								matchFound = true;
								
								if(matchedOptions.length && matchedOptions.length > 0)
								{
									matchedOptions[matchedOptions.length] = option;
								}
								else
								{
									// this is the first time we add to the array
									matchedOptions[0] = option;
								}
							}
						}
					}
					// ensure that our current option has child options
					else if(option.options && option.options.length > 0)
					{
						// traverse the child options to the next level
						for(var i = 0; i < option.options.length; i++)
						{
							matchFound = this._getFieldOptionsForLevel(matchedOptions, item, option.options[i], traversedLevel+1, matchLevel, requiredLevel);
							
							// if item is not null i.e. we are in match mode and have found a mathc then break out of loop
							if (matchFound && item != null)
							{
								break;
							}
						}
					}
					
					return matchFound;
				},
				
				_delmitedOptionPropertyValue : function(options, delimiter, propertyValue)
				{
					var delimitedOptions = new String();
					
					// do we have option to delimit
					if(options != null && options.length && options.length > 0)
					{
						for(var i = 0; i < options.length; i++)
						{
							delimitedOptions += options[i][propertyValue] + delimiter;
						}
					}
					
					// remove last delimiter
					delimitedOptions = delimitedOptions.substring(0, delimitedOptions.lastIndexOf(delimiter));
					
					return delimitedOptions;
				},
				
				// binds the derivative search criteria and refreshes controls that are dependant on range
				_refreshRangeContext : function(e, formElement)
				{
					this._managedInput.trigger("clear");
					
					// setup ajax call, to update range / model / derivative search criteria
					
					// setup ajax arguments
					var wflw = manheim.portfolio.global.Utilites.getScopedWorkflowKey(formElement, "_ra_up");
					
					//"se_na_ra_up"; // (default)search national range update
					
					$.ajaxManager.clearArguments();
					$.ajaxManager.ajaxSettings.arguments.add(this.ARGUMENT_WORKFLOW, wflw); // add work flow key
					$.ajaxManager.ajaxSettings.arguments.add("crtv",$(this.MANAGED_INPUT_CLASS).val()); // add criteria value
					$.ajaxManager.updateUrl($.ajaxManager.ajaxSettings.arguments.getString("&"));
					
					// bind ajax events
					var currentScope = this;
					$.ajaxManager.onBeforeSent	= function() { currentScope._refreshBefore() };
					$.ajaxManager.onError		= function(XMLHttpRequest, textStatus, errorThrown) { currentScope._refreshError(XMLHttpRequest, textStatus, errorThrown) };
					$.ajaxManager.onSuccess		= function(p_response) { currentScope._refreshSuccess(p_response) };
					
					$.ajaxManager.makeRequest(); // fire request
				},
				
				// handles the before send event of the ajax call
				_refreshBefore : function()
				{
					this._alertDebugMessage("_refreshBefore");
					
					// TODO set search criteria panel into a loading state
				},
				
				// handles the error event of the ajax call
				_refreshError : function(XMLHttpRequest, textStatus, errorThrown)
				{
					this._alertDebugMessage("_refreshError");
				},
				
				// handles the success event of the ajax call
				_refreshSuccess : function(p_response)
				{
					this._alertDebugMessage("_refreshSucess");					
					
					// evaluate response
					var result = eval(p_response);
					
					// replace all controls
					this.callbackUtilities._processResultControls(result);
					
					// get reference to the search criteria panel
					var searchCriteriaControlReference;
					var $searchCriteriaContainer;
					searchCriteriaControl = this.callbackUtilities._findDataControl(result,this.SEARCH_CRITERIA_PANEL);
					$searchCriteriaContainer = $('#' + searchCriteriaControl.targetDomId);
					
					/* _processResultControls takes care of this 
					// PNG Fix
					if(fix_PNGs)
					{
						fix_PNGs($searchCriteriaContainer);
					}
					*/
					
					// Render Sliders
					if(RenderChildSliders)
					{
						RenderChildSliders($searchCriteriaContainer);
					}
					
					// Advanced search panel image list bind
					if (manheim.global.isNamespaceDefined("manheim.portfolio.runtime.display.controls") && manheim.portfolio.runtime.display.controls.advancedSearchImageListControls)
					{
						manheim.portfolio.runtime.display.controls.advancedSearchImageListControls.bindContainer($searchCriteriaContainer);
					}
					
//					// Advanced search panel must have total select summary bind
//					if (prepareSearchCriteriaPanelContainer)
//					{
//						prepareSearchCriteriaPanelContainer($searchCriteriaContainer);
//					}
					
					// Rebind open and close panel click
					if (manheim.global.isNamespaceDefined("manheim.portfolio.runtime.display.controls") && manheim.portfolio.runtime.display.controls.advancedSearchPanel)
					{
						manheim.portfolio.runtime.display.controls.advancedSearchPanel.rebind();
					}
					
					// Rebind mp-search-count, form submit clicks and graph item selection updates
					if (manheim.global.isNamespaceDefined("manheim.portfolio.runtime.display") && manheim.portfolio.runtime.display.searchConfiguration)
					{
						manheim.portfolio.runtime.display.searchConfiguration.bind($searchCriteriaContainer);
					}
					
					// Rebind tool tips
					/* _processResultControls takes care of this 
					if (BindToolTips)
					{
						BindToolTips($searchCriteriaContainer);
					}
					*/
					
					// SWF
					if (sIFR && sIFR.styleAdvancedSettingsPanel)
					{
						sIFR.styleAdvancedSettingsPanel();
					}
					
					// SET O/C State [Optional]
					
					// Broadcast data update events to graphs, this creates the graphs
					
					
					// Process updated PRICE data
					if (json_priceData_level_1) 
					{
						// Create selection summary update event
						var summaryEvent = this._createSelectionSummaryEventLevel1(json_priceData_level_1);
						
						// Process level 1 update
						this._processDataLoadedLevel1(json_priceData_level_1, summaryEvent);
						
						// Create and broadcast additional level 2 selection sumamry updates
						this._createLevel2SelectionSummaryUpdates(json_priceData_level_1);
					}
					
					// Process updated ODOMETER data
					if (json_odometer_level_1) 
					{
						// Create selection summary update event
						var summaryEvent = this._createSelectionSummaryEventLevel1(json_odometer_level_1);
						
						// Process level 1 update
						this._processDataLoadedLevel1(json_odometer_level_1, summaryEvent);
						
						// Create and broadcast additional level 2 selection sumamry updates
						this._createLevel2SelectionSummaryUpdates(json_odometer_level_1);
					}
					
					if (json_fuelType_level_1) this._processDataLoadedLevel1(json_fuelType_level_1, {}); // fuel type
					if (json_transmissionData_level_1) this._processDataLoadedLevel1(json_transmissionData_level_1, {}); // transmission type
				},
				
				_createSelectionSummaryEventLevel1 : function(e)
				{
					var summaryEvent = {};
					
					summaryEvent.dataCategory	= e.dataCategory;
					summaryEvent.dataScope		= e.dataScope;
					
					summaryEvent.dataId			= e.dataSummary.id;
					
					summaryEvent.selectableMax	= e.selectionSummary.selectableMax;
					summaryEvent.selectableMin	= e.selectionSummary.selectableMin;
					summaryEvent.selectedMax	= e.selectionSummary.selectedMax;
					summaryEvent.selectedMin	= e.selectionSummary.selectedMin;
					
					return summaryEvent;
				},
				
				
				// @param	e	Level 1 jsonData object
				_createLevel2SelectionSummaryUpdates : function (e)
				{
					// Generate and broadcast multiple level 2 selection summary updates
					var dataCategory	= e.dataCategory;
					var dataScope		= "SCOPE_LEVEL_2";
					var selectedMax		= e.selectionSummary.selectedMax;
					var selectedMin		= e.selectionSummary.selectedMin;
					
					var selectableMax = undefined;
					var selectableMin = undefined;
					
					var i;
					var a = e.data;
					
					// First run - store selectable min / max
					for (i = 0; i < a.length; i++)
					{
						var item = a[i];
						
						if(item.selected)
						{
							var iMin = item.min;
							var iMax = item.max;
							selectableMin = (selectableMin) ? Math.min(selectableMin, iMin) : iMin;
							selectableMax = (selectableMax) ? Math.max(selectableMax, iMax) : iMax;
						}
						
					}
					
					// Second run - generate update event
					for (i = 0; i < a.length; i++)
					{
						var item					= a[i];
						var id						= item.id;
						var updateEvent				= {};
						
						// If selectable min / max still undefined -- i.e. no models selected set to range min / max
						var _selectableMin = (selectableMin) ? Math.max(selectableMin, item.min) : e.selectionSummary.selectableMin;
						var _selectableMax = (selectableMax) ? Math.max(selectableMax, item.max) : e.selectionSummary.selectableMax;
						
						//alert(" _selectableMin = " + _selectableMin + "\n _selectableMax = " + _selectableMax + "\n selectableMin = " + selectableMin + "\n selectableMax = " + selectableMax);
						
						updateEvent.dataCategory	= dataCategory;
						updateEvent.dataScope		= dataScope;
						updateEvent.dataId			= id;
						updateEvent.selectableMax	= _selectableMax;
						updateEvent.selectableMin	= _selectableMin;
						updateEvent.selectedMax		= selectedMax;
						updateEvent.selectedMin		= selectedMin;
						
						this._broadcastSelectionSummaryUpdate(updateEvent);
					}
					
				},
				
				
				
				// handled alert trace message
				_alertDebugMessage : function(message)
				{
					if (this.DEBUG)
					{
						alert(message);
					}
				},
				
				_last : "last"
		}
	);




/// <reference path="../../../../../jQuery/1.3.2/jquery-1.3.2-vsdoc.js" />


/**
 *****************************************************************
 * AdvancedSearchPanel
 *****************************************************************
 *
 * Provides custom open/close functionality for the AdvancedSearchPanel
 *
 * Author : Liam Prescott
 */


	//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.AdvancedSearchPanel = Object.subClass(
		{
			/*
			 =============================
			 CONSTANTS
			 =============================
			 */
				"CLASS_PANEL_ADVANCED_SETTINGS"			: "panel-advanced-settings",
				"CLASS_PANEL_ADVANCED_SETTINGS_CLOSED"	: "panel-advanced-settings-closed",
				
				// COLUMNS
				"CLASS_COLUMN_1"						: "column-1",
				"CLASS_COLUMN_2"						: "column-2",
				
				// CONTROL CONTAINER CLASSES
				"CLASS_CONTROL_CONTAINER"				: "control-container",
				
				// CONTROL CONTAINER SECONDARY CLASSES
				"CLASS_SLIDER_CONTAINER"				: "slider-container",
				"CLASS_RADIOBUTTONLIST_CONTAINER"		: "radiobuttonlist-container",
				"CLASS_CHECKBOXLIST_CONTAINER"			: "radiobuttonlist-container",
				"CLASS_IMAGELIST_CONTAINER"				: "imagelist-container",
				
				// CONTROL CONTAINER UNIQUE ID CLASSES
				"CLASS_DATA_DISPLAY_CONTAINERS" : ["priceto", "odometerto", "transmission", "fueltype"],
				
				
				
				// STANDARD DISPLAY CLASSES
				"CLASS_STANDARD_DISPLAY_SLIDER"			: "ui-slider-container",	//div.
				"CLASS_STANDARD_DISPLAY_RADIOBUTTONLIST": "radiobuttonlist",		//div.
				"CLASS_STANDARD_DISPLAY_IMAGELIST"		: "imagegroup",				//fieldset.
				
				"CLASS_STANDARD_DISPLAY_OPEN"			: "standard-display-open",
				"CLASS_STANDARD_DISPLAY_CLOSED"			: "standard-display-closed",
				
				"CLASS_STANDARD_DISPLAY_CONTROL_OPEN"	: "standard-display-open",
				"CLASS_STANDARD_DISPLAY_CONTROL_CLOSE"	: "standard-display-close",
				
				
				// EXTENDED DISPLAY CLASSES
				"CLASS_EXTENDED_DISPLAY"				: "extended-data-display",
				
				"CLASS_EXTENDED_DISPLAY_OPEN"			: "extended-display-open",
				"CLASS_EXTENDED_DISPLAY_CLOSED"			: "extended-display-closed",
				
				"CLASS_EXTENDED_DISPLAY_CONTROL_OPEN"	: "extended-display-open",
				"CLASS_EXTENDED_DISPLAY_CONTROL_CLOSE"	: "extended-display-close",
				
				
				// STD PANEL CONSTRUCT CLASSES
				"CLASS_PANEL_BODY_CONTAINER"			: "panel-body-container",
				"CLASS_PANEL_BODY_CONTAINER_OPEN"		: "panel-body-container-open",
				"CLASS_PANEL_BODY_CONTAINER_CLOSED"		: "panel-body-container-closed",
				
				"CLASS_PANEL_BODY_HEADER"				: "panel-body-header",
				"CLASS_PANEL_BODY_CONTENT"				: "panel-body-content",
				"CLASS_OPEN"							: "open",
				"CLASS_CLOSE"							: "close",
				
				
				// SPECIFIC ITEM JQUERY IDs
				"ID_RESULTS_LIST_MODE" : "div.results-container.list-container",
				"ID_RESULTS_FLOW_MODE" : "div.results-container.photoflow-container",
				"ID_RANGE_DETAILS" : "div.range-container",
				
				"ID_MUST_HAVES_CONTROL_CONTAINER" : "div.control-container.options.checkboxlist-container",
				
				
				// STATE CONSTANTS
				"STATE_OPEN"	: "OPEN",
				"STATE_CLOSE"	: "CLOSE",
				
				
				// SCOPE CONSTANTS
				"SCOPE_STANDARD" : "SCOPE_STANDARD",
				"SCOPE_EXTENDED" : "SCOPE_EXTENDED",
				
				
				// DEFAULT PANEL HEIGHTS
				"DEFAULT_PANEL_HEIGHT_2_COLUMN" : 250, //242
				"DEFAULT_PANEL_HEIGHT_1_COLUMN" : 376,
				"DEFAULT_PANEL_HEIGHT_RANGE_DETAILS" : 465,
				
				"PANEL_HEIGHT_CLOSED" : 30,
				
				// PANEL PERSISTENCE
				"DEFAULT_PANEL_LINK_OPEN"		: "Open",
				"DEFAULT_PANEL_LINK_CLOSE"		: "Close",
				"DEFAULT_PANEL_STATE_COOKIE"	: "EnabledPanels",
				"DEFAULT_PANEL_HEIGHT_COOKIE"	: "Height",		
				"DEFAULT_PANEL_PERSISTENCE"		: true,		
				
			/*
			 =============================
			 CONFIGURATION PROPERTIES (instance configuration)
			 =============================
			 */
			
			
			/*
			 =============================
			 CONSTRUCTOR
			 =============================
			 */
				"init" : function (dataDisplayInstanceDetails)
				{
					// Store local reference to data display instances
					
					this._dataDisplayInstances = new Array();
					
					var a = dataDisplayInstanceDetails;
					for (var i = 0; i < a.length; i++)
					{
						var string = a[i][0];
						this._dataDisplayInstances[string] = a[i][1];
					}
					
					
					// Setup
					this._setup();
					
					// Style panel header
					if (sIFR && sIFR.styleAdvancedSettingsPanel)
						sIFR.styleAdvancedSettingsPanel();
				},
			
			
			
			/*
			 =============================
			 INTERNAL RUN-TIME PROPERTIES
			 =============================
			 */
				"_panel_height_open"	: 0,
				
				"_dataDisplayInstances" : undefined,
				
				// Panel persistance array
				"_enabledPanelsNames" : new Array(""),

			/*
			 =============================
			 PUBLIC METHODS
			 =============================
			 */
				"rebind" : function ()
				{
					// If panel !in 2 column mode (i.e. in right hand column) collapse all basic displays
					if (this._basicDisplayCollapsable()) this._collapseAllBasicDisplays();
					
					// Reconfigure open / close links
					this._setupPanelOpenCloseLinks();
					this._setupDisplayOpenCloseLinks();
					
					// Open panels and set height from cookies
//
// DISABLED :: MECHANISM LOGIC FLAWED (Panel state history)
//
					//this._managePanels();
				},
				
				
			
			/*
			 =============================
			 INTERNAL METHODS
			 =============================
			 */
				/*
				 =============================
				 UTILITIES
				 =============================
				 */
					"_isRangeDetailsDisplay" : function () { return ($(this.ID_RANGE_DETAILS).length > 0) ? true : false; },
					
					"_twoColumnDisplayMode" : function ()
					{
						if ($(this.ID_RESULTS_LIST_MODE).length > 0 || this._isRangeDetailsDisplay()) return false; // TODO :: Also return false if on [Range details page]
						return true;
					},
					
					
					"_basicDisplayCollapsable" : function ()
					{
						return !this._twoColumnDisplayMode();
					},
					
					
					"_panelHeight" : function ()
					{
						return parseInt($("div." + this.CLASS_PANEL_ADVANCED_SETTINGS).css("height"));
					},
					
					
					"_getDefaultPanelHeight" : function ()
					{
						var h;
						if (this._twoColumnDisplayMode()) h = this.DEFAULT_PANEL_HEIGHT_2_COLUMN;
						else
						{
							// If results mode list
							if ($(this.ID_RESULTS_LIST_MODE).length > 0) h = this.DEFAULT_PANEL_HEIGHT_1_COLUMN;
							else if (this._isRangeDetailsDisplay()) h = this.DEFAULT_PANEL_HEIGHT_RANGE_DETAILS;
						}
						return h;				
						
						//return (this._twoColumnDisplayMode)? this.DEFAULT_PANEL_HEIGHT_2_COLUMN : this.DEFAULT_PANEL_HEIGHT_1_COLUMN; // TODO :: Account for height on [RangeDetail page]
					},
					
					
					// @param	:	control [ jQuery object ]	: jQuery object for the control container within which we want to find (& return) the standard display
					//											: This MUST be element with class = this.CLASS_CONTROL_CONTAINER
					// @return	:	[ jQuery object ]			: jQuery object for the standard display
					"_getStandardDisplay" : function (control)
					{
						var targetClass;
						
						if (control.hasClass(this.CLASS_SLIDER_CONTAINER))			targetClass = this.CLASS_STANDARD_DISPLAY_SLIDER;
						if (control.hasClass(this.CLASS_RADIOBUTTONLIST_CONTAINER)) targetClass = this.CLASS_STANDARD_DISPLAY_RADIOBUTTONLIST;
						if (control.hasClass(this.CLASS_IMAGELIST_CONTAINER))		targetClass = this.CLASS_STANDARD_DISPLAY_IMAGELIST;
						
						return control.find("." + targetClass);
					},
					
					
					"_setDisplayState" : function (control, scope, state)
					{
						switch (scope)
						{
							case this.SCOPE_STANDARD :
								switch (state)
								{
									case this.STATE_OPEN :
										if (control.hasClass(this.CLASS_STANDARD_DISPLAY_CLOSED)) control.removeClass(this.CLASS_STANDARD_DISPLAY_CLOSED);
										if (!control.hasClass(this.CLASS_STANDARD_DISPLAY_OPEN)) control.addClass(this.CLASS_STANDARD_DISPLAY_OPEN);
										break;
										
									case this.STATE_CLOSE :
										if (control.hasClass(this.CLASS_STANDARD_DISPLAY_OPEN)) control.removeClass(this.CLASS_STANDARD_DISPLAY_OPEN);
										if (!control.hasClass(this.CLASS_STANDARD_DISPLAY_CLOSED)) control.addClass(this.CLASS_STANDARD_DISPLAY_CLOSED);
										break;
									
									default : break;
								}
								break;
								
							case this.SCOPE_EXTENDED :
								switch (state)
								{
									case this.STATE_OPEN :
										if (control.hasClass(this.CLASS_EXTENDED_DISPLAY_CLOSED)) control.removeClass(this.CLASS_EXTENDED_DISPLAY_CLOSED);
										if (!control.hasClass(this.CLASS_EXTENDED_DISPLAY_OPEN)) control.addClass(this.CLASS_EXTENDED_DISPLAY_OPEN);
										break;
										
									case this.STATE_CLOSE :
										if (control.hasClass(this.CLASS_EXTENDED_DISPLAY_OPEN)) control.removeClass(this.CLASS_EXTENDED_DISPLAY_OPEN);
										if (!control.hasClass(this.CLASS_EXTENDED_DISPLAY_CLOSED)) control.addClass(this.CLASS_EXTENDED_DISPLAY_CLOSED);
										break;
									
									default : break;
								}
								break;
							
							default : break;
						}
					},
					
					
					
					"_getDataDisplayClassInstance" : function (jQueryObjectContainer)
					{
						var container	= jQueryObjectContainer;
						var instances	= this._dataDisplayInstances;
						
						var a = this.CLASS_DATA_DISPLAY_CONTAINERS;
						
						for (var i = 0; i < a.length; i++)
						{
							var id = a[i];
							
							if (container.hasClass(id))
							{
								return instances[id];
							}
						}
						return undefined;
					},
					
					
			
				/*
				 =============================
				 SETUP
				 =============================
				 */
					"_setup" : function ()
					{
						// Save current panel height
						var h = $("div." + this.CLASS_PANEL_ADVANCED_SETTINGS).height();
						
						this._panel_height_open = (h == this.PANEL_HEIGHT_CLOSED) ? this._getDefaultPanelHeight() : h;
						
						// Configure panel open / close links
						this._setupPanelOpenCloseLinks();
						
						// Configure display open / close links
						this._setupDisplayOpenCloseLinks();
						
						// If panel !in 2 column mode (i.e. in right hand column) collapse all basic displays
						if (this._basicDisplayCollapsable()) this._collapseAllBasicDisplays();

						// Open panels and set the height from cookies
//
// DISABLED :: MECHANISM LOGIC FLAWED (Panel state history)
//
						//this._managePanels();
						
						//Set up the manufacturer range drop downs for dealer site
						this._setUpManufacturerRangeDropDown();
					},



					// Open flash graphs from cookie
//
// DISABLED :: MECHANISM LOGIC FLAWED (Panel state history)
//				
//					"_managePanels" : function ()
//					{
//						// Check if open flash graph persistence is switched on
//						if (this.DEFAULT_PANEL_PERSISTENCE)
//						{
//							// Get panels cookie
//							var enabledPanelsNamesString = $.cookie(this.DEFAULT_PANEL_STATE_COOKIE);
//								
//							// Convert the cookie to an array
//							
//							if (enabledPanelsNamesString != null)
//							{
//								this._enabledPanelsNames = enabledPanelsNamesString.split(",");
//								// Walk panels						
//								for (var _iPanelItem = 0; _iPanelItem < this._enabledPanelsNames.length; _iPanelItem++)
//								{
//									if (this._enabledPanelsNames[_iPanelItem] != "")
//									{
//										// Open the panel 
//										$("#" + this._enabledPanelsNames[_iPanelItem] + "_" + this.DEFAULT_PANEL_LINK_OPEN).click();
//									}
//								}
//							}
//						}
//					},


					
					"_setupPanelOpenCloseLinks" : function ()
					{
						var __this = this;
						$("div." + this.CLASS_PANEL_ADVANCED_SETTINGS + " div." + this.CLASS_PANEL_BODY_HEADER + " a." + this.CLASS_OPEN).click(function (e){ __this._openPanel(); });
						$("div." + this.CLASS_PANEL_ADVANCED_SETTINGS + " div." + this.CLASS_PANEL_BODY_HEADER + " a." + this.CLASS_CLOSE).click(function (e){ __this._closePanel(); });
					},
			
					
					"_setupDisplayOpenCloseLinks" : function ()
					{
						var __this = this;
						
						// If this._twoColumnDisplayMode set up extended display open/close links
						// Else set up standard display links + must haves extended display link
						var isRangeDetails = (this._isRangeDetailsDisplay()) ? true : false;
						
						var extendedDisplay = (this._twoColumnDisplayMode() || isRangeDetails) ? true : false;
						
						switch (extendedDisplay)
						{
							case true :
								// Column 1
								$("div." + this.CLASS_PANEL_ADVANCED_SETTINGS + " div." + this.CLASS_COLUMN_1 + " div." + this.CLASS_CONTROL_CONTAINER + " a." + this.CLASS_EXTENDED_DISPLAY_CONTROL_OPEN).click(function (){ __this._openDisplay(this, __this.SCOPE_EXTENDED, ((!isRangeDetails)? 1 : 0)); });
								$("div." + this.CLASS_PANEL_ADVANCED_SETTINGS + " div." + this.CLASS_COLUMN_1 + " div." + this.CLASS_CONTROL_CONTAINER + " a." + this.CLASS_EXTENDED_DISPLAY_CONTROL_CLOSE).click(function (){ __this._closeDisplay(this, __this.SCOPE_EXTENDED, ((!isRangeDetails)? 1 : 0)); });
								
								// Column 2
								$("div." + this.CLASS_PANEL_ADVANCED_SETTINGS + " div." + this.CLASS_COLUMN_2 + " div." + this.CLASS_CONTROL_CONTAINER + " a." + this.CLASS_EXTENDED_DISPLAY_CONTROL_OPEN).click(function (){ __this._openDisplay(this, __this.SCOPE_EXTENDED, ((!isRangeDetails)? 2 : 0)); });
								$("div." + this.CLASS_PANEL_ADVANCED_SETTINGS + " div." + this.CLASS_COLUMN_2 + " div." + this.CLASS_CONTROL_CONTAINER + " a." + this.CLASS_EXTENDED_DISPLAY_CONTROL_CLOSE).click(function (){ __this._closeDisplay(this, __this.SCOPE_EXTENDED, ((!isRangeDetails)? 2 : 0)); });
								break;
								
							case false :
								$("div." + this.CLASS_PANEL_ADVANCED_SETTINGS + " div." + this.CLASS_CONTROL_CONTAINER + " a." + this.CLASS_STANDARD_DISPLAY_CONTROL_OPEN).click(function (){ __this._openDisplay(this, __this.SCOPE_STANDARD, 0); });
								$("div." + this.CLASS_PANEL_ADVANCED_SETTINGS + " " + this.ID_MUST_HAVES_CONTROL_CONTAINER + " a." + this.CLASS_EXTENDED_DISPLAY_CONTROL_OPEN).click(function (){ __this._openDisplay(this, __this.SCOPE_EXTENDED, 0); });
								$("div." + this.CLASS_PANEL_ADVANCED_SETTINGS + " div." + this.CLASS_CONTROL_CONTAINER + " a." + this.CLASS_STANDARD_DISPLAY_CONTROL_CLOSE).click(function (){ __this._closeDisplay(this, __this.SCOPE_STANDARD, 0); });
								$("div." + this.CLASS_PANEL_ADVANCED_SETTINGS + " " + this.ID_MUST_HAVES_CONTROL_CONTAINER + " a." + this.CLASS_EXTENDED_DISPLAY_CONTROL_CLOSE).click(function (){ __this._closeDisplay(this, __this.SCOPE_EXTENDED, 0); });
								break;
							
							default : break;
						}						
					},
					
					"_setUpManufacturerRangeDropDown" : function ()
					{
							//get our manufacturer select list
							var jqManufacturerSelect = $("#SearchCriteria select.manufacturer");
							//get our model select list.
							var jqRangeSelect = $("#SearchCriteria select.ranges");
							
							if(jqManufacturerSelect.val() == "null")
							{
								jqRangeSelect.attr("disabled" , "disabled");
							}
							
							
							if(jqManufacturerSelect != null)
							{
								jqManufacturerSelect.bind("change" , function()
									{
										var form = $("#SearchCriteria");
										form.trigger("submit");
									}
								)
							}
					},
			
			
			
				/*
				 =============================
				 DISPLAY CREATION
				 =============================
				 */
			
			
			
				/*
				 =============================
				 DISPLAY CONTROL
				 =============================
				 */
					"_collapseAllBasicDisplays" : function ()
					{
						var __this = this;
						// Get all control containers and add 'basic display closed' class and remove and 'extend display open' class
						$("div." + this.CLASS_CONTROL_CONTAINER).each (function ()
						{
							var _item = $(this);
							if (_item.hasClass(__this.CLASS_STANDARD_DISPLAY_OPEN)) _item.removeClass(__this.CLASS_STANDARD_DISPLAY_OPEN);
							if (!_item.hasClass(__this.CLASS_STANDARD_DISPLAY_CLOSED)) _item.addClass(__this.CLASS_STANDARD_DISPLAY_CLOSED);
							if (_item.hasClass(__this.CLASS_EXTENDED_DISPLAY_OPEN)) _item.removeClass(__this.CLASS_EXTENDED_DISPLAY_OPEN);
							if (!_item.hasClass(__this.CLASS_EXTENDED_DISPLAY_CLOSED)) _item.addClass(__this.CLASS_EXTENDED_DISPLAY_CLOSED);
						});
					},
			
					
					"_openPanel" : function ()
					{
						var p = $("div." + this.CLASS_PANEL_ADVANCED_SETTINGS);
						if (p.hasClass(this.CLASS_PANEL_ADVANCED_SETTINGS_CLOSED)) p.removeClass(this.CLASS_PANEL_ADVANCED_SETTINGS_CLOSED);
						
						var body = p.find("div." + this.CLASS_PANEL_BODY_CONTAINER);
						if(body.hasClass(this.CLASS_PANEL_BODY_CONTAINER_CLOSED)) body.removeClass(this.CLASS_PANEL_BODY_CONTAINER_CLOSED);
						if(!body.hasClass(this.CLASS_PANEL_BODY_CONTAINER_OPEN)) body.addClass(this.CLASS_PANEL_BODY_CONTAINER_OPEN);
						
						$("div." + this.CLASS_PANEL_ADVANCED_SETTINGS).height(this._panel_height_open);
					},
					
					
					"_closePanel" : function ()
					{
						var p = $("div." + this.CLASS_PANEL_ADVANCED_SETTINGS);
						p.addClass(this.CLASS_PANEL_ADVANCED_SETTINGS_CLOSED);
						
						var body = p.find("div." + this.CLASS_PANEL_BODY_CONTAINER);
						if(body.hasClass(this.CLASS_PANEL_BODY_CONTAINER_OPEN)) body.removeClass(this.CLASS_PANEL_BODY_CONTAINER_OPEN);
						if(!body.hasClass(this.CLASS_PANEL_BODY_CONTAINER_CLOSED)) body.addClass(this.CLASS_PANEL_BODY_CONTAINER_CLOSED);
						
						$("div." + this.CLASS_PANEL_ADVANCED_SETTINGS).height(this.PANEL_HEIGHT_CLOSED);
					},
					
					
					"_openDisplay" : function (link, scope, columnId)
					{
						//alert("_openDisplay : " + scope + " / col = " + columnId);

						var panel		= $("div." + this.CLASS_PANEL_ADVANCED_SETTINGS);
						var control		= $(link).parent("div." + this.CLASS_CONTROL_CONTAINER);
						var display;
						
						var panelDataDisplayClass = this._getDataDisplayClassInstance(control);
						
						// Current panel height
						var p_h		= panel.height();
						
						// New panel height
						var new_h;
						
						switch (scope)
						{
							case this.SCOPE_STANDARD :
								display		= this._getStandardDisplay(control);
								var d_h		= display.height() + parseInt(display.css("paddingTop")) + parseInt(display.css("paddingBottom")) + parseInt(display.css("borderTopWidth"));
								var c_h		= control.height();
								new_h		= p_h + d_h - c_h; //alert("p_h = " + p_h + "\nd_h = " + d_h + "\nc_h = " + c_h + "\nnew_h = " + new_h);
								this._setDisplayState(control, scope, this.STATE_OPEN);
								break;
							
							case this.SCOPE_EXTENDED :
								var panel_body	= panel.find("div." + this.CLASS_PANEL_BODY_CONTENT);
								var column_1	= panel.find("div." + this.CLASS_COLUMN_1);
								var column_2	= panel.find("div." + this.CLASS_COLUMN_2);
								
								display			= control.find("div." + this.CLASS_EXTENDED_DISPLAY);
								
								if (columnId == 0)
								{
									// Set display state class - occurs mid-calculation so 'open' styles (padding) can be used in next stage of calculation
									this._setDisplayState(control, scope, this.STATE_OPEN);
									
									// Continue with calculation
									var d_h		= display.height() + parseInt(display.css("paddingTop")) + parseInt(display.css("paddingBottom")) + parseInt(display.css("borderTopWidth"));
									new_h		= p_h + d_h;
								}
								else 
								{
									var c_h		= (columnId == 1) ? column_1.height() : column_2.height();
									c_h			+= (parseInt(panel_body.css("paddingTop")) + parseInt(panel_body.css("marginBottom"))); // Add column y position and any container padding to height
									
									// Set display state class - occurs mid-calculation so 'open' styles (padding) can be used in next stage of calculation
									this._setDisplayState(control, scope, this.STATE_OPEN);
									
									// Continue with calculation
									var d_h		= display.height() + parseInt(display.css("paddingTop")) + parseInt(display.css("paddingBottom")) + parseInt(display.css("borderTopWidth"));
									var xs_h	= p_h - c_h;
									var add_h	= Math.max(d_h - xs_h, 0);
									new_h		= p_h + add_h; //alert("p_h = " + p_h + "\nc_h = " + c_h + "\nd_h = " + d_h + "\nxs_h = " + xs_h + "\nadd_h = " + add_h + "\nnew_h = " + new_h);
								}
								
								//
								//
								// CREATE DATA DISPLAY [If range details or 2 column mode]
								//
								//
								if (this._isRangeDetailsDisplay() || columnId != 0)
								{
									if (panelDataDisplayClass)
									{
										try { panelDataDisplayClass.createDisplay(); }
										catch (e){}
									}
								}
								
								
								break;
							
							default : 
								new_h = p_h;
								break;
						}
						
						// Save new overal panel height
						this._panel_height_open = new_h;
						
						// Set new overall panel height
						panel.height(new_h);

//
// DISABLED :: MECHANISM LOGIC FLAWED (Panel state history)
//
//						var aName = $(link).attr("id");
//						var exists = false;
//						// Find panel
//												
//						for (var _openPanelIndex = 0; _openPanelIndex < this._enabledPanelsNames.length; _openPanelIndex++)
//						{
//							if (this._enabledPanelsNames[_openPanelIndex] != "")
//							{
//								if (aName == this._enabledPanelsNames[_openPanelIndex] + "_" + this.DEFAULT_PANEL_LINK_OPEN)
//								{
//									// already included
//									exists = true;
//									break;
//								}
//							}
//						}
//						if (!exists)
//						{
//							// Get in-memory name
//							var name = this._extract(aName)
//							// Push enabled panel into enabled panels array
//							this._enabledPanelsNames.push(name);
//						}
//						// Save cookies
//						this._saveCookies(new_h)
						
					},
					
					// extract value
//
// DISABLED :: MECHANISM LOGIC FLAWED (Panel state history)
//
//					"_extract" : function (aName)
//					{
//						// copy to underscore
//						var nameLen = aName.indexOf('_');
//						
//						var trueName = "";
//						
//						if (nameLen > 1)
//						{
//							trueName = aName.substr(0, nameLen);
//						}
//						return trueName;
//					},
					
					"_closeDisplay" : function (link, scope, columnId)
					{
						//alert("_closeDisplay : " + scope + " / col = " + columnId);
						
						var panel		= $("div." + this.CLASS_PANEL_ADVANCED_SETTINGS);
						var control		= $(link).parent("div." + this.CLASS_CONTROL_CONTAINER);
						var display;
						
						// Current panel height
						var p_h	= panel.height();
						
						// New panel height
						var new_h;
						
						switch (scope)
						{
							case this.SCOPE_STANDARD :
								this._setDisplayState(control, scope, this.STATE_CLOSE);
								display		= this._getStandardDisplay(control);
								var d_h		= display.height() + parseInt(display.css("paddingTop")) + parseInt(display.css("paddingBottom")) + parseInt(display.css("borderTopWidth"));
								var c_h		= control.height();
								new_h		= (p_h - d_h) + c_h;
								break;
							
							case this.SCOPE_EXTENDED :
								var panel_body	= panel.find("div." + this.CLASS_PANEL_BODY_CONTENT);
								var column_1	= panel.find("div." + this.CLASS_COLUMN_1);
								var column_2	= panel.find("div." + this.CLASS_COLUMN_2);
								
								var additionalColumn_h	= (parseInt(panel_body.css("paddingTop")) + parseInt(panel_body.css("marginBottom")));
								
								var col1_h	= column_1.height() + additionalColumn_h;
								var col2_h	= column_2.height() + additionalColumn_h;
								
								display		= control.find("div." + this.CLASS_EXTENDED_DISPLAY);
								var d_h		= display.height() + parseInt(display.css("paddingTop")) + parseInt(display.css("paddingBottom")) + parseInt(display.css("borderTopWidth"));
								
								if (columnId == 0)
								{
									// No column checking required so just set remove display height
									new_h = p_h - d_h;
								}
								else 
								{
									// Is current column the column that is controlling overall panel height
									var colControllingHeight = false;
									var column_primary_h;
									var column_secondary_h;
									
									if (columnId == 1)
									{
										colControllingHeight	= (col1_h > col2_h)? true : false;
										column_primary_h		= col1_h;
										column_secondary_h		= col2_h;
									}
									else if (columnId == 2)
									{
										colControllingHeight	= (col2_h > col1_h)? true : false;
										column_primary_h		= col2_h;
										column_secondary_h		= col1_h;
									}
									
									if (!colControllingHeight) new_h = p_h; 
									else
									{
										var calc_new_h = column_primary_h - d_h;
										if (calc_new_h < column_secondary_h)
										{
											var max_reduction_h = column_primary_h - column_secondary_h;
											calc_new_h			= column_primary_h - max_reduction_h;
										}
										new_h = calc_new_h; //alert(" p_h = " + p_h + "\n new_h = " + new_h + "\n d_h = " + d_h + "\n col1_h = " + col1_h + "\n col2_h = " + col2_h + "\t column_primary_h = " + column_primary_h + "\n column_secondary_h = " + column_secondary_h);
									}
								}
								
								this._setDisplayState(control, scope, this.STATE_CLOSE);
								break;
							
							default : 
								new_h = p_h;
								break;
						}
						
						if (new_h != p_h)
						{
							// Save new overal panel height
							this._panel_height_open = new_h;
							
							// Set new overall panel height
							panel.height(new_h);
						}

//
// DISABLED :: MECHANISM LOGIC FLAWED (Panel state history)
//
//						var aName = $(link).attr("id");
//						var exists = -1;
//						
//						// Find panel
//						for (var _closePanelIndex = 0; _closePanelIndex < this._enabledPanelsNames.length; _closePanelIndex++)
//						{
//							if (this._enabledPanelsNames[_closePanelIndex] != "")
//							{
//								if (aName == this._enabledPanelsNames[_closePanelIndex] + "_" + this.DEFAULT_PANEL_LINK_CLOSE)
//								{
//									// already included
//									exists = _closePanelIndex;
//									break;
//								}
//							}
//						}
//						if (exists > -1)
//						{
//							// remove from array list using splice (as pop method does not work)
//							this._enabledPanelsNames.splice(_closePanelIndex, 1);
//						}
//						// Save cookies
//						this._saveCookies(new_h);

					}
			
					// Saves cookies for open states and panel height
//
// DISABLED :: MECHANISM LOGIC FLAWED (Panel state history)
//
//					"_saveCookies" : function (new_h)
//					{
//						// Pack array in string
//						var cookieNames = this._enabledPanelsNames.join();
//						
//						// Save cookie
//						$.cookie(this.DEFAULT_PANEL_STATE_COOKIE, cookieNames, { expires: 7, path: "/" });
//						
//						// Save height for the panel in the cookie 						
//						$.cookie(this.CLASS_PANEL_ADVANCED_SETTINGS + this.DEFAULT_PANEL_HEIGHT_COOKIE, new_h, { expires: 7, path: "/" });												
//					}			
			
				/*
				 =============================
				 INTERNAL EVENT HANDLERS
				 =============================
				 */
				
				
		}
	);
	
	//alert("hellooooooooooooooooooooooooooo");



/// <reference path="../../../../jQuery/1.3.2/jquery-1.3.2-vsdoc.js" />

/**
 *
 * DisplayManager
 *
 * This class manages the search configuration status within the client environment
 *
 * Managing status and communications between otherwise disparate page elements including:
 *	- Multiple, separate, flash display elements
 *	- Associated html display elements (checkbox links, html slider widgets etc) 
 *
 */

	// 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.controls")) manheim.global.createNamespace("manheim.portfolio.common.controls", "1.0");
	
	
	// Class definition :

	manheim.portfolio.common.controls.ImageListControls = Object.subClass
	(
		{
			/*
			=============================
			CONSTANTS
			=============================
			*/
			SELECTED_CLASS					: "selected",
			SELECTED_HOVER_CLASS			: "selected-hover",
			UNSELECTED_CLASS				: "unselected",
			UNSELECTED_HOVER_CLASS			: "unselected-hover",
			
			CLASS_IMAGELIST_CONTAINER		: "imagelist-container",
			
			SELECTOR_IMAGELIST_CONTAINER	: "div.imagelist-container",
			SELECTOR_FIELD_IMAGELIST		: "div.field-imagelist",
			
			/*
			=============================
			CONSTRUCTOR
			=============================
			*/
			init: function() 
			{
			
			},
			
			
			/*
			=============================
			PUBLIC MEMBERS
			=============================
			*/
			bindContainer : function(jqContainer)
			{
				this.bind(jqContainer.find(this.SELECTOR_IMAGELIST_CONTAINER));
			},
			
			//function used to configure the colour image buttons
			bind : function (jqContainer, unselectedClass, unselectedHoverClass, selectedClass, selectedHoverClass)
			{
				// set optional params
				unselectedClass			= (unselectedClass)?		unselectedClass			: this.UNSELECTED_CLASS;
				unselectedHoverClass	= (unselectedHoverClass)?	unselectedHoverClass	: this.UNSELECTED_HOVER_CLASS;
				selectedClass			= (selectedClass)?			selectedClass			: this.SELECTED_CLASS;
				selectedHoverClass		= (selectedHoverClass)?		selectedHoverClass		: this.SELECTED_HOVER_CLASS;
				
				// set class scope
				var _this = this;
				
				// ensure we are in correct sope
				if (!jqContainer.hasClass(this.CLASS_IMAGELIST_CONTAINER))
				{
					jqContainer = jqContainer.find(this.SELECTOR_IMAGELIST_CONTAINER);
				}
				
				jqContainer.find(this.SELECTOR_FIELD_IMAGELIST).each(function() {
					//store the imageButton wrapper
					var imageListContainer = $(this).closest(_this.SELECTOR_IMAGELIST_CONTAINER);
					var imageButtonContainer = $(this);
			        
					// work out the image code
					var src = imageButtonContainer.find("img:first").attr("src");
					var imageCode = src.substring(src.replace(/_selected/, '').lastIndexOf('_') + 1, src.replace(/_selected/, '').lastIndexOf('_') + 3);
			        
					// add image code to image button
					this.imageCode = imageCode;
			        
					//on the hover of each of its images, switch the container's class
					imageButtonContainer.find('img').each(function() {
						var image = $(this);
						
						image.hover(function() {
							if (imageButtonContainer.hasClass(unselectedClass)) {
								imageButtonContainer.removeClass(unselectedClass).addClass(unselectedHoverClass);
							}
							else {
								imageButtonContainer.removeClass(selectedClass).addClass(selectedHoverClass);
							}
						},function() {
							if (imageButtonContainer.hasClass(unselectedHoverClass)) {
								imageButtonContainer.removeClass(unselectedHoverClass).addClass(unselectedClass);
							}
							else {
								imageButtonContainer.removeClass(selectedHoverClass).addClass(selectedClass);
							}
						});
						
						// add references to parent objects
						this.imageListContainer = imageListContainer;
						this.imageButtonContainer = imageButtonContainer;
						
						//configure the click event
						var eventData =
						{
							"unselectedHoverClass"	: unselectedHoverClass,
							"selectedHoverClass"	: selectedHoverClass
						};
						
						image.bind("click.imageclick", eventData, function(e) { _this._handleClick(e); } );
						
					});
				});
			},
			
			
			/*
			=============================
			PRIVATE MEMBERS
			=============================
			*/
			
			//function used to handle the click of an imagebutton
			_handleClick : function (e)
			{
			    
				var _imageListContainer		= e.target.imageListContainer;
				var _imageButtonContainer	= e.target.imageButtonContainer;
				var _image					= $(e.target);
				var _unselectedHoverClass	= e.data.unselectedHoverClass;
				var _selectedHoverClass		= e.data.selectedHoverClass;
				var _imageCode				= _imageButtonContainer[0].imageCode;
			    
				//find the input that holds the values
				var _input = _imageListContainer.find('input');
			      
				if(_image.hasClass(_selectedHoverClass)) {
					_imageButtonContainer.removeClass(_selectedHoverClass).addClass(_unselectedHoverClass);
					_input.val(_input.val().replace(_imageCode, '').replace(/,,/, ','));
				}
				else {
					_imageButtonContainer.removeClass(_unselectedHoverClass).addClass(_selectedHoverClass);
					_input.val((_input.val() + ',' + _imageCode).replace(/,,/, ','));
				}
				_input.trigger("change");
			}
			
		}
	);

/// <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" />

/**
 *
 * Location map feature
 *
 */
	
	if (!manheim.global.isNamespaceDefined("manheim.portfolio.common.display.views")) manheim.global.createNamespace("manheim.portfolio.common.display.views", "1.0");
	
	
	if (manheim.portfolio.common.display.SwfExternalDataHost.subClass)
	{
			manheim.portfolio.common.display.views.LocationMapFeature = manheim.portfolio.common.display.SwfExternalDataHost.subClass(
			{
				
				
	//			
	//				=== DATA STRUCTURE ====
	//
	//				{
	//					"userCriteria" : 
	//					{
	//						"location"		: "AA1 1AA",	// [ String ]			[ non-selected = undefined ]
	//						"easting"		: 00000,		// [ int (5 digit)]		[ non-selected = -1 ]
	//						"northing"		: 00000,		// [ int (5 digit)]		[ non-selected = -1 ]
	//						"maxDistance"	: -1;			// [ int ]				[ non-selected = -1 ]
	//					},
	//					
	//					"centreData" : 
	//					[
	//						{
	//							"centreId"			: -1,		// [ int ]
	//							"centreName"		: "",		// [ String ]			[ non-selected = undefined ]
	//							"easting"			: 00000,	// [ int (5 digit)]		[ non-selected = -1 ]
	//							"northing"			: 00000,	// [ int (5 digit)]		[ non-selected = -1 ]
	//							"distance"			: -1;		// [ int ]				[ non-selected = -1 ]
	//						}
	//					]
	//				}
	//
				
				
				/*
				 =============================
				 CONSTANTS
				 =============================
				 */
					DISPLAY_MODE_DEFAULT	: "DISPLAY_MODE_DEFAULT",
					DISPLAY_MODE_NARROW		: "DISPLAY_MODE_NARROW",
				
					
					DISPLAY_HEIGHT			: 380,
					
					DISPLAY_WIDTH_DEFAULT	: 414,
					DISPLAY_WIDTH_NARROW	: 265,
					
					
					SELECTOR_LINKS_CONTAINER : "div.search-location-panel-container > div.panel-search-location div.panel-body > div.panel-body-footer > div.panel-body-footer-links",
					
					CLASS_PANEL_OPEN	: "panel-search-location-open",
					CLASS_PANEL			: "panel-search-location",
					
					CLASS_PANEL_BODY_CONTAINER			: "panel-body-container",
					CLASS_PANEL_BODY_CONTAINER_OPEN		: "panel-body-container-open",
					CLASS_PANEL_BODY_CONTAINER_CLOSED	: "panel-body-container-closed",
					
					CLASS_OPEN : "open",
					CLASS_CLOSE : "close",
					
					
					
					EVENT_TYPE_INVALID_LOCATION : "EVENT_TYPE_INVALID_LOCATION",
					EVENT_TYPE_UPDATE_DISTANCE	: "EVENT_TYPE_UPDATE_DISTANCE",
					
					
					EVENT_PROP_TYPE			: "type",
					EVENT_PROP_MAX_DISTANCE	: "distanceMax",
					
					
					
				/*
				 =============================
				 CONFIGURATION PROPERTIES (instance configuration)
				 =============================
				 */
				
				
				
				/*
				 =============================
				 CONSTRUCTOR
				 =============================
				 */
					init : function (classInstanceID, replacementTargetParentID, replacementTargetID, swfInstanceID, swfData, displayMode)
					{
						
						// Configure flash object attributes and properties
						var targetFlashVersion		= "9.0.48";
						//var targetFlashVersion	= "100";
						
						
						var width	= (displayMode == this.DISPLAY_MODE_NARROW) ? this.DISPLAY_WIDTH_NARROW : this.DISPLAY_WIDTH_DEFAULT;
						var height	= this.DISPLAY_HEIGHT;
						
						
						var swfAttributes				= {};
						swfAttributes.data				= "/assets/flash/MapLocationFeature.swf";
						swfAttributes.id				= swfInstanceID;
						swfAttributes.name				= swfInstanceID;
						swfAttributes.width				= width;
						swfAttributes.height			= height;
						swfAttributes.pluginspage		= "http://www.macromedia.com/go/getflashplayer";
						
						var swfParameters				= {};
						swfParameters.align				= "top";
						swfParameters.allowfullscreen	= true;
						swfParameters.allowscriptaccess	= "sameDomain";
						swfParameters.base				= "../../";
						swfParameters.bgcolor			= "#c7c7c7";
						swfParameters.devicefont		= false;
						swfParameters.loop				= false;
						swfParameters.menu				= true;
						swfParameters.play				= true;
						swfParameters.quality			= "best";
						swfParameters.salign			= "tl";
						swfParameters.scale				= "noscale";
						swfParameters.wmode				= "opaque"; //transparent || opaque
						
						
						//this._swfFlashVars = "&a=" + "a";
						
						this._swfData = swfData;
						
						// Call super class init()
						this._super(classInstanceID, replacementTargetParentID, replacementTargetID, swfInstanceID, targetFlashVersion, swfAttributes, swfParameters, "", swfData, true);
						
						
						
						
						// Configure panel open / close functionality
						this._configureOpenCloseMechanism();
						
				
						// TEMP :: Configure temporary testing links >>> REMOVE WHEN COMPLETE!!!
						this.__setupTestLinks();
					},
				
				
				
				/*
				 =============================
				 INTERNAL RUN-TIME PROPERTIES
				 =============================
				 */
				
				
				
				/*
				 =============================
				 PUBLIC METHODS
				 =============================
				 */
					
					
					/*
					 --------------------------------
					 [ OVERRIDE ] :: Triggers data load
					 --------------------------------
					*/
						setSwfObjectReady : function (b, swfObjectID)
						{
							//alert("setSwfObjectReady : swfObjectID = " + swfObjectID);
							this._super(b, swfObjectID);
							if (b && this.isSwfObjectInstanceDefined()) this.getSwfObject().triggerDataLoad();
						},
					
					
					
					/*
					 --------------------------------
					 --------------------------------
					*/
						processDistanceUpdate : function (distance)
						{
							// Pass to internal processing method
							var e = {};
							e[this.EVENT_PROP_TYPE] = this.EVENT_TYPE_UPDATE_DISTANCE;
							e[this.EVENT_PROP_MAX_DISTANCE] = distance;
							
							this._updateMapStatus(e);
						},
						
						
						processInvalidLocationUpdate : function ()
						{
							// Pass to internal processing method
							var e = { "type" : this.EVENT_TYPE_INVALID_LOCATION };
							this._updateMapStatus(e);
						},
						
						
						
						processDataUpdate : function (dataObject)
						{
							this._updateMapData(dataObject);
						},
						
						
						
				
				
				/*
				 =============================
				 INTERNAL METHODS
				 =============================
				 */
					/*
					 =============================
					 INTERNAL EVENT HANDLERS
					 =============================
					 */
						_handlePanelOpen : function (e)
						{
							var link = $(e.target);
							var open = (link.hasClass(this.CLASS_OPEN)) ? true : false;
							
							var panel		= link.closest("div." + this.CLASS_PANEL); 
							var panelBody	= link.closest("div." + this.CLASS_PANEL_BODY_CONTAINER);
							
							if (open)
							{
								panel.addClass(this.CLASS_PANEL_OPEN);
								panelBody.removeClass(this.CLASS_PANEL_BODY_CONTAINER_CLOSED);
								panelBody.addClass(this.CLASS_PANEL_BODY_CONTAINER_OPEN);
								
								// Create swf object if not already created
								if (!this.isSwfObjectInstanceDefined())
								{
									this._setupSwfObject();
								}
							}
							else
							{
								panel.removeClass(this.CLASS_PANEL_OPEN);
								panelBody.removeClass(this.CLASS_PANEL_BODY_CONTAINER_OPEN);
								panelBody.addClass(this.CLASS_PANEL_BODY_CONTAINER_CLOSED);
							}
						},
						
						
						
					/*
					 =============================
					 UTILITIES
					 =============================
					 */
				
				
				
					/*
					 =============================
					 SETUP
					 =============================
					 */
						_configureOpenCloseMechanism : function ()
						{
							var __this = this;
							
							var linksContainer = $(this.SELECTOR_LINKS_CONTAINER);
							var links = linksContainer.find("a.open-close");
							
							links.click(
								function (e)
								{
									__this._handlePanelOpen(e);
								}
							);
						},
				
				
				
					/*
					 =============================
					 DISPLAY CONTROL
					 =============================
					 */
						_updateMapStatus : function (e)
						{
							/*
							{
								"type"			: "EVENT_TYPE_UPDATE_DISTANCE" || "EVENT_TYPE_INVALID_LOCATION",
								"distanceMax"	: "200" (optional : include if == EVENT_TYPE_UPDATE_DISTANCE)
							}
							*/
							
							var type = e[this.EVENT_PROP_TYPE];
							
							// Store update in internal data object
							switch (type)
							{
								case this.EVENT_TYPE_INVALID_LOCATION :
									this._storeLocationDataInvalid();
									break;
								
								case this.EVENT_TYPE_UPDATE_DISTANCE :
									this._storeMaxDistance(e[this.EVENT_PROP_MAX_DISTANCE]);
									break; 
							}
							
							// Pass update into map if created
							if (this.getSwfObjectReady()) this.getSwfObject().remoteUpdateStatus(e);
						},
						
						
						
						_updateMapData : function (newMapData)
						{
							// Store new data
							this._swfData = newMapData;
							
							// Pass into map if created
							if (this.getSwfObjectReady()) this.getSwfObject().remoteUpdateNewData(newMapData);
						},
						
				
				
				
					/*
					 =============================
					 INTERNAL DATA STORAGE
					 =============================
					 */
						_storeLocationDataInvalid : function ()
						{
							var emptyData = 
							{
								"location"		: "",
								"easting"		: "-1",
								"northing"		: "-1",
								"distanceMax"	: -1,
								"localCentreId" : -1
							}
							
							this._swfData["userCriteria"] = emptyData;
						},
						


						_storeMaxDistance : function (distance)
						{
							try	{ this._swfData["userCriteria"]["distanceMax"] = distance; } catch (e){}
						},
					
					
					
					
					/////////////////////////////////////////
					/////////////////////////////////////////
					/////////////////////////////////////////
					/////////////////////////////////////////
					/////////////////////////////////////////
					/////////////////////////////////////////
						/////////////////////////////////////////
							/////////////////////////////////////////
								/////////////////////////////////////////
									/////////////////////////////////////////
										/////////////////////////////////////////
											
											
											__setupTestLinks : function ()
											{
												var __this = this;
												
												$("a.test-updateData").click(function (e){ __this.__TEST_newDataLoad(); });
												
												$("a.test-updateDistance").click(function (e){ __this.__TEST_distanceChange(); });
												
												$("a.test-updateInvalid").click(function (e){ __this.__TEST_invalidLocation(); });
											},
											
											
											
											
											__TEST_distanceChange : function ()
											{
												//alert("__TEST_distanceChange");
												this.processDistanceUpdate(300);
											},
											
											
											__TEST_invalidLocation : function ()
											{
												//alert("__TEST_invalidLocation");
												this.processInvalidLocationUpdate();
											},
											
					
											__TEST_newDataLoad : function ()
											{
												//alert("__TEST_newDataLoad");
												var newData = 
												{
													"userCriteria" : 
													{
														"location"		: "AA1 1AB",
														"easting"		: "30000",
														"northing"		: "30000",
														"distanceMax"	: 200,
														"localCentreId" : -1
													},
													
													"centreData" : 
													[
														{
															"centreId"			: 1,
															"centreName"		: "New centre 1",
															"easting"			: "00000",
															"northing"			: "00000",
															"distance"			: 70
														},
														{
															"centreId"		: 2,
															"centreName"	: "New centre 2",
															"easting"		: "05000",
															"northing"		: "05000",
															"distance"		: 200
														},
														{
															"centreId"		: 3,
															"centreName"	: "New centre 3",
															"easting"		: "10000",
															"northing"		: "10000",
															"distance"		: 400
														}
													]
						
												};
											
												this.processDataUpdate(newData);
											}
					
										/////////////////////////////////////////
									/////////////////////////////////////////
								/////////////////////////////////////////
							/////////////////////////////////////////
						/////////////////////////////////////////
					/////////////////////////////////////////
					/////////////////////////////////////////
					/////////////////////////////////////////
					/////////////////////////////////////////
					/////////////////////////////////////////
					/////////////////////////////////////////
					
					
					
			
			}
		);
	}
	
	
	//alert("a");


