
function ClassCYDRE()
{
	//
	// PRIVATE PROPERTIES ONLY AVAILABLE FROM WITHIN THE CLASS
	// ...must have var prefix
	//
	var _REQUEST_COUNTER = {};
	var _STR_REQUEST_URL = "/cydre.html";
	var _STR_REQUEST_METHOD = "POST"; // GET | POST
	var _SHOWN_INIT_GRAPHIC = false;
	var _INIT_GRAPH = "/site/"+_SITE_VERSION+"/images/cydre/cydre-init01.jpg";

	// LOADING CONFIG
	var _INT_LOADING_BASE_ZINDEX = 100;
	var _STR_PATH_TO_LOADER_GRAPHIC = "/images/ajax-loader.gif";
	var _INT_LOADER_GRAPHIC_WIDTH = 16;
	var _INT_LOADER_GRAPHIC_HEIGHT = 16;
	var _STR_COVER_BGCOLOUR = "#fff";
	var _INT_COVER_OPACITY = 85;
	var _INT_CYDRE_CATEGORY = 421;
	var _SUMMARY = new Object(); // To hold the actual user selection or init values
	var _STONE = new Object(); // To hold the stone selection and init values
	var _PAGINATION_SUPER_NUMBER = 0;
	_STONE["colour"] = [];
	_STONE["clarity"] = [];
	var _ARR_COLOUR = ["J", "I", "H", "G", "F", "E", "D"];
	var _ARR_CLARITY = ["SI2", "SI1", "VS2", "VS1", "VVS2", "VVS1", "IF"];
	var _ARR_DG_DISPLAY_NUMBER = [10, 20, 50, 100, 200, 500]; // User selects number of records to display
	// The order of _ARR_METALS and _ARR_METALS_DISPLAY must exactly correspond
	var _ARR_METALS = ["Palladium", "18kt White Gold", "18kt Yellow Gold", "18kt Rose Gold", "18kt Yellow Gold / 950 Platinum Head", "950 Platinum"];
	var _ARR_METALS_DISPLAY = ["PALL", "18WG", "18YG", "18RG", "18YG/PLAT", "PLAT"];
	var _ARR_DG_FIELDS = ["ref", "shape", "carat", "colour", "clarity", "cert", "total", "certificate_image"]; // Actual field headings
	var _CONTEXT_HELP_ID = "contextHelp";
	var _STR_ORDER_NOW_BTN_PATH = "/site/"+_SITE_VERSION+"/images/cydre/btn-order-now.png";
	var _STR_ORDER_NOW_BTN_PATH_OVER = "/site/"+_SITE_VERSION+"/images/cydre/btn-order-now-over.png";

	var _HSH_SUMMARY_SELECTED =
	{
		RING_SIZE_SELECTION: "Ring Size",
		METAL_TYPE:   "Metal",
		shape:    "Diamond Shape",
		carat:    "Diamond Carat",
		colour:   "Diamond Colour",
		clarity:  "Diamond Clarity",
		cert:     "Certificate",
	}

	var _ARR_DG_FIELD_WIDTHS = ["60", "60", "40", "40", "50", "50", ""]; // Actual field headings
	var _STR_IMG_PATH_SORT_ASC = "/site/3.1.4.2/images/cydre/sort-ascending.png";
	var _STR_IMG_PATH_SORT_DESC = "/site/3.1.4.2/images/cydre/sort-descending.png";
	var _BOX_NAME = "cydreDataGridBox";
	// var _BOX_WIDTH = 190; // The width of the datagrid popup box
	// var _BOX_OPEN = false;
	var _CURR_DATAGRID_DATA = new Object();

	// PUBLIC GETTERS/SETTERS
	this["BuildInterface"] = _BuildInterface;
	this["UpdateCydreSettingThumbsDisplay"] = _UpdateCydreSettingThumbsDisplay;
	this["ClickOnCssHandler"] = _ClickOnCssHandler;
	this["UpdateRingSize"] = _UpdateRingSize;
	this["cydreDataGridUpdateHandler"] = cydreDataGridUpdateHandler;
	this["SetNumberRecordsDisplayed"] = _SetNumberRecordsDisplayed;
	this["SortField"] = _SortField;
	this["ShowCert"] = _ShowCert;
	this["ShowPage"] = _ShowPage;
	this["RingDesignSearch"] = _RingDesignSearch;

	function _BuildInterface()
	{
		// arg 1: the actual command
		// arg 2: the object requiring the loading utility
		// arg1 and arg2 will often be the same
		// Additional args can be sent to server in pairs, ie arg3 is the key, arg4 is the value
		// _ServerRequest("systemTest", "cydreStone");
		_ServerRequest("cydreShape", "cydreShape", "CATE_ID", _INT_CYDRE_CATEGORY);
		// _ServerRequest("cydreSettingThumbs", "cydreSettingThumbs");
		// _ServerRequest("cydreMediaCentre", "cydreMediaCentre");
		BuildCaratSlider(this); // This sits outside the main class at the bottom of this file
		cydreColour();
		cydreClarity();
	}

	function _ServerRequest(strCommand, strObjectName)
	{
		// Rapid click stopper - If user clicks rapidly only hold the latest request
		if (_REQUEST_COUNTER[strCommand] === undefined) _REQUEST_COUNTER[strCommand] = 1;
		else _REQUEST_COUNTER[strCommand]++;

		// This function
		var strFunctionName = _GetFunctionName(arguments.callee.toString());

		// LOADING UTILITY
		_ObjectLoading(strObjectName)

		// BUILD THE REQUEST QUERY STRING
		var strKeyVal = "strCommand="+strCommand+"&strPlatform="+strObjectName;

		// ADDITIONAL ARGUMENTS TO BE PASSED THROUGH
		for (var i = 2; i < _ServerRequest.arguments.length; i += 2)
		{
			strKeyVal += "&"+_ServerRequest.arguments[i]+"="+_ServerRequest.arguments[i+1];
		}

		// Set up the request
		var xmlhttp = new XMLHttpRequest();

		// Arg3: true = asynchronous | false = synchronous
		// synchronous means the browser will be locked down and unable to function while waiting for response
		xmlhttp.open(_STR_REQUEST_METHOD, _STR_REQUEST_URL, true);

		// The callback function
		xmlhttp.onreadystatechange = function()
		{
			if (xmlhttp.readyState == 4)
			{
				// DEBUG - This shows exact string response from server
				// alert(new XMLSerializer().serializeToString(xmlhttp.responseXML));

				if (xmlhttp.status == 200)
				{
					// Convert xml string to array/hash
					var objResponse = _ParseXmlStringToObject(xmlhttp.responseXML);

					// Remove the loading graphics
					_ObjectLoading(objResponse["strPlatform"]);

					// Multiple requests stopper
					if (_REQUEST_COUNTER[objResponse["strCommand"]] !== undefined)
					{
						// If there's only 1 request in this should set back to zero
						_REQUEST_COUNTER[objResponse["strCommand"]]--;

						if (_REQUEST_COUNTER[objResponse["strCommand"]] > 0) return;
						else if (_REQUEST_COUNTER[objResponse["strCommand"]] < 0) _REQUEST_COUNTER[objResponse["strCommand"]] = 0;
					}

					// Check for errors from server-size
					if (objResponse["intResult"] == "0")
					{
						// alert(objResponse["strResult"]);
						alert(strFunctionName+"()\n"+Dump(objResponse, 3));
					}

					// Process result into commands
					switch(objResponse["strCommand"])
					{
						case "system_test": /* alert(Dump(objResponse, 3)); */ break;
						case "cydreShape":  cydreShape(objResponse["DATA"]); break;
						case "cydreSettingThumbs": cydreSettingThumbs(objResponse["DATA"]); break;
						case "cydreMediaCentre": cydreMediaCentre(objResponse["DATA"]); break;
						case "cydreMetal": cydreMetal(objResponse["DATA"]); break;
						case "cydreDataGrid":
							// Some data contained in the xml comment area - to avoid a separate server request
							// The search row count is inside squiggly brackets
							var arrMatch = objResponse["strResult"].match(/{(.*?)}/);
							if (arrMatch[1] !== undefined) _STONE["searchRowCount"] = arrMatch[1];
							else _STONE["searchRowCount"] = 0;

							_CURR_DATAGRID_DATA = objResponse["DATA"];

							// Build the datagrid
							cydreDataGrid(objResponse["DATA"]);
							break;

						default: alert(strFunctionName+"()\nUnknown command: '"+objResponse["strCommand"]+"' or internet connection slow!");
					} // End switch
				}
				else alert("Error: '"+_STR_REQUEST_URL+"' is not available");
			}
		}

		// Send the POST request
		xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		xmlhttp.send(strKeyVal);
	}

	function _ParseXmlStringToObject(responseXML) //
	{
		// INITIALISE RETURNS
		var objKeyValCollection = new Object();
		objKeyValCollection["DATA"] = new Object();

		// IF THERE'S NO REPONSE END NOW
		if(!responseXML)
		{
			objKeyValCollection["STR_VALUE"] = 0;
			objKeyValCollection["STR_KEY"] = "Sorry. Unexpected NULL response from server. Please try again.";
			return objKeyValCollection;
		}

		// BASIC SETTER RESPONSE
		if (responseXML.getElementsByTagName("strCommand")[0] != null)
			objKeyValCollection["strCommand"] = responseXML.getElementsByTagName("strCommand")[0].firstChild.data;

		if (responseXML.getElementsByTagName("strPlatform")[0] != null)
			objKeyValCollection["strPlatform"] = responseXML.getElementsByTagName("strPlatform")[0].firstChild.data;

		if (responseXML.getElementsByTagName("strResult")[0] != null)
			objKeyValCollection["strResult"] = responseXML.getElementsByTagName("strResult")[0].firstChild.data;

		if (responseXML.getElementsByTagName("intResult")[0] != null)
			objKeyValCollection["intResult"] = responseXML.getElementsByTagName("intResult")[0].firstChild.data;

		// DATA ELEMENT RESPONSE - PARSE
		if (responseXML.getElementsByTagName("item")[0] != null)
		{
			var arrItems = responseXML.getElementsByTagName("item")

			for(var i = 0; i < arrItems.length; i++)
			{
				var objTmpCollection = new Object;

				// alert(arrItems[i].getAttribute("id"));
				var strTmpItemId = arrItems[i].getAttribute("id");

				for(var j = 0; j < arrItems[i].childNodes.length; j++)
				{
					// EXTRACT THE KEY/VALUE
					// alert(strNodeName = arrItems[i].childNodes[j].nodeName+":"+arrItems[i].childNodes[j].firstChild.nodeValue);
					var strNodeName = arrItems[i].childNodes[j].nodeName;
					var strNodeValue = "";
					if (arrItems[i].childNodes[j].firstChild != undefined) strNodeValue = arrItems[i].childNodes[j].firstChild.data;
					objTmpCollection[strNodeName] = strNodeValue;
				}
				// ADD TO MAIN ARRAY
				objKeyValCollection["DATA"][strTmpItemId] = objTmpCollection;
				// objKeyValCollection["DATA"].push(objTmpCollection);
				// alert(Dump(objTmpCollection, 2));
			}
		}
		return objKeyValCollection;
	}

	// arg1: strIdName - id of the html object
	// arg2: strObjBtnTitle - the actual text to display on the button
	// arg3: strActionKey - the colon separated string of arguments to pass
	function _CreateButton(strIdName, strObjBtnTitle, strActionKey, strClassName, blnEnableAction, strContextHelp)
	{
		// CREATE ANCHOR ELEMENT - The onclick event doesn't work as anchor tag
		var objTmp = document.createElement("div");
		objTmp["id"] = strIdName;

		if (strClassName != undefined)
		{
			objTmp.setAttribute("class", strClassName); // For Most Browsers
			objTmp.setAttribute("className", strClassName); // For IE; harmless to other browsers
		}

		if (typeof strObjBtnTitle == "string")
		{
			// CREATE TEXT ELEMENT
			var objTxtNode = document.createTextNode(strObjBtnTitle);
			objTmp.appendChild(objTxtNode);
		}
		else // object ie image
		{
			objTmp.appendChild(strObjBtnTitle);
		}

		// CREATE THE ACTION
		if (blnEnableAction)
		{
			try // IE
			{
				objTmp.onclick = function() { return _OnClickExecute(this, strActionKey) };
			}
			catch (err)
			{
				objTmp.setAttribute("onclick", "return _OnClickExecute(this, strActionKey);");
			}
		}

		// Context help
		if (strContextHelp !== undefined)
		{
			var objContext = document.createElement("span");
			objContext["innerHTML"] = strContextHelp;
			objTmp.appendChild(objContext);
		}

		return objTmp;
	}

	function _OnClickExecute(objRequest, strActionKey)
	{
		// alert(strActionKey);

		// Split into parts at the colon
		var arrTmp = strActionKey.split(":");
		for (var i = 2; i < arrTmp.length; i+=2)
		{
			_SUMMARY[arrTmp[i]] = arrTmp[i+1]; // Set/update the summary with this value
		}

		switch(arrTmp[0])
		{
			case "cydreMetalUpdateHandler":
				cydreMetalUpdateHandler();
			break;

			case "cydreColour":
				if (arrTmp[2] == "colour") cydreColourUpdateHandler(arrTmp[3]);
			break;

			case "cydreClarity":
				if (arrTmp[2] == "clarity") cydreClarityUpdateHandler(arrTmp[3]);
			break;

			case "cydreDataGridUpdateHandler":
				if (_SUMMARY["startRow"] !== undefined)
				{
					_STONE["startRow"] = _SUMMARY["startRow"];
					_SUMMARY["startRow"] = undefined;
				}
				cydreDataGridUpdateHandler();
			break;

			case "cydreSummary":
				cydreSummary();
			break;

			// Default is to make a server request
			default:
				_ServerRequest(arrTmp[0], arrTmp[1], arrTmp[2], arrTmp[3]);
				// cydreSummary();
		} // End switch

		// Switch to "on" button state

		_ClickOnCssHandler(objRequest);
		return false;
	}

	function _ClickOnCssHandler(obj)
	{
		if (obj["id"] == undefined) return;

		var strItemId = obj["id"];
		var arrTmp = strItemId.split("_");
		var strParentObjName = arrTmp[0];
		var strOrigStyleClass = arrTmp[0]+"Item";
		var strOnStyleClass = arrTmp[0] + "ItemOn";
		// alert("PARENT OBJECT ID: "+strParentObjName+"\nCURR OBJECT ID: "+obj["id"]+"\nORIG STYLE NAME: "+strOrigStyleClass+"\nNEW STYLE NAME: "+strOnStyleClass);

		var objParentNode = document.getElementById(strParentObjName);
		var arrChildNodes = objParentNode.getElementsByTagName("div");

		switch(strParentObjName)
		{
			// Special cases
			// case "cydreShapeasdfdsasd":
			// case "cydreSettingThumbs":
			// case "leftContainer": // Media Suite buttons

			// Each is toggled
			case "cydreColour":
				// alert(_STONE["colour"].length);
				for(var i = 0; i < arrChildNodes.length; i++)
				{
					var strClassName = "";
					try { strClassName = arrChildNodes[i].getAttribute("class"); }
					catch (err) { strClassName = arrChildNodes[i].getAttribute("className"); }

					// These are selected
					if (InArray(arrChildNodes[i]["innerHTML"], _STONE["colour"])) ChangeCssClass(arrChildNodes[i], strOnStyleClass);

					// These are not
					else ChangeCssClass(arrChildNodes[i], strOrigStyleClass);
				}

			break;

			// Each is toggled
			case "cydreClarity":
				// alert(_STONE["clarity"].length);
				for(var i = 0; i < arrChildNodes.length; i++)
				{
					var strClassName = "";
					try { strClassName = arrChildNodes[i].getAttribute("class"); }
					catch (err) { strClassName = arrChildNodes[i].getAttribute("className"); }

					// These are selected
					if (InArray(arrChildNodes[i]["innerHTML"], _STONE["clarity"])) ChangeCssClass(arrChildNodes[i], strOnStyleClass);

					// These are not
					else ChangeCssClass(arrChildNodes[i], strOrigStyleClass);
				}

			break;

			// Normal behaviour
			// ... when click it shows on position, all others are switch to off
			default:
				// Switch off all the others
				// var objParentNode = obj.parentNode;
				// alert(arrChildNodes["id"] +" "+arrChildNodes.length);
				for(var i = 0; i < arrChildNodes.length; i++)
				{
					var strClassName = "";
					try
					{
						strClassName = arrChildNodes[i].getAttribute("class");
					}
					catch (err)
					{
						strClassName = arrChildNodes[i].getAttribute("className");
					}

					try
					{
						if (strClassName.match(/grey/i)) continue; // This one is greyed out
						else ChangeCssClass(arrChildNodes[i], strOrigStyleClass);
					}
					catch (err)
					{
						//
					}
				}

				// Change the current element
				ChangeCssClass(obj, strOnStyleClass);

			break;
		} // End switch
	}

	function ChangeCssClass(obj, strNewStyleClass)
	{
		if (!obj) return;
		else if (strNewStyleClass == "") return;

		// alert(obj["id"]+"  "+strNewStyleClass);
		var blnDebug = false;
		var blnParseEntireStyle = false;

		if (!blnParseEntireStyle)
		{
			obj.setAttribute("class", strNewStyleClass); // For Most Browsers
			obj.setAttribute("className", strNewStyleClass); // For IE; harmless to other browsers
		}
		else
		{
			// This may need to be modified ... rather than setting
			// the class, the literal key should match whatever is in the style sheet rule
			// for example ... div.myStyle instead of myStyle
			var objStyle = _GetCssObjectByRuleName(strNewStyleClass);

			var str = "CSS RULES FOR CLASS/ID: "+strNewStyleClass+"\n";
			if (objStyle)
			{
				for (key in objStyle)
				{
					if (objStyle[key] == "") continue;
					else if (key == "") continue;

					// For FireFox to route out a few problems
					if (navigator.userAgent.indexOf("Firefox") != -1)
					{
						try
						{
							key = key.toString();
							if (blnDebug) objStyle[key] = objStyle[key].toString();
							// if (objStyle[key].match("/overline/gi")) continue;
						}
						catch(err)
						{
							//alert((typeof objStyle[key]));
							continue;
						}
					}
					if (blnDebug) str +=key+":"+objStyle[key]+";"; // For testing
					if (objStyle[key]) obj["style"][key] = objStyle[key];
				}
			}
			if (blnDebug) alert(str); // For testing
		}
	}

	//
	// Looks through all style sheet for a particular rule name
	//
	function _GetCssObjectByRuleName(strCssRuleName)
	{
		var blnDebug = false;
		var strDebug = "";
		var cssRules;
		var objStyle;

		if (document.all) cssRules = "rules";
		else if (document.getElementById) cssRules = "cssRules";

		// alert(document.styleSheets.length);
		for (var i = 0; i < document.styleSheets.length; i++)
		{
			if (blnDebug) strDebug += "NUMBER OF STYLE SHEETS: "+document.styleSheets.length+"\n";

			try
			{
				for (var j = 0; j < document.styleSheets[i][cssRules].length; j++)
				{
					try
					{
						if (blnDebug) strDebug += document.styleSheets[i][cssRules][j].selectorText +": "+document.styleSheets[i][cssRules][j].style +"\n";

						// if (document.styleSheets[i][cssRules][j].selectorText.replace(".", "").replace("#", "") == strCssRuleName)
						if (document.styleSheets[i][cssRules][j].selectorText == strCssRuleName)
						{
							objStyle = document.styleSheets[i][cssRules][j].style;
						}
					}
					catch(err) { }
				}
			}
			catch(err) { }
		}
		if (blnDebug) alert(strDebug);
		return objStyle;
	}

	// All display items are within brackets {REPLACE_ME}
	function _UpdateDisplay(objTarget, hshData)
	{
		// alert(Dump(_SUMMARY, 3));
		// var strElemId = _GetFunctionName(arguments.callee.toString());
		if (!objTarget) return;

		if (hshData === undefined) hshData = _SUMMARY;

		for (var key in hshData)
		{
			var objTmp = document.getElementById(key);
			if (objTmp) objTmp["innerHTML"] = hshData[key];
		}
	}

	// Initialisation method
	function cydreShape(hshData)
	{
		var strElemId = _GetFunctionName(arguments.callee.toString());
		var objSource = document.getElementById(strElemId);
		if (!objSource)
		{
			alert("Unable to locate HTML element: '"+strElemId+"'");
			return;
		}

		var objTable = document.createElement("table");
		var objRow = document.createElement("tr");
		objTable.appendChild(objRow);
		var i = 0;

		for (var key in hshData)
		{
			// Initialization value
			if (_SUMMARY["CATE_ID"] == undefined)
			{
				_SUMMARY["CATE_ID"] = hshData[key]["CATE_ID"];
				_SUMMARY["CATE_NAME"] = hshData[key]["CATE_NAME"];
			}

			// Context popups
			var strContextData = undefined;
			var strContextKey = "context-"+hshData[key]["CATE_NAME"].toLowerCase();
			var objContextData = document.getElementById(strContextKey);
			if (objContextData) strContextData = objContextData["innerHTML"];

			// Colon separated values
			// THE_FUNCTION:THE_OBJECT:THE_PARAMETER_KEY:THE_PARAMETER_VALUE
			// Basically the arguments for _ServerRequest() method
			var strIdName = strElemId+"_"+i;
			var strAction = "cydreSettingThumbs:cydreSettingThumbs:CATE_ID:"+hshData[key]["CATE_ID"]+":CATE_NAME:"+hshData[key]["CATE_NAME"];
			var objTmp = _CreateButton(strIdName, hshData[key]["CATE_NAME"], strAction, strElemId+"Item", true, strContextData); // Basically return a div
			var objCell = document.createElement("td");
			objCell.appendChild(objTmp);
			objRow.appendChild(objCell);
			i++;
		}
		objSource.appendChild(objTable);

		// Initialization value
		if (_SUMMARY["CATE_ID"] != undefined)
		{
			// This remains static
			_GetRingSizeDropDown();

			// Trigger the thumb carousel
			_ServerRequest("cydreSettingThumbs", "cydreSettingThumbs", "CATE_ID", _SUMMARY["CATE_ID"]);

			// Switch on the first element
			ChangeCssClass(document.getElementById("cydreShape_0"), "cydreShapeItemOn");
		}
	}

	function cydreSettingThumbs(hshData)
	{
		// alert(Dump(hshData, 3));
		var strElemId = _GetFunctionName(arguments.callee.toString());
		var objSource = document.getElementById(strElemId);
		if (!objSource)
		{
			alert("Unable to locate HTML element: '"+strElemId+"'");
			return;
		}
		else if (_SUMMARY["CATE_ID"] == undefined) alert(strElemId+"() unable to locate CATE_ID");
		else
		{
			// Clear current contents
			objSource["innerHTML"] = "";
			objSource["style"]["left"] = 0;
		}

		// Reset as a new shape selected
		_SUMMARY["CPNO_PARENT_ID"] = undefined;

		var i = 0;
		for (var key in hshData)
		{
			// Target:
			// <div class="slide"><a href="#"><img src="/catalogue/422/squarethumbs/6223.01.jpg" style="margin-left:1px;" /></a></div>

			// Initialization value
			if (_SUMMARY["CPNO_PARENT_ID"] == undefined)
			{
				_SUMMARY["CPNO_PARENT_ID"] = hshData[key]["CPNO_ID"]; // This is an invented value ie not a real database field
				_SUMMARY["CPNO_PARENT_NAME"] = hshData[key]["CPNO_NAME"]; // This is an invented value ie not a real database field
			}

			// Image
			var objImg = document.createElement("img");
			objImg["src"] = "/catalogue/"+_SUMMARY["CATE_ID"]+"/squarethumbs/"+hshData[key]["CPNO_ID"]+".01.jpg";
			objImg.setAttribute("id", "crs"+i);
			objImg.setAttribute("title", hshData[key]["CPNO_NAME"].replace(/&quot;/gi, ""));

			// The button/anchor tag
			// 4 value colon separated values
			// THE_FUNCTION:THE_PARAMETER_KEY:THE_PARAMETER_VALUE
			var strAction = "cydreMediaCentre:cydreMediaCentre:CPNO_PARENT_ID:"+hshData[key]["CPNO_ID"];
			strAction += ":CPNO_PARENT_NAME:"+hshData[key]["CPNO_NAME"];
			var strIdName = strElemId+"_"+i;
			objImg.setAttribute("alt", strAction);
			var objTmp = _CreateButton(strIdName, objImg, strAction, strElemId+"Item", true);

			// Add to the main div
			objSource.appendChild(objTmp);

			// Count
			i++;
		}

		// Update the small panel above the display
		// Initialize display
		var intFinalItemOfPage =(i < _INT_ITEMS_PER_PAGE)?i:_INT_ITEMS_PER_PAGE;
		_UpdateCydreSettingThumbsDisplay(objSource, i, 1, intFinalItemOfPage)

		// Initialization value
		if (_SUMMARY["CPNO_PARENT_ID"] != undefined)
		{
			// Trigger next step
			_ServerRequest("cydreMediaCentre", "cydreMediaCentre", "CPNO_PARENT_ID", _SUMMARY["CPNO_PARENT_ID"]);
			// _ServerRequest("cydreMetal", "cydreMetal", "CPNO_ID", _SUMMARY["CPNO_ID"]);

			_INT_CURR_PAGE = 0; // Reset value on web page
			if (i <= _INT_ITEMS_PER_PAGE) // Set on web page
			{
				// Disable both controls as there's no more than what's seen
				DisableControls(); // Disable both left and right value on web page
			}
			else
			{
				ResetControls("right"); // Reset value on web page
				DisableControls("left"); // Disable value on web page
			}

			// Switch on the first element
			ChangeCssClass(document.getElementById("cydreSettingThumbs_0"), "cydreSettingThumbsItemOn");
		}
		else DisableControls();
	}

	function _RingDesignSearch(objBtn, strSearchFieldName)
	{
		// objBtn.blur();

		var objTmp = document.getElementById("searchResponse");
		if (objTmp) objTmp.parentNode.removeChild(objTmp);

		var blnFoundItem = false;
		var objSearchField = document.getElementById(strSearchFieldName);
		var strSearch = objSearchField["value"].toLowerCase();
		if (strSearch == "") return "";

		// Search pattern
		// var strPattern = "/"+strSearch+"/gi";

		// Find the thumbs
		var objSource = document.getElementById("cydreSettingThumbs");
		if (objSource)
		{
			var arrObjDiv = objSource.getElementsByTagName("div");
			if (arrObjDiv.length)
			{
				for(var i = 0; i < arrObjDiv.length; i++)
				{
					var arrObjImg = arrObjDiv[i].getElementsByTagName("img");
					if (arrObjImg[0]["title"].toLowerCase().indexOf(strSearch) != -1)
					{
						// alert(arrObjDiv[i]["onclick"]);
						var intDestinationPage = parseInt(i/_INT_ITEMS_PER_PAGE);
						// alert("Found item: "+i+"\n"+arrObjImg[0]["alt"]);
						// _INT_ITEMS_PER_PAGE
						// _INT_CURR_PAGE

						// Providing this isn't on the first page, we need to move
						if (_INT_CURR_PAGE != intDestinationPage)
						{
							if (intDestinationPage > _INT_CURR_PAGE)
							{
								var intDifference = intDestinationPage - _INT_CURR_PAGE;
								for(var j = 0; j < intDifference; j++)
								{
									ScrollRight(document.getElementById("cydreSettingThumbsMoveRightAnchor"));
								}
							}
							else
							{
								var intDifference = _INT_CURR_PAGE - intDestinationPage;
								for(var j = 0; j < intDifference; j++)
								{
									ScrollLeft(document.getElementById("cydreSettingThumbsMoveLeftAnchor"));
								}
							}
						}
						_OnClickExecute(arrObjDiv[i], arrObjImg[0]["alt"]);
						blnFoundItem = true;
						break;
					}
				}
			}
		}

		// Didn't find anything - provide a message
		if (!blnFoundItem)
		{
			var objTmp = document.createElement("div");
			objTmp.setAttribute("id", "searchResponse");
			objTmp["style"]["display"] = "table";
			objTmp["style"]["padding"] = "15px";
			objTmp["style"]["margin"] = "1px 0 0 0";
			objTmp["style"]["background"] = "#f5f5f5 url(/site/"+_SITE_VERSION+"/images/cydre/style-search-background.jpg) repeat-x 0 0";
			objTmp["style"]["border"] = "1px solid #399fc1";
			objTmp["style"]["position"] = "absolute";
			objTmp["style"]["color"] = "#399fc1";
			objTmp["style"]["zIndex"] = "99999";
			objTmp["innerHTML"] = "Sorry. Nothing found.";

			objSearchField.parentNode.appendChild(objTmp);
			setTimeout(_CloseSearchReport, 3000);
		}

		// alert("Searching for: "+strSearch+"\n"+"Number of items to search through: "+arrObjDiv.length+"\nComing soon ...");
		return false;
	}

	function _CloseSearchReport()
	{
		var objTmp = document.getElementById("searchResponse");
		if (objTmp) objTmp.parentNode.removeChild(objTmp);
	}

	function cydreMetal(hshData)
	{
		// alert(Dump(hshData, 3));
		// Initialise
		var strElemId = _GetFunctionName(arguments.callee.toString());
		var objSource = document.getElementById(strElemId);
		if (!objSource)
		{
			alert("Unable to locate HTML element: '"+strElemId+"'");
			return;
		}
		else if (_SUMMARY["CATE_ID"] == undefined) alert(strElemId+"() unable to locate CATE_ID");
		else if (_SUMMARY["CPNO_PARENT_ID"] == undefined) alert(strElemId+"() unable to locate CPNO_PARENT_ID");

		// Reset values
		objSource["innerHTML"] = "";
		_SUMMARY["CPNO_ID"] = undefined;

		// Prepare an array of the usable metals
		var arrActiveMetals = new Array();
		var x = 0;
		for (var key in hshData)
		{
			arrActiveMetals[x] = hshData[key]["METAL_TYPE"];
			x++
		}
		// alert(arrActiveMetals.length);

		var strItemIdInitialise = "";

		// Build the element
		var objTable = document.createElement("table");
		var objRow = document.createElement("tr");
		objTable.appendChild(objRow);

		for(var i = 0; i < _ARR_METALS.length; i++)
		{
			var strIdName = strElemId+"_"+i;
			var strAction = ""

			if (_InArray(_ARR_METALS[i], arrActiveMetals) || (_ARR_METALS[i] == "950 Platinum" && hshData[key]["METAL_TYPE"] == "Platinum"))
			{
				// Get other data about this metal type
				for (var key in hshData)
				{
					if (_ARR_METALS[i] == hshData[key]["METAL_TYPE"] || (_ARR_METALS[i] == "950 Platinum" && hshData[key]["METAL_TYPE"] == "Platinum"))
					{
						// Initialization value
						if (_SUMMARY["CPNO_ID"] == undefined)
						{
							strItemIdInitialise = strIdName;

							_SUMMARY["CPNO_ID"] = hshData[key]["CPNO_ID"];
							_SUMMARY["CPNO_NAME"] = hshData[key]["CPNO_NAME"];
							_SUMMARY["CPNO_DESCRIPTION"] = hshData[key]["CPNO_DESCRIPTION"];
							_SUMMARY["CPNO_PRICE"] = hshData[key]["CPNO_PRICE"];
							_SUMMARY["METAL_TYPE"] = hshData[key]["METAL_TYPE"];
							_SUMMARY["MOUNT_PRICE"] = hshData[key]["MOUNT_PRICE"];
						}

						// Available fields"CPNO_ID", "CPNO_PARENT_ID", "CPNO_NAME", "CPNO_DESCRIPTION", "CPNO_PRICE", "METAL_TYPE"
						strAction = "cydreMetalUpdateHandler:cydreMetalUpdateHandler:CPNO_ID:"+hshData[key]["CPNO_ID"];
						strAction += ":CPNO_NAME:"+hshData[key]["CPNO_NAME"];
						strAction += ":CPNO_DESCRIPTION:"+hshData[key]["CPNO_DESCRIPTION"];
						strAction += ":METAL_TYPE:"+hshData[key]["METAL_TYPE"];
						strAction += ":CPNO_PRICE:"+hshData[key]["CPNO_PRICE"];
						strAction += ":MOUNT_PRICE:"+hshData[key]["MOUNT_PRICE"];

						// Context popups
						var strContextData = undefined;
						var strContextKey = "context-"+_ARR_METALS_DISPLAY[i].toLowerCase().replace(" / ", "");
						var objContextData = document.getElementById(strContextKey);
						if (objContextData) strContextData = objContextData["innerHTML"];

						// Here the actual display text changes
						var objTmp = _CreateButton(strIdName, _ARR_METALS_DISPLAY[i], strAction, strElemId+"Item", true, strContextData); // returns a div
					}
				}
			}
			else
			{
				var objTmp = _CreateButton(strIdName, _ARR_METALS_DISPLAY[i], strAction, strElemId+"ItemGrey", false); // return a div
			}

			var objCell = document.createElement("td");
			objCell.appendChild(objTmp);
			objRow.appendChild(objCell);
		}

		objSource.appendChild(objTable);

		// Initialization value
		if (_SUMMARY["CPNO_ID"] != undefined)
		{
			// Diamond datagrid
			_STONE["startRow"] = "0";
			cydreDataGridUpdateHandler(_SELECTED_CARAT);

			// Trigger the summary update
			cydreSummary();

			// Switch on the first element
			ChangeCssClass(document.getElementById(strItemIdInitialise), "cydreMetalItemOn");

			// Get the Ring size permutations
			// _ServerRequest("cydreSize", "cydreSize", "CPNO_ID", _SUMMARY["CPNO_ID"]);
		}
	}

	function cydreMetalUpdateHandler()
	{
		_STONE["startRow"] = "0";
		cydreDataGridUpdateHandler();
		cydreSummary();
	}

	function _GetRingSizeDropDown()
	{
		var objDiv1 = document.getElementById("cydreSize");
		var objDiv2 = document.getElementById("RingSizeDropDown");
		if (objDiv1 && objDiv2)
		{
			objDiv1["innerHTML"] = objDiv2["innerHTML"];
		}

		// Default
		_SUMMARY["RING_SIZE_SELECTION"] = "Don't know";
	}

	function _UpdateRingSize(objRequest)
	{
		_SUMMARY["RING_SIZE_SELECTION"] = objRequest["value"];
		// _UpdateDisplay(document.getElementById("cydreSettingThumbsDisplay"));
		cydreSummary();
		return false;
	}

	function cydreColour()
	{
		var strElemId = _GetFunctionName(arguments.callee.toString());
		var objSource = document.getElementById(strElemId);
		if (!objSource)
		{
			alert("Unable to locate HTML element: '"+strElemId+"'");
			return;
		}

		for(var i = 0; i < _ARR_COLOUR.length; i++)
		{
			var strIdName = strElemId+"_"+i;
			var strAction = "cydreColour:cydreColour:colour:"+_ARR_COLOUR[i];
			var objTmp = _CreateButton(strIdName, _ARR_COLOUR[i], strAction, strElemId+"Item", true); // return a div
			if (i == _ARR_COLOUR.length - 1) objTmp["style"]["marginRight"] = "0";
			objSource.appendChild(objTmp);
		}

		// Initialize
		// _STONE["colour"] = arrColour;
		// _ClickOnCssHandler(objSource); // This adjusts the class on each item
	}

	function cydreColourUpdateHandler(strColour)
	{
		// Initialize colour array if this is the first use
		if (typeof(_STONE["colour"]) == "undefined") _STONE["colour"] = [];

		// Check to see whether this colour is already present
		// if (strColour in _STONE["colour"])
		if (InArray(strColour,  _STONE["colour"]))
		{
			// If it's already in the array and been clicked again this means "remove"
			var arrTmp = new Array();

			for(var i = 0; i < _STONE["colour"].length; i++)
			{
				if (_STONE["colour"][i] == strColour) continue;
				else arrTmp.push(_STONE["colour"][i]);
			}
			_STONE["colour"] = arrTmp
		}

		// Add it
		else _STONE["colour"].push(strColour);

		// Sort it
		_STONE["colour"].sort();
		_STONE["startRow"] = "0";
		cydreDataGridUpdateHandler();
		// alert(_STONE["colour"].join(", "));
	}

	function cydreClarity()
	{
		var strElemId = _GetFunctionName(arguments.callee.toString());
		var objSource = document.getElementById(strElemId);
		if (!objSource)
		{
			alert("Unable to locate HTML element: '"+strElemId+"'");
			return;
		}

		for(var i = 0; i < _ARR_CLARITY.length; i++)
		{
			var strIdName = strElemId+"_"+i;
			var strAction = "cydreClarity:cydreClarity:clarity:"+_ARR_CLARITY[i];
			var objTmp = _CreateButton(strIdName, _ARR_CLARITY[i], strAction, strElemId+"Item", true); // return a div
			if (i == _ARR_CLARITY.length - 1) objTmp["style"]["marginRight"] = "0";
			objSource.appendChild(objTmp);
		}

		// Initialize
		// _STONE["colour"] = arrColour;
		// _ClickOnCssHandler(objSource); // This adjusts the class on each item
	}

	function cydreClarityUpdateHandler(strClarity)
	{
		// Initialize colour array if this is the first use
		if (typeof(_STONE["clarity"]) == "undefined") _STONE["clarity"] = [];

		// Check to see whether this colour is already present
		// if (strClarity in _STONE["clarity"])
		if (InArray(strClarity,  _STONE["clarity"]))
		{
			// If it's already in the array and been clicked again this means "remove"
			var arrTmp = new Array();

			for(var i = 0; i < _STONE["clarity"].length; i++)
			{
				if (_STONE["clarity"][i] == strClarity) continue;
				else arrTmp.push(_STONE["clarity"][i]);
			}
			_STONE["clarity"] = arrTmp
		}

		// Add it
		else _STONE["clarity"].push(strClarity);

		// Sort it
		_STONE["clarity"].sort();
		_STONE["startRow"] = "0";
		cydreDataGridUpdateHandler();
		// alert(_STONE["colour"].join(", "));
	}

	function _UpdateCydreSettingThumbsDisplay(obj, intTotalItems, intStartItem, intEndItem)
	{
		// alert(Dump(_SUMMARY, 3));
		_SUMMARY["SHAPE_TOTAL_ITEMS"] = (intTotalItems == undefined)?"":intTotalItems;
		_SUMMARY["SHAPE_START_ITEM"] = (intStartItem == undefined)?"":intStartItem;
		_SUMMARY["SHAPE_END_ITEM"] = (intEndItem == undefined)?"":intEndItem;
		_UpdateDisplay(document.getElementById("cydreSettingThumbsDisplay"));
	}

	function cydreMediaCentre(hshData)
	{
		// alert(Dump(hshData, 3));
		var strElemId = _GetFunctionName(arguments.callee.toString());
		var objSource = document.getElementById(strElemId);
		if (!objSource)
		{
			alert("Unable to locate HTML element: '"+strElemId+"'");
			return;
		}
		else if (_SUMMARY["CATE_ID"] == undefined) alert(strElemId+"() unable to locate CATE_ID");
		else if (_SUMMARY["CPNO_PARENT_ID"] == undefined) alert(strElemId+"() unable to locate CPNO_PARENT_ID");

		// THE MEDIA CENTRE IN TOTALLITY
		var intRequiredFlashVersion = 8;
		var hshBtnText = new Object();
		hshBtnText["3dhand"] = "3D Hand";
		hshBtnText["video"] = "3D 360\u00B0"; // ° &deg; &#176;
		hshBtnText["flvVideo"] = "Video"; // Legacy video
		hshBtnText["magnify"] = "Magnify";
		hshBtnText["dimensions"] = "Ring Dims";
		hshBtnText["diamondDimensions"] = "Dia Dims";
		hshBtnText["sizeComparison"] = "Compare Size";
		hshBtnText["views"] = "Photos";
		hshBtnText["staticImage"] = "Photos";
		hshBtnText["packaging"] = "Box";
		hshBtnText["sample"] = "Sample";
		hshBtnText["description"] = "Description";
		var objMediaCentre = new ClassMediaCentre();
		objMediaCentre.SetPrimaryObjectName("cydreMediaCentre");
		objMediaCentre.SetRequiredFlashVersion(intRequiredFlashVersion);
		objMediaCentre.SetProduct(_SUMMARY["CATE_ID"], _SUMMARY["CPNO_PARENT_ID"], _SUMMARY["CPNO_PARENT_NAME"], hshBtnText);

		if (!_SHOWN_INIT_GRAPHIC)
		{
			_SHOWN_INIT_GRAPHIC = true;
			var objImg = document.createElement("img");
			objImg["src"] = _INIT_GRAPH;
			objImg.setAttribute("id", "___init_image");
			objImg.setAttribute("alt", "Create You Diamond Ring");
			objSource.appendChild(objImg);
			// objSource.insertBefore(objImg, objSource.firstChild);
		}

		else
		{
			// check that the graphic is removed
			var objTmp = document.getElementById("___init_image");
			if (objTmp) objTmp.parentNode.removeChild(objTmp);

			var objTmp1 = document.getElementById("rightContainer");
			var objTmp2 = document.getElementById("leftContainer");
			if (objTmp1) objTmp1["style"]["display"] = "block";
			if (objTmp2) objTmp2["style"]["display"] = "block";
		}
		_ServerRequest("cydreMetal", "cydreMetal", "CPNO_ID", _SUMMARY["CPNO_PARENT_ID"]);
	}

	// Selection Summary
	function cydreSummary()
	{
		// alert(Dump(_SUMMARY, 3));

		// Initialise
		var strElemId = _GetFunctionName(arguments.callee.toString());
		var objSource = document.getElementById(strElemId);
		if (!objSource)
		{
			alert("Unable to locate HTML element: '"+strElemId+"'");
			return;
		}

		if(!_SHOWN_INIT_GRAPHIC)
		{
			_SHOWN_INIT_GRAPHIC = true;
			return;
		}

		/*
        RING_SIZE_SELECTION
        CATE_ID
        CATE_NAME
        CPNO_PARENT_ID
        CPNO_PARENT_NAME
        CPNO_ID
        CPNO_NAME
        MOUNT_PRICE
        CPNO_DESCRIPTION
        CPNO_PRICE
        METAL_TYPE
        */

		// Part number image
		// imagePartNumber
		// /catalogue/422/thumbs/1781.01.jpg
		var objImg = document.getElementById("imagePartNumber");
		if (objImg)
		{
			if (_SUMMARY["CATE_ID"] !== undefined && _SUMMARY["CPNO_ID"] !== undefined)
			{
				objImg["src"] = "/catalogue/"+_SUMMARY["CATE_ID"]+"/squarethumbs/"+_SUMMARY["CPNO_ID"]+".01.jpg";
				objImg["alt"] = _SUMMARY["CPNO_NAME"].replace(/&quot;/gi, "");
				objImg["title"] = _SUMMARY["CPNO_NAME"].replace(/&quot;/gi, "");
			}
			else
			{
				objImg["src"] = "/site/"+_SITE_VERSION+"/images/image-unavailable.jpg";
				objImg["alt"] = "";
				objImg["title"] = "";
			}
		}

		var objTmp = document.getElementById("cydreSummaryProductName");
		if (objTmp)
		{
			if (_SUMMARY["CPNO_NAME"] !== undefined ) objTmp["innerHTML"] = _SUMMARY["CPNO_NAME"].replace(/&quot;/gi, "");
			else objTmp["innerHTML"] = "";
		}

		var objTmpStoneSummary = document.getElementById("cydreStoneSummaryBox");
		var objTmp = document.getElementById("cydreSummaryTotalPriceValue");
		var objTmpLabel = document.getElementById("cydreSummaryTotalPriceLabel");
		var objTmpBtn = document.getElementById("cydreSummaryBasketButton");

		if (objTmpStoneSummary && objTmp && objTmpLabel && objTmpBtn)
		{
			var arrImg = objTmpBtn.getElementsByTagName("img");

			if (_SUMMARY["total"] !== undefined && _SUMMARY["total"] != "")
			{
				// Stone summary

				// Clean out previous
				objTmpStoneSummary["innerHTML"] = "";

				// Build a data table
				var objTable = document.createElement("table");

				for (var key in _HSH_SUMMARY_SELECTED)
				{
					// objTmpStoneSummary["innerHTML"] += _HSH_SUMMARY_SELECTED[key]+":"+_SUMMARY[key]+"<br />";
					var objRow = document.createElement("tr");
					// if (key == "cert") objRow.setAttribute("id", );

					var objCell_1 = document.createElement("td");
					objCell_1["innerHTML"] = _HSH_SUMMARY_SELECTED[key];
					objCell_1.setAttribute("class", "cellTitle"); // For Most Browsers
					objCell_1.setAttribute("className", "cellTitle"); // For IE; harmless to other browsers
					objRow.appendChild(objCell_1);

					var objCell_2 = document.createElement("td");
					objCell_2["innerHTML"] = _SUMMARY[key].replace(/&quot;/gi, "");
					objCell_2.setAttribute("class", "cellValue"); // For Most Browsers
					objCell_2.setAttribute("className", "cellValue"); // For IE; harmless to other browsers
					// alert(key +":"+_SUMMARY[key]+":"+_SUMMARY["certificate_image"]);

					if (key == "cert" && _SUMMARY[key] != "" && _SUMMARY["certificate_image"] != "")
					{
						var objImg = document.createElement("img");
						objImg.setAttribute("src", _STR_IMG_PATH_CERT);
						objImg.setAttribute("class", "datagridCert"); // For Most Browsers
						objImg.setAttribute("className", "datagridCert"); // For IE; harmless to other browsers
						objImg.setAttribute("alt", "Certificate available");
						objImg["style"]["position"] = "relative";
						objImg["style"]["marginRight"] = "2px";
						objCell_2.insertBefore(objImg, objCell_2.firstChild);
						// objCell_2.appendChild(objImg);

						try // IE
						{
							objCell_2.onclick = function() { return _ShowCert(_SUMMARY['ref']) };
						}
						catch (err)
						{
							objCell_2.setAttribute("onclick", "return _ShowCert(_SUMMARY['ref']);");
						}
						objCell_2["style"]["cursor"] = "pointer";
					}

					objRow.appendChild(objCell_2);

					objTable.appendChild(objRow);
				}
				objTmpStoneSummary.appendChild(objTable);

				// Prices/Button area
				// _STR_ORDER_NOW_BTN_PATH _STR_ORDER_NOW_BTN_PATH_OVER
				objTmp["innerHTML"] = _SUMMARY["total"];
				objTmpLabel["innerHTML"] = "Total Package Price (incl VAT)";
				arrImg[0]["src"] = _STR_ORDER_NOW_BTN_PATH;
				arrImg[0]["style"]["cursor"] = "pointer";

				// Basket URL
				// Base64Encode()
				/*
					shopping-cart.html?
						prod_id=NTg2Mg%3D%3D&
						ex5h=MTgwLjAw&
						stoneId=MTM1MzIw&
						ringSize=QSZmcmFjMTI7&
						rt2p=wqM1MjguOTk%3D&
						cyo=1
				*/
				var strBasketUrl = "/basket.html?cyo=2"
				+"&prod_id="+parseInt(_SUMMARY["CPNO_ID"])
				+"&ex5h="+parseFloat(_SUMMARY["MOUNT_PRICE"])
				+"&stoneId="+parseInt(_SUMMARY["ref"])
				+"&ringSize="+escape(_SUMMARY["RING_SIZE_SELECTION"])
				+"&rt2p="+_SUMMARY["total"].replace("&pound;", "");

				// Action
				try // IE
				{
					arrImg[0].onmouseover = function() { return _OnMouseOver(this, _STR_ORDER_NOW_BTN_PATH_OVER) };
					arrImg[0].onmouseout = function() { return _OnMouseOut(this, _STR_ORDER_NOW_BTN_PATH) };
					arrImg[0].onclick = function() { window.location = strBasketUrl; };
				}
				catch (err)
				{
					arrImg[0].setAttribute("onmouseover", "return _OnMouseOver(this, _STR_ORDER_NOW_BTN_PATH_OVER);");
					arrImg[0].setAttribute("onmouseout", "return _OnMouseOut(this, _STR_ORDER_NOW_BTN_PATH);");
					arrImg[0].setAttribute("onclick", "window.location = strBasketUrl;");
				}
			}
			else
			{
				objTmp["innerHTML"] = "";
				objTmpLabel["innerHTML"] = "";
				objTmpStoneSummary["innerHTML"] = "";
				arrImg[0]["src"] = "/images/spacer.gif";
				arrImg[0]["style"]["cursor"] = "default";
			}
		}
	}

	// Stone summary
	function cydreDataGridUpdateHandler(hshData)
	{
		// alert(Dump(hshData, 3));

		// Empty the selected diamond data
		for(var i = 0; i < _ARR_DG_FIELDS.length; i++)
		{
			var strField = _ARR_DG_FIELDS[i];
			_SUMMARY[strField] = "";
		}
		cydreSummary();

		// Update the selection
		if (typeof(hshData) !== undefined)
		{
			for (var key in hshData)
			{
				// Reset the pagination start row if the carat criteria has been changed
				if (key == "min" && _STONE[key] != hshData[key]) _STONE["startRow"] = "0";
				else if (key == "max" && _STONE[key] != hshData[key]) _STONE["startRow"] = "0";

				_STONE[key] = hshData[key];
			}
		}

		// Build cydreDataGrid server request
		// These are all the DEFAULTS
		if (_SUMMARY["CATE_NAME"] === undefined) _SUMMARY["CATE_NAME"] = "Round";
		if (_STONE["startRow"] === undefined) _STONE["startRow"] = "0";
		if (_STONE["displayNumber"] === undefined) _STONE["displayNumber"] = "10";
		if (_STONE["sortField"] === undefined) _STONE["sortField"] = "stn_total";
		if (_STONE["sortFieldDirection"] === undefined) _STONE["sortFieldDirection"] = "asc";
		// alert(_STONE["startRow"]);

		_ServerRequest
		(
			"cydreDataGrid", "cydreDataGrid",
			"caratMin", _STONE["min"],
			"caratMax", _STONE["max"],
			"colour", _STONE["colour"].join(","),
			"clarity", _STONE["clarity"].join(","),
			"shape", _SUMMARY["CATE_NAME"],
			"mountPrice", _SUMMARY["MOUNT_PRICE"],
			"startRow", _STONE["startRow"],
			"displayNumber", _STONE["displayNumber"],
			"totalDiamondCount", _TOTAL_DIAMOND_COUNT,
			"sortField", _STONE["sortField"],
			"sortFieldDirection", _STONE["sortFieldDirection"],
			"client", "www.dejoria.co.uk"
		);
		return false;
	}

	// Stone summary
	function cydreDataGrid(hshData)
	{
		// alert(Dump(hshData, 3));
		var strElemId = _GetFunctionName(arguments.callee.toString());
		var objSource = document.getElementById(strElemId);
		if (!objSource)
		{
			alert("Unable to locate HTML element: '"+strElemId+"'");
			return;
		}

		// objSource["innerHTML"] = "<pre>Result:\n"+Dump(hshData, 3)+"\n</pre>";

		// Clear previous table
		objSource["innerHTML"] = "";

		// Search status
		objSource.appendChild(_SetSearchStatus(_STONE["searchRowCount"]));

		if (_STONE["searchRowCount"] == 0)
		{
			var objDiv = document.createElement("div");
			objDiv["innerHTML"] = document.getElementById("noStones").innerHTML;
			objSource.appendChild(objDiv);
		}

		else
		{
			/*
			   'ref' => "138327"
				'shape' => "round"
				'carat' => "0.310000"
				'colour' => "J"
				'clarity' => "SI2"
				'cert' => "EGL"
				'total' => "£217.73"
				'symmetry' => "Very Good"
				'polish' => "Very Good"
				'cut_grade' => "10"
				'depth' => "61.100000"
				'table' => "60.000000"
				'fluorescence' => "Faint"
				'girdle' => ""
				'culet' => ""
				'measurements' => "4.38x4.34x2.66"
			*/

			// Field heading row
			var objDiv = document.createElement("div");
			objDiv.setAttribute("id", "dataGridHeadings");
			var objTable = document.createElement("table");
			var objRow = document.createElement("tr");
			for(var i = 0; i < _ARR_DG_FIELDS.length; i++)
			{
				// Don't display the image path
				if (_ARR_DG_FIELDS[i] == "certificate_image") continue;

				var objCell = document.createElement("th");
				if (_ARR_DG_FIELD_WIDTHS[i] != "" && _ARR_DG_FIELD_WIDTHS[i] !== undefined) objCell["style"]["width"] = _ARR_DG_FIELD_WIDTHS[i]+"px";
				objCell["innerHTML"] = UppercaseFirst(_ARR_DG_FIELDS[i]); // .toUpperCase();

				try // IE
				{
					objCell.onclick = function() { return objCYDRE.SortField(this['innerHTML']) };
				}
				catch (err)
				{
					objCell.setAttribute("onclick", "return objCYDRE.SortField(this['innerHTML']);");
				}

				if (_STONE["sortField"].toLowerCase() == _ARR_DG_FIELDS[i].toLowerCase())
				{
					var strImg = "";
					if (_STONE["sortFieldDirection"] == "desc") strImg = _STR_IMG_PATH_SORT_DESC;
					else strImg = _STR_IMG_PATH_SORT_ASC;
					objCell["style"]["background"] = "#fff url("+strImg+") no-repeat center top";
				}

				objRow.appendChild(objCell);
			}
			objTable.appendChild(objRow);
			objDiv.appendChild(objTable);
			objSource.appendChild(objDiv);

			// Prepare datagrid container for style
			var objDiv = document.createElement("div");
			objDiv.setAttribute("id", "dataGrid");
			var objTable = document.createElement("table");
			objTable.setAttribute("id", "mainDataTable");

			// Data rows
			for (var strKey in hshData)
			{
				var objRow = document.createElement("tr");
				var strRef = hshData[strKey]["ref"];
				objRow.setAttribute("id", strRef);

				// alert(Dump(hshData[strKey], 3)); // For debug
				// Data cells
				for(var j = 0; j < _ARR_DG_FIELDS.length; j++)
				{
					// Don't display the image path
					if (_ARR_DG_FIELDS[j] == "certificate_image") continue;

					var objCell = document.createElement("td");
					if (_ARR_DG_FIELD_WIDTHS[j] != "" && _ARR_DG_FIELD_WIDTHS[j] !== undefined) objCell["style"]["width"] = _ARR_DG_FIELD_WIDTHS[j]+"px";
					var strField = _ARR_DG_FIELDS[j];
					objCell["innerHTML"] = hshData[strKey][strField];

					try // IE
					{
						objCell.onmouseover = function() { _OnRowOver(this) };
						objCell.onmouseout = function() { _OnRowOut(this) };
						// objCell.onclick = function() { return _RowSelect(this) };
					}
					catch (err)
					{
						objCell.setAttribute("onmouseover", "_OnRowOver(this);");
						objCell.setAttribute("onmouseout", "_OnRowOut(this);");
						// objCell.setAttribute("onclick", "return _RowSelect(this);");
					}

					switch(strField)
					{
						// Change the onlick event for the certificate
						case "cert":
							if (hshData[strKey]["certificate_image"] != "")
							{
								// objCell["style"]["textDecoration"] = "underline";
								var strCert = hshData[strKey]["certificate_image"];

								try // IE
								{
									objCell.onclick = function() { return _ShowCert(this) };
								}
								catch (err)
								{
									objCell.setAttribute("onclick", "return _ShowCert(this);");
								}

								// Add the cert graphic
								var objImg = document.createElement("img");
								objImg.setAttribute("src", _STR_IMG_PATH_CERT);
								objImg.setAttribute("class", "datagridCert"); // For Most Browsers
								objImg.setAttribute("className", "datagridCert"); // For IE; harmless to other browsers
								objImg.setAttribute("alt", "Certificate available");
								// objCell.appendChild(objImg);
								objCell.insertBefore(objImg, objCell.firstChild);
							}
							break;

						/*
						case "total":

							objCell.setAttribute("class", "boxSelectRow "); // For Most Browsers
							objCell.setAttribute("className", "boxSelectRow "); // For IE; harmless to other browsers
							break;
						*/

						default:

							try // IE
							{
								objCell.onclick = function() { return _RowSelect(this) };
							}
							catch (err)
							{
								objCell.setAttribute("onclick", "return _RowSelect(this);");
							}

					} // End switch

					objRow.appendChild(objCell);
				}
				objTable.appendChild(objRow);
			}

			// Add the datagrid
			objDiv.appendChild(objTable);
			objSource.appendChild(objDiv);

			// "Number of records" selector
			var objTmp = document.createElement("div");
			objTmp.setAttribute("id", "numRecordsSelector");
			objTmp.setAttribute("class", "RecordNumberSelector "); // For Most Browsers
			objTmp.setAttribute("className", "RecordNumberSelector "); // For IE; harmless to other browsers

			var objOption = document.createElement("select");

			// Action
			try // IE
			{
				objOption.onchange = function() { return objCYDRE.SetNumberRecordsDisplayed(this) };
			}
			catch (err)
			{
				objOption.setAttribute("onchange", "return objCYDRE.SetNumberRecordsDisplayed(this);");
			}

			for(var i = 0; i < _ARR_DG_DISPLAY_NUMBER.length; i++)
			{
				var objItem = document.createElement("option");
				objItem.setAttribute("value", _ARR_DG_DISPLAY_NUMBER[i]);
				objItem["innerHTML"] = _ARR_DG_DISPLAY_NUMBER[i];
				if (parseInt(_STONE["displayNumber"]) == parseInt(_ARR_DG_DISPLAY_NUMBER[i])) objItem.setAttribute("selected", "selected");
				objOption.appendChild(objItem);
			}
			objTmp.appendChild(objOption);
			objSource.appendChild(objTmp);

			// Pagination
			objSource.appendChild(_SetPagination(_STONE["searchRowCount"], _STONE["displayNumber"], _STONE["startRow"]));
		}
	}

	function _ShowCert(objCallee)
	{
		var strObjCalleeId = null;
		if (typeof objCallee == 'string') strObjCalleeId = objCallee; // String from summary window
		else strObjCalleeId = objCallee.parentNode["id"];

		for (var strKey in _CURR_DATAGRID_DATA)
		{
			if (parseInt(_CURR_DATAGRID_DATA[strKey]["ref"]) === parseInt(strObjCalleeId))
			{
				window.open(_CURR_DATAGRID_DATA[strKey]["certificate_image"], "cert_01", "toolbar=no, directories=no, status=no, menubar=no, location=yes");
				break;
			}
		}
		return false;
	}

	function _OnRowOver(objCallee)
	{
		// alert(objCallee.parentNode.id);
		var strObjCalleeId = objCallee.parentNode["id"];

		var objDiv = document.getElementById(_BOX_NAME); // Outer container
		var objContent = document.getElementById("innerContainer");

		if (!objDiv)
		{
			alert("Unable to locate id '"+_BOX_NAME+"'");
			return;
		}
		objDiv["style"]["display"] = "block";

		// Update box
		for (var strKey in _CURR_DATAGRID_DATA)
		{
			if (parseInt(_CURR_DATAGRID_DATA[strKey]["ref"]) === parseInt(strObjCalleeId))
			{
				_UpdateDisplay(objContent, _CURR_DATAGRID_DATA[strKey]);
				break;
			}
		}

		// Set the arrow
		var arrTD = objCallee.parentNode.getElementsByTagName("TD");
		if (arrTD)
		{
			// Adjust the arrow on the last cell and create the popup
			var objLastTD = arrTD[arrTD.length-1];
			if (objLastTD)
			{
				/*
				objLastTD.setAttribute("class", ""); // For Most Browsers
				objLastTD.setAttribute("className", ""); // For IE; harmless to other browsers
				*/

				var objTmp = document.createElement("div");
				objTmp.setAttribute("class", "boxArrow"); // For Most Browsers
				objTmp.setAttribute("className", "boxArrow"); // For IE; harmless to other browsers
				objTmp.setAttribute("id", "boxArrowActive");
				objLastTD.appendChild(objTmp);
			}
		}

		// Open box
		objDiv["style"]["display"] = "block";
	}

	function _RowSelect(objCallee)
	{
		var strObjCalleeId = objCallee.parentNode["id"];
		// alert(objCallee.parentNode["id"]);

		// check that the init graphic is removed
		var objTmp = document.getElementById("___init_image");
		if (objTmp)
		{
			objTmp.parentNode.removeChild(objTmp);

			var objTmp1 = document.getElementById("rightContainer");
			var objTmp2 = document.getElementById("leftContainer");
			if (objTmp1) objTmp1["style"]["display"] = "block";
			if (objTmp2) objTmp2["style"]["display"] = "block";
		}

		// Check to see whether this row is already selected ... if so deselect it
		// Empty the selected diamond data
		if (_SUMMARY["ref"] == strObjCalleeId)
		{

			for(var i = 0; i < _ARR_DG_FIELDS.length; i++)
			{
				var strField = _ARR_DG_FIELDS[i];
				_SUMMARY[strField] = "";
			}
			cydreSummary();

			// Display
			var objRow = objCallee.parentNode;
			var objTbl = objRow.parentNode;

			// First clear any previous selects
			var arrRow = objTbl.getElementsByTagName("tr");
			if (arrRow)
			{
				for(var i = 0; i < arrRow.length; i++)
				{
					arrRow[i].setAttribute("class", ""); // For Most Browsers
					arrRow[i].setAttribute("className", ""); // For IE; harmless to other browsers
				}
			}
			return;
		}

		// Get the data
		for (var strKey in _CURR_DATAGRID_DATA)
		{
			if (parseInt(_CURR_DATAGRID_DATA[strKey]["ref"]) === parseInt(strObjCalleeId))
			{
				// This data is now added to the summary
				for(var i = 0; i < _ARR_DG_FIELDS.length; i++)
				{
					var strField = _ARR_DG_FIELDS[i];
					_SUMMARY[strField] = _CURR_DATAGRID_DATA[strKey][strField];
				}
				cydreSummary();
				break;
			}
		}

		// Display
		var objRow = objCallee.parentNode;
		var objTbl = objRow.parentNode;

		// First clear any previous selects
		var arrRow = objTbl.getElementsByTagName("tr");
		if (arrRow)
		{
			for(var i = 0; i < arrRow.length; i++)
			{
				arrRow[i].setAttribute("class", ""); // For Most Browsers
				arrRow[i].setAttribute("className", ""); // For IE; harmless to other browsers
			}
		}

		// Next set the selected row
		objRow.setAttribute("class", "selectedRow"); // For Most Browsers
		objRow.setAttribute("className", "selectedRow"); // For IE; harmless to other browsers

		// Re-add the dormant arrow
		/*
		var arrTD = objRow.getElementsByTagName("td");
		if (arrTD)
		{
			// Adjust the arrow on the last cell and create the popup
			var objLastTD = arrTD[arrTD.length-1];
			objLastTD.setAttribute("class", "boxDeSelectRow"); // For Most Browsers
			objLastTD.setAttribute("className", "boxDeSelectRow"); // For IE; harmless to other browsers
		}
		*/

		// This class can't set the border top ... therefore try to set each td border top
		/*
		var arrCell = objRow.getElementsByTagName("td");
		for(var i = 0; i < arrCell.length; i++)
		{
			arrCell[i]["style"]["borderTop"] = "2px solid #399fc1";
		}
		*/
		return false;
	}

	function _ShowPage(strPageUrl)
	{
		if (strPageUrl == "") return false;

		_ObjectLoading("content");

		var objTarget = document.getElementById("content");
		var intVerticalMargin = 50;
		var intHorizontalMargin = 100;
		var intWidth = objTarget["offsetWidth"] - (intHorizontalMargin*2);
		var intHeight = objTarget["offsetHeight"] - (intVerticalMargin*2);
		var intTopMarginHeight = 20;

		// Create a platform over the cover
		var objTmp = document.createElement("div");
		objTmp.setAttribute("id", "pagePlatform");
		// objTmp["style"]["background"] = "#888";
		objTmp["style"]["display"] = "block";
		objTmp["style"]["position"] = "absolute";
		objTmp["style"]["overflow"] = "hidden";
		objTmp["style"]["width"] = intWidth+"px";
		objTmp["style"]["height"] = intHeight+intTopMarginHeight+"px";
		objTmp["style"]["zIndex"] = _INT_LOADING_BASE_ZINDEX+2;
		objTmp["style"]["margin"] = intVerticalMargin+"px "+intHorizontalMargin+"px";
		objTmp["style"]["borderRight"] = "1px solid #888";
		objTmp["style"]["borderBottom"] = "1px solid #999";
		objTmp["style"]["borderLeft"] = "1px solid #ccc";

		// Close button
		var objImg = document.createElement("img");
		objImg["src"] = _STR_IMG_PATH_CLOSE_BTN;
		objImg.setAttribute("id", "btnClose0001");

		// Action
		try // IE
		{
			objImg.onmouseover = function() { _OnMouseOver(this, _STR_IMG_PATH_CLOSE_BTN_OVER) };
			objImg.onmouseout = function() { _OnMouseOut(this, _STR_IMG_PATH_CLOSE_BTN) };
			objImg.onclick = function() { return _ClosePage(this) };
		}
		catch (err)
		{
			objImg.setAttribute("onmouseover", "_OnMouseOver(this, _STR_IMG_PATH_CLOSE_BTN_OVER);");
			objImg.setAttribute("onmouseout", "_OnMouseOut(this, _STR_IMG_PATH_CLOSE_BTN);");
			objImg.setAttribute("onclick", "return _ClosePage(this);");
		}

		// Top margin
		var objTmp2 = document.createElement("div");
		objTmp2["style"]["display"] = "block";
		objTmp2["style"]["overflow"] = "hidden";
		objTmp2["style"]["width"] = intWidth+"px";
		objTmp2["style"]["height"] = intTopMarginHeight+"px";
		objTmp2["style"]["background"] = "url('"+_STR_IMG_PATH_CLOSE_BTN_TOP_MARGIN+"')";
		objTmp2["style"]["margin"] = "0";
		objTmp2["style"]["padding"] = "0";
		objTmp2.appendChild(objImg);
		objTmp.appendChild(objTmp2);

		// Create iframe
		var objIfr = document.createElement("iframe");
		objIfr.setAttribute("name", "iframe00001");
		objIfr.setAttribute("src", strPageUrl);
		objIfr.setAttribute("scrolling", "auto");
		objIfr.setAttribute("frameborder", "0");
		objIfr["style"]["width"] = intWidth+"px";
		objIfr["style"]["height"] = intHeight+"px";
		objIfr["style"]["zIndex"] = _INT_LOADING_BASE_ZINDEX+3;
		objTmp.appendChild(objIfr);

		objTarget.insertBefore(objTmp, objTarget.firstChild);

		return false;
	}

	function _ClosePage(objImg)
	{
		var objDiv = document.getElementById("pagePlatform");
		if (objDiv) objDiv.parentNode.removeChild(objDiv);
		_ObjectLoading("content");
		return false;
	}

	function _OnMouseOver(objImg, strImgPath)
	{
		// if (objImg) objImg["src"] = _STR_IMG_PATH_CLOSE_BTN_OVER;
		if (objImg) objImg["src"] = strImgPath;
		return false;
	}

	function _OnMouseOut(objImg, strImgPath)
	{
		// if (objImg) objImg["src"] = _STR_IMG_PATH_CLOSE_BTN;
		if (objImg) objImg["src"] = strImgPath;
		return false;
	}

	function _OnRowOut(objCallee)
	{
		// _BOX_OPEN
		var objDiv = document.getElementById(_BOX_NAME);
		if (!objDiv) return;
		objDiv["style"]["display"] = "none";

		// Remove arrow
		var objDiv = document.getElementById("boxArrowActive");
		if (objDiv) objDiv.parentNode.removeChild(objDiv);

		// Re-add the dormant arrow
		var arrTD = objCallee.parentNode.getElementsByTagName("TD");
		if (arrTD)
		{
			// Adjust the arrow on the last cell and create the popup
			/*
			var objLastTD = arrTD[arrTD.length-1];
			objLastTD.setAttribute("class", "boxArrowDormant"); // For Most Browsers
			objLastTD.setAttribute("className", "boxArrowDormant"); // For IE; harmless to other browsers
			*/
		}
	}

	function _SetSearchStatus(intSearchTotal)
	{
		var objTmp = document.createElement("div");
		objTmp.setAttribute("id", "searchStatus");
		objTmp["innerHTML"] = "Your search criteria found: <span>"+NumberAddCommas(intSearchTotal)+"</span> diamonds";
		return objTmp;
	}

	function _SortField(strField) // Datagrid
	{
		strField = strField.toLowerCase();

		if (!InArray(strField, _ARR_DG_FIELDS))
		{
			alert("Sorry. Sort field not recognised.");
		}
		else
		{
			if (_STONE["sortField"].toLowerCase() == strField)
			{
				if (_STONE["sortFieldDirection"] == "asc") _STONE["sortFieldDirection"] = "desc";
				else _STONE["sortFieldDirection"] = "asc";
			}
			else
			{
				_STONE["sortField"] = strField;
				_STONE["sortFieldDirection"] = "asc";
			}

			_STONE["startRow"] = "0";
			cydreDataGridUpdateHandler();
		}
		return false;
	}

	function _SetNumberRecordsDisplayed(selObj)
	{
		// alert("hi - "+selObj.options[selObj.selectedIndex]["value"]);
		if (selObj.options[selObj.selectedIndex]["value"] !== undefined)
		{
			_STONE["displayNumber"] = selObj.options[selObj.selectedIndex]["value"];
			_STONE["startRow"] = 0;
			cydreDataGridUpdateHandler();
		}
		return false;
	}

	function _SetPagination(intSearchRowCount, intDisplayNumber, intStartRow)
	{
		var _PAGINATION_GROUP_MAX = 10;

		// Convert to integers
		var objTmpBtn = null;
		intSearchRowCount = parseInt(intSearchRowCount);
		intDisplayNumber = parseInt(intDisplayNumber);
		intStartRow = parseInt(intStartRow);

		// Create the container
		var objTmp1 = document.createElement("div");
		objTmp1.setAttribute("id", "pagination");

		// Total pages
		var intTotalPages = Math.floor(intSearchRowCount/intDisplayNumber);
		var intRemainder = intSearchRowCount % intDisplayNumber;
		if (intRemainder > 0) intTotalPages++;

		if (intTotalPages <= 1) return objTmp1;

		// Current page
		// Always display up to 10 available pages
		var intCurrentPage = Math.floor(intStartRow/intDisplayNumber);
		var intStartPageGroup = 0;

		intStartPageGroup = intCurrentPage;
		var intStartRemainder = intStartPageGroup % 10;
		intStartPageGroup -= intStartRemainder;

		// Debug
		// alert ("Pagination...\nintSearchRowCount: "+ intSearchRowCount+"\nintDisplayNumber: "+intDisplayNumber+"\nintStartRow: "+intStartRow+"\nintTotalPages: "+intTotalPages+"\nintRemainder: "+intRemainder+"\nintCurrentPage: "+intCurrentPage+"\nintStartPageGroup:"+intStartPageGroup);

		var intEndPageGroup = intStartPageGroup + _PAGINATION_GROUP_MAX;
		if (intEndPageGroup > intTotalPages) intEndPageGroup = intTotalPages;

		// Go back to previous page group
		if (intStartPageGroup >= _PAGINATION_GROUP_MAX)
		{
			var intActionStartRow = parseInt((intStartPageGroup * intDisplayNumber) - intDisplayNumber);
			if (intActionStartRow < 0) intActionStartRow = 0;
			// alert("intActionStartRow: "+intActionStartRow+"\nintStartPageGroup: "+intStartPageGroup);
			var strIdName = "pagination_a";
			var strObjBtnTitle = "<<";
			var strAction = "cydreDataGridUpdateHandler:cydreDataGridUpdateHandler:startRow:"+String(intActionStartRow);
			var strClassName = "paginationItem";
			var blnEnableAction	= true;
			var objBtn = _CreateButton(strIdName, strObjBtnTitle, strAction, strClassName, blnEnableAction);

			// Slightly different appearance
			objBtn.setAttribute("class", "paginationItemForwardBackward"); // For Most Browsers
			objBtn.setAttribute("className", "paginationItemForwardBackward"); // For IE; harmless to other browsers

			objTmp1.appendChild(objBtn);
		}
		else
		{
			var objTmp = document.createElement("span");
			objTmp["innerHTML"] = "&nbsp;";
			objTmp1.appendChild(objTmp);
		}

		for(i = intStartPageGroup; i < intEndPageGroup; i++)
		{
			var intActionStartRow = parseInt(i*intDisplayNumber);
			var strIdName = "pagination_"+i;
			var strObjBtnTitle = String(i + 1);
			var strAction = "cydreDataGridUpdateHandler:cydreDataGridUpdateHandler:startRow:"+String(intActionStartRow);
			var strClassName = "paginationItem";
			var blnEnableAction	= true;
			var objBtn = _CreateButton(strIdName, strObjBtnTitle, strAction, strClassName, blnEnableAction);
			// Switch on the current page
			if (i == intCurrentPage)
			{
				objBtn.setAttribute("class", strClassName+"On"); // For Most Browsers
				objBtn.setAttribute("className", strClassName+"On"); // For IE; harmless to other browsers
			}
			objTmp1.appendChild(objBtn);
		}

		// Go forward to next page group
		if (intTotalPages > _PAGINATION_GROUP_MAX)
		{
			var intActionStartRow = (intStartPageGroup * intDisplayNumber) + (_PAGINATION_GROUP_MAX * intDisplayNumber);
			var strIdName = "pagination_z";
			var strObjBtnTitle = ">>";
			var strAction = "cydreDataGridUpdateHandler:cydreDataGridUpdateHandler:startRow:"+String(intActionStartRow);
			var strClassName = "paginationItem";
			var blnEnableAction	= true;
			var objBtn = _CreateButton(strIdName, strObjBtnTitle, strAction, strClassName, blnEnableAction);

			// Slightly different appearance
			objBtn.setAttribute("class", "paginationItemForwardBackward"); // For Most Browsers
			objBtn.setAttribute("className", "paginationItemForwardBackward"); // For IE; harmless to other browsers
			objTmp1.appendChild(objBtn);
		}
		else
		{
			var objTmp = document.createElement("span");
			objTmp["innerHTML"] = "&nbsp;";
			objTmp1.appendChild(objTmp);
		}

		return objTmp1;
	}

























	//
	// UNTILITY METHODS BELOW THIS POINT
	//
	function _GetFunctionName(str)
	{
		var strRtnName = ""
		if (str == "") return strRtnName;

		var strRtnName = str.substr('function '.length);
		strRtnName = strRtnName.substr(0, strRtnName.indexOf('('));
		return strRtnName;
	}

	function _InArray(strSource, arrTarget)
	{
		if (strSource == "") return false;
		else if (arrTarget.length == 0) return false;

		for (var i = 0; i < arrTarget.length; i++)
		{
			if (arrTarget[i] == undefined) continue;
			else if (arrTarget[i] == strSource) return true;
		}
		return false;
	}

	function _ObjectLoading(strObjectName)
	{
		// _INT_LOADING_BASE_ZINDEX = 100;
		// _STR_COVER_BGCOLOUR = "#345";
		// _INT_COVER_OPACITY = 50;

		// This is an exception because it's mostly hidden
		if (strObjectName == "cydreSettingThumbs") strObjectName = "cydreSettingThumbsGroup";
		if (strObjectName == "cydreMediaCentre") strObjectName = "cydreSetting";

		// Find the object in question
		var objTarget = document.getElementById(strObjectName);

		if (!objTarget)
		{
			alert("Unable to locate request object: '"+strObjectName+"'");
			return;
		}

		var intWidth = objTarget["offsetWidth"];
		var intHeight = objTarget["offsetHeight"];

		// CHECK WHETHER THE COVER EXISTS ALREADY
		var strLoadingCoverName = "LOADING_COVER_"+strObjectName;
		var objCover = document.getElementById(strLoadingCoverName);

		// If it does exist - remove it
		if (objCover)
		{
			// objTarget.removeChild(objCover);
			objCover.parentNode.removeChild(objCover);
			return;
		}

		var objCover = document.createElement("div");
		objCover.setAttribute("id", strLoadingCoverName);
		objCover["style"]["position"] = "absolute";
		objCover["style"]["display"] = "block";
		objCover["style"]["float"] = "left";

		objCover["style"]["width"] = intWidth+"px";
		objCover["style"]["height"] = intHeight+"px";
		objCover["style"]["background"] = _STR_COVER_BGCOLOUR;
		objCover["style"]["zIndex"] = _INT_LOADING_BASE_ZINDEX;

		if (_INT_COVER_OPACITY != 100)
		{
			objCover["style"]["filter"] = "alpha(opacity="+_INT_COVER_OPACITY+") Shadow(Color="+_STR_COVER_BGCOLOUR+", Direction=225)";
			objCover["style"]["-moz-opacity"] = "."+_INT_COVER_OPACITY;
			objCover["style"]["opacity"] = "."+_INT_COVER_OPACITY;
			objCover["style"]["-khtml-opacity"] = "0."+_INT_COVER_OPACITY;
		}

		// Create a platform over the cover
		var objTmp = document.createElement("div");
		objTmp["style"]["background"] = _STR_COVER_BGCOLOUR;
		objTmp["style"]["display"] = "block";
		objTmp["style"]["width"] = _INT_LOADER_GRAPHIC_WIDTH+"px";
		objTmp["style"]["zIndex"] = _INT_LOADING_BASE_ZINDEX+1;
		objTmp["style"]["height"] = _INT_LOADER_GRAPHIC_HEIGHT+"px";
		objTmp["style"]["margin"] = (parseInt(intHeight/2) - parseInt(_INT_LOADER_GRAPHIC_HEIGHT/2))+"px auto";
		objCover.appendChild(objTmp);

		// Add loading image
		var objImg = document.createElement("img");
		objImg["src"] = _STR_PATH_TO_LOADER_GRAPHIC;
		// objImg.setAttribute("name", "dimension");
		// objImg.setAttribute("id", "dimension");
		// objImg.setAttribute("onload", alert(1));
		objTmp.appendChild(objImg);

		// objTarget.appendChild(objCover);
		objTarget.insertBefore(objCover, objTarget.firstChild);
	}

	/**
	 * Function : dump()
	 * Arguments: The data - array,hash(associative array),object
	 *    The level - OPTIONAL
	 * Returns  : The textual representation of the array.
	 * This function was inspired by the print_r function of PHP.
	 * This will accept some data as the argument and return a
	 * text that will be a more readable version of the
	 * array/hash/object that is given.
	 * Docs: http://www.openjs.com/scripts/others/dump_function_php_print_r.php
	 */
	function Dump(arr, level)
	{
		var dumped_text = "";
		if(!level) level = 0;

		//The padding given at the beginning of the line.
		var level_padding = "";
		for(var j=0;j<level+1;j++) level_padding += "    ";

		if(typeof(arr) == 'object')
		{
			//Array/Hashes/Objects
			for(var item in arr)
			{
				var value = arr[item];

				if(typeof(value) == 'object')
				{
					//If it is an array,
					dumped_text += level_padding + "'" + item + "' ...\n";
					dumped_text += Dump(value, level+1);
				}
				else
				{
					dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
				}
			}
		}
		else
		{ //Stings/Chars/Numbers etc.
			dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
		}
		return dumped_text;
	}

	/*
	function _Sleep(intMs)
	{
		var dtNow = new Date();
		var dtExitTime = dtNow.getTime() + intMs;
		while (true)
		{
			dtNow = new Date();
			if (dtNow.getTime() > dtExitTime) return;
		}
	}
	*/

} // End of class

// FOR SLIDING THUMBS MECHANISM
function ScrollLeft(objAnchor)
{
  objAnchor.blur();
  var obj = document.getElementById(_STR_CONVEYER_NAME);
  if (!obj) return;
  else if (_DISABLE_LEFT_SLIDE) return;

  // Needs divs
  var arrItems = obj.getElementsByTagName("div");
  if (arrItems.length == 0) return;

  // Start position
  var intStartPos = null;
  var intEndPos = null;
  if (_INT_CURR_PAGE <= 0)
  {
    DisableControls("left");
    return;
  }
  else intStartPos = -(_INT_CURR_PAGE*_INT_PAGE_WIDTH);

  // End position
  intEndPos = -((_INT_CURR_PAGE*_INT_PAGE_WIDTH) - _INT_PAGE_WIDTH);

  // Tween
  var twn1 = new Tween(obj["style"], "left", Tween.strongEaseOut, intStartPos, intEndPos, 0.5, "px");
  twn1.start();

  // Need to know which page we've arrived at
  _INT_CURR_PAGE--;

  // Item display
  var intStartItem = (_INT_CURR_PAGE * _INT_ITEMS_PER_PAGE) + 1;
  var intEndItem = intStartItem + _INT_ITEMS_PER_PAGE - 1;
  if (intEndItem > arrItems.length) intEndItem = arrItems.length; // For the very last item

  // Update display
  twn1.onMotionFinished = function(){ objCYDRE.UpdateCydreSettingThumbsDisplay(obj, arrItems.length, intStartItem, intEndItem); };

  // Grey out buttons if unavailable
  if(_INT_CURR_PAGE <= 0)
  {
    DisableControls("left");
  }
  ResetControls("right");

  return false;
}

function ScrollRight(objAnchor)
{
  objAnchor.blur();
  var obj = document.getElementById(_STR_CONVEYER_NAME);
  if (!obj) return;
  else if (_DISABLE_RIGHT_SLIDE) return;

  ResetControls("right");

  // Needs divs
  var arrItems = obj.getElementsByTagName("div");
  if (arrItems.length == 0) return;

  // Start position
  var intStartPos = null;
  var intEndPos = null;
  if (_INT_CURR_PAGE <= 0)
  {
    intStartPos = 0; // test for max page
    _INT_CURR_PAGE = 0; // in case it's dropped below 0
  }
  else intStartPos = -(_INT_CURR_PAGE*_INT_PAGE_WIDTH);

  // End position
  if (_INT_CURR_PAGE == 0) intEndPos = -_INT_PAGE_WIDTH;
  else intEndPos = -((_INT_CURR_PAGE*_INT_PAGE_WIDTH) + _INT_PAGE_WIDTH);

  // Tween
  var twn1 = new Tween(obj["style"], "left", Tween.strongEaseOut, intStartPos, intEndPos, 0.5, "px");
  twn1.start();

  // Need to know which page we've arrived at
  _INT_CURR_PAGE++;

  // Item display
  var intStartItem = (_INT_CURR_PAGE * _INT_ITEMS_PER_PAGE) + 1;
  var intEndItem = intStartItem + _INT_ITEMS_PER_PAGE - 1;
  // if (intStartItem > arrItems.length) intStartItem = arrItems.length;
  if (intEndItem > arrItems.length) intEndItem = arrItems.length; // For the very last item

  // Update display
  twn1.onMotionFinished = function(){ objCYDRE.UpdateCydreSettingThumbsDisplay(obj, arrItems.length, intStartItem, intEndItem); };

  // Adjust the controls
  var intRemainder = arrItems.length % _INT_ITEMS_PER_PAGE;
  var intTotalAvailablePages = parseInt(arrItems.length/_INT_ITEMS_PER_PAGE);
  if (intRemainder) intTotalAvailablePages++;

  if (_INT_CURR_PAGE+1 >= intTotalAvailablePages) DisableControls("right");
  else if (arrItems.length <= _INT_ITEMS_PER_PAGE) DisableControls();
  ResetControls("left");

  return false;
}

function DisableControls()
{
  var strCtrl = "both";
  if (DisableControls.arguments[0]) strCtrl = DisableControls.arguments[0];

  if (strCtrl == "both" || strCtrl == "left")
  {
    var objDiv = document.getElementById("cydreSettingThumbsMoveLeft");
    if (objDiv)
    {
      var arrImg = objDiv.getElementsByTagName("img");
      if (arrImg.length) arrImg[0]["src"] = _LEFT_ARROW_PATH_GREY;
    }
    _DISABLE_LEFT_SLIDE = true;
  }

  if (strCtrl == "both" || strCtrl == "right")
  {
    var objDiv = document.getElementById("cydreSettingThumbsMoveRight");
    if (objDiv)
    {
      var arrImg = objDiv.getElementsByTagName("img");
      if (arrImg.length) arrImg[0]["src"] = _RIGHT_ARROW_PATH_GREY;
    }
    _DISABLE_RIGHT_SLIDE = true;
  }
}

function ResetControls()
{
  var strCtrl = "both";
  if (ResetControls.arguments[0]) strCtrl = ResetControls.arguments[0];

  if (strCtrl == "both" || strCtrl == "left")
  {
    var objDiv = document.getElementById("cydreSettingThumbsMoveLeft");
    if (objDiv)
    {
      var arrImg = objDiv.getElementsByTagName("img");
      if (arrImg.length) arrImg[0]["src"] = _LEFT_ARROW_PATH;
    }
    _DISABLE_LEFT_SLIDE = false;
  }

  if (strCtrl == "both" || strCtrl == "right")
  {
    var objDiv = document.getElementById("cydreSettingThumbsMoveRight");
    if (objDiv)
    {
      var arrImg = objDiv.getElementsByTagName("img");
      if (arrImg.length) arrImg[0]["src"] = _RIGHT_ARROW_PATH;
    }
    _DISABLE_RIGHT_SLIDE = false;
  }
}

//
// Carat Slider Controls
//
function BuildCaratSlider(objClass)
{
	// Initialisation
	var objCydreCarat = document.getElementById("cydreCarat");
	var objM1 = document.getElementById("mark1");
	var objM2 = document.getElementById("mark2");
	var objC1 = document.getElementById("carat_min");
	var objC2 = document.getElementById("carat_max");

	objC1["innerHTML"] = RoundTo2DecimalPlaces(_MIN_CARAT);
	objC2["innerHTML"] = RoundTo2DecimalPlaces(_MAX_CARAT);

	// init : function(o, oRoot, minX, maxX, minY, maxY, bSwapHorzRef, bSwapVertRef, fXMapper, fYMapper)
	Drag.init(objM1, null, 0, _FRAMEWORK_WIDTH, 0, 0);
	Drag.init(objM2, null, 0, _FRAMEWORK_WIDTH, 0, 0);

	// 1. To start data grid cover
	// 2. Push this up a level
	objM1.onDragStart = function(x, y) { objM1["style"]["zIndex"] = _Z_INDEX++; }
	objM2.onDragStart = function(x, y) { objM2["style"]["zIndex"] = _Z_INDEX++; }

	// To end data grid cover
	objM1.onDragEnd = function(x, y) { CalculateCarat("min", objM1, objC1, _FRAMEWORK_WIDTH, x); objClass.cydreDataGridUpdateHandler(_SELECTED_CARAT); }
	objM2.onDragEnd = function(x, y) { CalculateCarat("max", objM2, objC2, _FRAMEWORK_WIDTH, x); objClass.cydreDataGridUpdateHandler(_SELECTED_CARAT); }

	// To make sure they don't cross over
	objM1.onDrag = function(x, y) { CalculateCarat("min", objM1, objC1, _FRAMEWORK_WIDTH, x); }
	objM2.onDrag = function(x, y) { CalculateCarat("max", objM2, objC2, _FRAMEWORK_WIDTH, x); }
}

function CalculateCarat(strType, objMark, objDisplay, intFrameworkWidth, intVal)
{
  // carat value 0.30 to 3.00
  if (strType && objMark && objDisplay && intFrameworkWidth && intVal)
  {
    if (intVal == 1) intVal = 0;
    _SELECTED_VALUE[strType] = intVal;

    SnapCaratMark(strType, objMark, intFrameworkWidth, intVal);
    intVal = _SELECTED_VALUE[strType];

    var fltCarat = _MIN_CARAT + (intVal * (_MAX_CARAT - _MIN_CARAT))/intFrameworkWidth;
    fltCarat = RoundTo2DecimalPlaces(fltCarat);
    objDisplay["innerHTML"] = fltCarat;
    // objDisplay["innerHTML"] = intVal; // For debug
    _SELECTED_CARAT[strType] = fltCarat;
  }
}

function SnapCaratMark(strType, objMark, intFrameworkWidth, intVal)
{
  // alert(strType+":"+fltCarat+":"+_SELECTED_CARAT["min"]+":"+_SELECTED_CARAT["max"]);

  // Default
  _SELECTED_VALUE[strType] = intVal;

  if (strType == "max" && intVal < _SELECTED_VALUE["min"])
  {
    _SELECTED_VALUE["max"] = _SELECTED_VALUE["min"];
    objMark["style"]["left"] = _SELECTED_VALUE["min"]+"px";
  }
  else if (strType == "max" && intVal > _FRAMEWORK_WIDTH)
  {
    _SELECTED_VALUE["max"] = _FRAMEWORK_WIDTH;
    objMark["style"]["left"] = _FRAMEWORK_WIDTH+"px";
  }
  else if (strType == "min" && intVal < 0)
  {
    _SELECTED_VALUE["min"] = 0;
    objMark["style"]["left"] = 0+"px";
  }
  else if (strType == "min" && intVal > _SELECTED_VALUE["max"])
  {
    _SELECTED_VALUE["min"] = _SELECTED_VALUE["max"];
    objMark["style"]["left"] = _SELECTED_VALUE["max"]+"px";
  }
}

function RoundTo2DecimalPlaces(n)
{
  return (Math.round(n*100+((n*1000)%10>4?1:0))/100).toFixed(2);
}

function NumberAddCommas(nStr)
{
	nStr += "";
	x = nStr.split(".");
	x1 = x[0];
	x2 = x.length > 1 ? "." + x[1] : "";
	var rgx = /(\d+)(\d{3})/;
	while (rgx.test(x1))
	{
		x1 = x1.replace(rgx, "$1" + "," + "$2");
	}
	return x1 + x2;
}

function InArray(strValue, arrArray)
{
	for(i = 0; i < arrArray.length; i++)
	{
		if (strValue == arrArray[i]) return true;
	}
	return false;
}

function UppercaseFirst(str)
{
    return str.charAt(0).toUpperCase()+str.slice(1);
}

// http://javascript.info/tutorial/animation
/*
	delay - 		Time between frames (in ms, 1/1000 of second). For example, 10ms
	duration - 		The full time the animation should take, in ms. For example, 1000ms

	Then on animation starts, we also fix:
	dtStart - 		The time of animation start, dtStart = new Date.

	As the core of the animation process, on each frame we calculate:
	timePassed - 	The time (in ms) passed from the animation start.
					Changes from 0 to duration, but may occasionally exceed duration because the browser timer is imprecise.
	progress - 		The fraction of animation time that has already passed, calculated on every frame as timePassed/duration. Gradually moves from 0 to 1.
					For example, value progress = 0.5 means that half of duration time is out.
	delta(progress) A function, which returns the current animation progress.
*/
function Move(objElement, fncAnimationType, intMsDuration, strStyleParam, intStyleParamTargetValue)
{
	Animate
	(
		{
			delay: 10,
			duration: intMsDuration || 1000, // 1 sec by default
			delta: fncAnimationType,
			step: function(fncAnimationType)
			{
				objElement["style"][strStyleParam] = intStyleParamTargetValue * fncAnimationType + "px";
			}
		}
	)
}

function Animate(opts)
{
  var dtStart = new Date;

  var id = setInterval
  (
	  function()
	  {
		var timePassed = new Date - dtStart;
		var progress = timePassed / opts.duration;

		if (progress > 1) progress = 1;

		var delta = opts.delta(progress);
		opts.step(delta);

		if (progress == 1)
		{
		  clearInterval(id);
		}
	  },
	  opts.delay || 10
  )
}

function Linear(progress)
{
	return progress;
}

function Quad(progress)
{
	return Math.pow(progress, 2);
}

function Circ(progress)
{
	return 1 - Math.sin(Math.acos(progress));
}

var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
function Base64Encode(input)
{
 input = escape(input);
 var output = "";
 var chr1, chr2, chr3 = "";
 var enc1, enc2, enc3, enc4 = "";
 var i = 0;

 do
 {
	chr1 = input.charCodeAt(i++);
	chr2 = input.charCodeAt(i++);
	chr3 = input.charCodeAt(i++);

	enc1 = chr1 >> 2;
	enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
	enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
	enc4 = chr3 & 63;

	if (isNaN(chr2))
	{
	   enc3 = enc4 = 64;
	}
	else if (isNaN(chr3))
	{
	   enc4 = 64;
	}

	output = output +
	   keyStr.charAt(enc1) +
	   keyStr.charAt(enc2) +
	   keyStr.charAt(enc3) +
	   keyStr.charAt(enc4);
	chr1 = chr2 = chr3 = "";
	enc1 = enc2 = enc3 = enc4 = "";
 }
 while (i < input.length);

 return output;
}

function Base64Decode(input)
{
 var output = "";
 var chr1, chr2, chr3 = "";
 var enc1, enc2, enc3, enc4 = "";
 var i = 0;

 // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
 var base64test = /[^A-Za-z0-9\+\/\=]/g;
 if (base64test.exec(input))
 {
	alert("There were invalid base64 characters in the input text.\n" +
		  "Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
		  "Expect errors in decoding.");
 }
 input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

 do
 {
	enc1 = keyStr.indexOf(input.charAt(i++));
	enc2 = keyStr.indexOf(input.charAt(i++));
	enc3 = keyStr.indexOf(input.charAt(i++));
	enc4 = keyStr.indexOf(input.charAt(i++));

	chr1 = (enc1 << 2) | (enc2 >> 4);
	chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
	chr3 = ((enc3 & 3) << 6) | enc4;

	output = output + String.fromCharCode(chr1);

	if (enc3 != 64)
	{
	   output = output + String.fromCharCode(chr2);
	}
	if (enc4 != 64)
	{
	   output = output + String.fromCharCode(chr3);
	}

	chr1 = chr2 = chr3 = "";
	enc1 = enc2 = enc3 = enc4 = "";

 }
 while (i < input.length);

 return unescape(output);
}

function GetCertificate(objCallee)
{
  var arrDiv = objCallee.parentNode.parentNode.document.getElementsByTagName("div");
  for(var i = 0; i < arrDiv.length; i++)
  {
    if (arrDiv[i]["id"] == "ref")
    {
      objCYDRE.ShowCert(arrDiv[i]["innerHTML"]);
      break;
    }
  }
}

function OnKeyPressedcheck(e, objCallee)
{
	var keycode;
	if (window.event) keycode = window.event.keyCode;
	else if (e) keycode = e.which;

	if(keycode == 13) return objCYDRE.RingDesignSearch(objCallee, 'designSearchText');
}

function SearchLoad(obj)
{
  if (obj["value"] == "" || obj["value"] == strSearchText_02)
  {
    obj["value"] = strSearchText_02;
    obj["style"]["color"] = "#666";
    obj["style"]["fontStyle"] = "italic";
  }
  else
  {
    obj["style"]["color"] = "#000";
    obj["style"]["fontStyle"] = "normal";
  }
  return false;
}

function SearchFocus(obj)
{
  var objTmp = document.getElementById("searchResponse");
  if (objTmp) objTmp.parentNode.removeChild(objTmp);

  if (obj["value"] == strSearchText_02)
  {
    obj["value"] = "";
  }
  obj["style"]["color"] = "#000";
  obj["style"]["fontStyle"] = "normal";
  return false;
}

function SearchBlur(obj)
{
  var objTmp = document.getElementById("searchResponse");
  if (objTmp) objTmp.parentNode.removeChild(objTmp);

  if (obj["value"] == "" || obj["value"] == strSearchText_02)
  {
    obj["value"] = strSearchText_02;
    obj["style"]["color"] = "#666";
    obj["style"]["fontStyle"] = "italic";
  }
  else
  {
    obj["style"]["color"] = "#000";
    obj["style"]["fontStyle"] = "normal";
  }
  return false;
}

function Search(obj)
{
  var objTmp = document.getElementById("searchResponse");
  if (objTmp) objTmp.parentNode.removeChild(objTmp);

  var objTmp = document.getElementById(strSearchFieldId_02);
  if (objTmp)
  {
    if (objTmp["value"] == strSearchText_02 || objTmp["value"] == "")
    {
      alert("Please enter a word to search");
      objTmp.focus();
    }
    else GoTo("/ideas-mcsearch/?ideaSearchTxt="+objTmp["value"]);
  }
  return false;
}


