var firstClick = false;
var clearPanel = false;
var tooltip;
var ti=0;
if (typeof(Adiamor) == "undefined")
{
	Adiamor = {};
}

function PriceChange(value, limit)
{
	if(value == '')
		value = null;
	g_diamondData.setParam("price_"+limit, value);
	g_grid.render();
}

function CaratChange(value, limit)
{
	if(value == '')
		value = null;
	g_diamondData.setParam("carat_"+limit, value);
	g_grid.render();
}

function ShapeChange(value)
{
	document.getElementById("round-qr_cb").checked = true;
	document.getElementById("round_cb").checked = true;
	g_diamondData.setParam('shape_round');

	document.getElementById("princess-qr_cb").checked = true;
	document.getElementById("princess_cb").checked = true;
	g_diamondData.setParam('shape_princess');

	document.getElementById("emerald-qr_cb").checked = true;
	document.getElementById("emerald_cb").checked = true;
	g_diamondData.setParam('shape_emerald');

	document.getElementById("marquise-qr_cb").checked = true;
	document.getElementById("marquise_cb").checked = true;
	g_diamondData.setParam('shape_marquise');

	document.getElementById("heart-qr_cb").checked = true;
	document.getElementById("heart_cb").checked = true;
	g_diamondData.setParam('shape_heart');

	document.getElementById("pear-qr_cb").checked = true;
	document.getElementById("pear_cb").checked = true;
	g_diamondData.setParam('shape_pear');

	document.getElementById("radiant-qr_cb").checked = true;
	document.getElementById("radiant_cb").checked = true;
	g_diamondData.setParam('shape_radiant');

	document.getElementById("oval-qr_cb").checked = true;
	document.getElementById("oval_cb").checked = true;
	g_diamondData.setParam('shape_oval');

	document.getElementById("asscher-qr_cb").checked = true;
	document.getElementById("asscher_cb").checked = true;
	g_diamondData.setParam('shape_asscher');

	document.getElementById("cushion-qr_cb").checked = true;
	document.getElementById("cushion_cb").checked = true;
	g_diamondData.setParam('shape_cushion');
	
	document.getElementById(value+"-qr_cb").checked = true;
	document.getElementById(value+"_cb").checked = true;
	g_diamondData.setParam('shape_'+value, g_inverseMappings.Shape[value]);
	
	updateSliders(0);
	updateSliders(1);
}

function formatCarat(val)
{
	var caratPrecision = 2;
	if (val > 5) { caratPrecision = 1; }
	return Adiamor.lang.formatNumber(val, caratPrecision) + 'ct';
}

function formatMoney0(val)
{
	return Adiamor.lang.formatMoney(val, 0);
}
function formatNumber1(val)
{
	return Adiamor.lang.formatNumber(val, 1);
}
function formatNumber2(val)
{
	return Adiamor.lang.formatNumber(val, 2);
}
function formatDouble(val)
{
	return Math.round(val);
}

function parseValues(aValue)
{
	if(isNaN(aValue))
	{
		return aValue;
	}
	else
	{
		if(typeof(aValue) != "string")
		{
			aValue = aValue.toString();
		}
		
		if(aValue.indexOf(".")>0)
		{
			return parseFloat(aValue);
		}
		else
		{
			return parseInt(aValue, 10);
		}
	}
}

function getDocHeight() {
    var D = document;
    return Math.max(
        Math.max(D.body.scrollHeight, D.documentElement.scrollHeight),
        Math.max(D.body.offsetHeight, D.documentElement.offsetHeight),
        Math.max(D.body.clientHeight, D.documentElement.clientHeight)
    );
}

function getDocWidth() {
    var D = document;
    return Math.max(
        Math.max(D.body.scrollWidth, D.documentElement.scrollWidth),
        Math.max(D.body.offsetWidth, D.documentElement.offsetWidth),
        Math.max(D.body.clientWidth, D.documentElement.clientWidth)
    );
}

function OpenOptions()
{
	FeedbackHide(null);
	if (typeof(Adiamor.ui.Effects.OPEN) == "undefined")
	{
		Adiamor.ui.Effects.OPEN = false;
	}
	if(Adiamor.ui.Effects.OPEN)
	{
		$('slider-mask-polish').style.display="none";
		$('slider-mask-symmetry').style.display="none";
		$('slider-mask-depth').style.display="none";
		$('slider-mask-table').style.display="none";
		$('slider-mask-size').style.display="none";
		$('slider-mask-fluor').style.display="none";
		
		$('label-polish').src="http://www.adiamor.com/images/Adiamor_T/polishlabel.gif";
		$('label-symmetry').src="http://www.adiamor.com/images/Adiamor_T/symmetrylabel.gif";
		$('label-depth').src="http://www.adiamor.com/images/Adiamor_T/depthlabel.gif";
		$('label-table').src="http://www.adiamor.com/images/Adiamor_T/tablelabel.gif";
		$('label-fluor').src="http://www.adiamor.com/images/Adiamor_T/fluorlabel.gif";
		$('label-size').src="http://www.adiamor.com/images/Adiamor_T/lwlabel.gif";
		
		Adiamor.ui.Effects.growToAutomatic($('optional-overlay'), 500, false);
		$('optional-button').style.left="0px";
	}
	else
	{
		$('optional-overlay').style.borderLeft = "solid 1px #a0aebb";
		Adiamor.ui.Effects.shrinkToAutomatic($('optional-overlay'), 500, false);
		$('optional-button').style.left="255px";
	}
	Adiamor.ui.Effects.OPEN = !(Adiamor.ui.Effects.OPEN);
}

function CompleteOpener()
{
	FeedbackHide(null);
	if(typeof(Adiamor.ui.Effects.OPEN) == "undefined")
	{}
	else if(Adiamor.ui.Effects.OPEN)
	{
		$('query-results-filter').style.borderRight = "solid 0px #a0aebb";
		$('optional-overlay').style.backgroundImage = "url('../images/adiamor_t/optional-closer.gif')";
	}
	else
	{
		$('optional-overlay').style.borderLeft = "solid 0px #a0aebb";
		$('optional-overlay').style.backgroundImage = "url('../images/adiamor_t/optional-opener.gif')";
	}
}

function FeedbackShow()
{
	if(Adiamor.ui.Effects.OPEN)
	{
		document.getElementById('FeedbackDiv').style.right="-127px";
		document.getElementById('FeedbackDiv').style.borderRight="0px solid #C1C1C1";
		document.getElementById('FeedbackDiv').style.borderLeft="1px solid #C1C1C1";
	}
	else
	{
		document.getElementById('FeedbackDiv').style.right="-146px";
		document.getElementById('FeedbackDiv').style.borderRight="1px solid #C1C1C1";
		document.getElementById('FeedbackDiv').style.borderLeft="0px solid #C1C1C1";
	}
	document.getElementById('FeedbackDiv').style.display="inline";
}

function FeedbackHide(e)
{
	//var te = (e.toElement || e.relatedTarget);
	
	document.getElementById('FeedbackDiv').style.display="none";
}

/**
 * The url that the provides data for the application.
 * @type String
 */
var g_getHandlerUrl = 'AjaxSearch.aspx';

/**
 * The path to the images for the application
 */
var g_imagePath = '../images/Adiamor_t/';

/**
 * The Grid of diamond results on the second page.
 */
var g_grid;

/**
 * The large sliders on the first page. Each value in the array is an object containing information about each slider.
 * @type Array
 */
var g_mainSliders;
/**
 * The smaller sliders on the first page. Each value in the array is an object containing information about each slider.
 * @type Array
 */
var g_smallSliders;
/**
 * The small sliders on the second page which correspond to the main sliders on the first page. Each value in the array is an object containing information about each slider.
 * @type Array
 */
var g_miniSliders;

/**
 * The slider that is currently being moved. This is used for when users go off the page.
 */
var g_activeSlider = null;

/**
 * Array of checkboxes for the different types of diamonds.
 */
var g_checkboxes = [{name:'round'},
					{name:'princess'},
					{name:'emerald'},
					{name:'marquise'},
					{name:'heart'},
					{name:'pear'},
					{name:'radiant'},
					{name:'oval'},
					{name:'asscher'},
					{name:'cushion'}];

if (typeof(Adiamor.lang) == "undefined")
{
	/**
	 * @constructor
	 */
	Adiamor.lang = {};
}

Adiamor.lang.defineNs = function(namespace)
{
	var names = namespace.split(".");
	var currentNamespace ="";
	var dot="";
	for (var i=0; i < names.length; i++)
	{
		currentNamespace += dot + names[i];
		dot=".";
		if (typeof(eval(currentNamespace)) == "undefined")
		{
			eval(currentNamespace + "={}");
		}
	}
};

/**
 * Allows support for inheritance.
 * @param subClass {object} The class that will inherit from the base.
 * @param baseClass {object} The class that will be inherited from.
 */
Adiamor.lang.extend = function(subClass, baseClass) {
   function inheritance() {}
   inheritance.prototype = baseClass.prototype;

   subClass.prototype = new inheritance();
   subClass.prototype.constructor = subClass;
   subClass.baseConstructor = baseClass;
   if (baseClass.base)
   {
	   baseClass.prototype.base = baseClass.base;
   }
   subClass.base = baseClass.prototype;
};

Adiamor.lang.implement = function(class_, interface_)
{
	if (!(typeof(interface_) == "undefined" || interface_ == null))
	{
		for (var member in interface_.prototype)
		{
			if (interface_.prototype.hasOwnProperty(member)) {
				class_.prototype[member] = interface_.prototype[member];
			}	
		}
	}
	else
	{
		var msg="Adiamor.lang.implement argument interface_ is null or undefined.  The most likely cause of this is that a js file has not been included, or has been included in the wrong order.";
		Adiamor.lang.throwError(msg);		
	}
};

/**
 * Returns true if the member is defined and false otherwise. 
 * Use this only on members, eg, isDefined(this.foo) or 
 * isDefined(obj.foo) but never isDefined(foo).
 * @param {object} a Any member.
 */
Adiamor.lang.isDefined = function(a)
{
	return (typeof(a) != "undefined");
};

Adiamor.lang.close = function(context, func, params)
{
	if (null == params)
	{
		return function()
		{
			return func.apply(context, arguments);
		};
	}
	else
	{
		return function()
		{
			return func.apply(context, params);
		};
	}
};

Adiamor.lang.forEach = function(arr, func)
{
	var len = arr.length;
	for (var i=0; i<len; i++)
	{
		func.call(this, arr[i], i);
	}
	func = null;
};

/**
 * Returns a number from a value, and never returns NaN.
 * @param {String} val A value that may or may not be a number.
 * @return {Number} The numeric interpretation of the value. If none can be made, zero is returned.
 */
Adiamor.lang.parseNumber = function(val)
{
	var num = parseInt(val,10);
	return (isNaN(num) ? 0 : num);
};

Adiamor.lang.formatMoney = function(val, decimals)
{
	if (decimals == null)
	{
		decimals = 2;
	}	
		
	if (val == null)
	{
		val = "NA";
	}
	else
	{
		val = '$' + Adiamor.lang.formatNumber(val, decimals);
	}
	
	return val;
};

/**
 * Formats an integer with commas.
 */
Adiamor.lang.formatNumber = function(nStr, decimals)
{
	nStr += '';
	decimals = (decimals==null?2:decimals);
	var x = nStr.split('.');
	var x1 = x[0];
	var x2 = (x[1]!=null?(x[1]):(''));
	var dot = '';
	if (decimals > 0)
	{
		dot = '.';
		x2 = x2.substring(0, decimals);
		while (x2.length < decimals)
		{
			x2 = x2 + '0';
		}
	}
	else
	{
		x2 = "";
		x1 = (Math.round(nStr)+'').split('.')[0];
	}
	var rgx = /(\d+)(\d{3})/;
	while (rgx.test(x1)) {
		x1 = x1.replace(rgx, '$1' + ',' + '$2');
	}
	return x1 + dot + x2;
};

$ = function(id)
{
	return document.getElementById(id);
};
Adiamor.lang.defineNs("Adiamor.base");

if (typeof(Adiamor.base) == "undefined")
{
	/**
	 * @constructor
	 */
	Adiamor.base = function() {};
}

/**
 * The unique id counter.
 * @private
 */
Adiamor.base.uid = 1;

/**
 * Returns a unique id.
 */
Adiamor.base.getUid = function()
{
	return "Adiamor__uid__"+(Adiamor.base.uid++);
};
/**
 * Generic object that supports the setting of object properties with a single constructor argument and provides garbage collection.
 */
Adiamor.base.Object = function()
{
};

Adiamor.base.Object.prototype.setValues = function(values)
{
	// Sets values on the object using a struct
	for (var item in values)
	{
		if (this[item] != null)
		{
			this[item] = values[item];
		}	
		else if (this[item] instanceof Function)
		{
			this[item](values[item]);
		}	
		else if (this['set'+item] instanceof Function)
		{
			this['set'+item](values[item]);
		}	
		else
		{
			this[item] = values[item];
		}	
	}
};


Adiamor.base.Object.prototype.dispose = function()
{
	if (this.disposing)
	{
		return;
	}	

	this.disposing = true;

	if (this.disposal != null)
	{
		// Loop through the disposal array first. 
		var disposalLength = this.disposal.length;
		for (var i=0; i<disposalLength; i++)
		{
			if (disposal[i] instanceof Function)
			{
				disposal[i].call(context);
			}
			disposal[i] = null;
		}
	}

	// Loop through every item in the object.
	for (var item in this)
	{
		if (this.hasOwnProperty(item)) {
			if (this[item] != null && this[item].dispose instanceof Function)
			{
				this[item].dispose.call(this[item]);
			}
			this[item] = null;
		}	
	}
};
Adiamor.lang.defineNs("Adiamor.base");

/**
 * Based on the MVC pattern the SubjectHelper class is used for event subscription and notification.
 */
Adiamor.base.SubjectHelper = function()
{
	this.handlers = {};
	this.guid = 0;
};

/**
 * Subscribes the given function and context to the event.
 * @type {Int}
 * @returns Returns the unique identifier of the event subscription that can be used for unsubscribing. 
 */
Adiamor.base.SubjectHelper.prototype.subscribe = function(method, context)
{
	var func = method;
	if (typeof context == "object" && method instanceof Function)
	{
		func = Adiamor.lang.close(context, method);
	}
	var guid = func.observer_guid || method.observer_guid || this.guid++;
	func.observer_guid = guid;
	method.observer_guid = guid;
	this.handlers[guid] = func;
};

/**
 * Unsubscribes the subscriber with the given unique ID.
 * @param {Int} guid The unique subscription ID.
 */
Adiamor.base.SubjectHelper.prototype.unSubscribe = function(guid)
{
	if (guid instanceof Function)
	{
		guid = guid.observer_guid;
	}	
	this.handlers[guid] = null;
	delete this.handlers[guid];
};

/**
 * Notifies all the interested subscribers of the event occuring.
 * @param {Object} evtArgs Arbitrary event arguments to be passed to each of the subscribers.
 */
Adiamor.base.SubjectHelper.prototype.notify = function(evtArgs)
{
	var fail = false;
	for (var item in this.handlers)
	{
		if (this.handlers.hasOwnProperty(item)) {
			var handler = this.handlers[item];
			if (handler instanceof Function)
			{
				var rv = (handler.apply(this, arguments)==false);
				fail = fail || rv;
			}
		}	
	}
	return !fail;
};

/**
 * @private
 */
Adiamor.base.SubjectHelper.prototype.dispose = function()
{
	for (handler in this.handlers)
	{
		if (this.handlers.hasOwnProperty(handler)) {
			this.handlers[handler] = null;
		}	
	}
	this.handlers = null;
};

Adiamor.lang.defineNs("Adiamor.browser");


if (typeof(Adiamor.browser) == "undefined")
{
	/**
	 * @constructor
	 */
	Adiamor.browser = function() {};
}


Adiamor.browser.UNKNOWN = true;
Adiamor.browser.IE = false;
Adiamor.browser.MOZ = false;
Adiamor.browser.SAFARI = false;
Adiamor.browser.OPERA = false;
Adiamor.browser.CHROME = false;

/**
 * Detects which browser is being used. <BR>
 * Sets booleans:
 * <UL>
 *   <LI><CODE>Adiamor.browser.IE</CODE>: If browser is Internet Explorer</LI>
 *   <LI><CODE>Adiamor.browser.MOZ</CODE>: If browser is Mozilla (FF or NS)</LI>
 *   <LI><CODE>Adiamor.browser.SAFARI</CODE>: If browser is Safari</LI>
 *   <LI><CODE>Adiamor.browser.UNKNOWN</CODE>: If browser is none of the above</LI>
 * </UL>
 */
Adiamor.browser.detect = function ()
{
	var data = [
		{
			string: navigator.vendor,
			subString: "Apple",
			identity: "Safari"
		},
		{
			prop: window.opera,
			identity: "Opera"
		},
		{
			string: navigator.vendor,
			subString: "iCab",
			identity: "iCab"
		},
		{
			string: navigator.vendor,
			subString: "KDE",
			identity: "Konqueror"
		},
		{
			string: navigator.userAgent,
			subString: "Firefox",
			identity: "Firefox"
		},
		{	// for newer Netscapes (6+)
			string: navigator.userAgent,
			subString: "Netscape",
			identity: "Netscape"
		},
		{
			string: navigator.userAgent,
			subString: "MSIE",
			identity: "Explorer",
			versionSearch: "MSIE"
		},
		{
			string: navigator.userAgent,
			subString: "Gecko",
			identity: "Mozilla",
			versionSearch: "rv"
		},
		{ 	// for older Netscapes (4-)
			string: navigator.userAgent,
			subString: "Mozilla",
			identity: "Netscape",
			versionSearch: "Mozilla"
		}
	];

	var browser = "Unknown";
	var subString = "";
	var dataString = "";
	for (var i=0;i<data.length;i++)	{
		dataString = data[i].string;
		var dataProp = data[i].prop;
		if (dataString) {
			if (dataString.indexOf(data[i].subString) != -1)
			{
				browser = data[i].identity;
				subString = data[i].subString;
				break;
			}
		}
		else if (dataProp)
		{
			browser = data[i].identity;
			subString = data[i].subString;
			break;
		}
	}
	
	Adiamor.browser.IE = (browser == "Explorer");
	Adiamor.browser.IE6 = (Adiamor.browser.IE && !window.XMLHttpRequest);
	Adiamor.browser.IE7 = (Adiamor.browser.IE && window.XMLHttpRequest);
	if (typeof(dataString) == "undefined")
	{
		Adiamor.browser.IE8 = false;
	}
	else
	{
		Adiamor.browser.IE8 = (dataString.indexOf('MSIE 8.0') != -1);
	}

	Adiamor.browser.MOZ = (browser == "Netscape" || browser == "Firefox");
	Adiamor.browser.SAFARI = (browser == "Safari");
	Adiamor.browser.OPERA = (browser == "Opera");
	Adiamor.browser.CHROME = (browser + subString == "MozillaGecko");
	Adiamor.browser.IPHONE = (navigator.appVersion.toLowerCase().indexOf('iphone') != -1);
	Adiamor.browser.IPAD = (navigator.appVersion.toLowerCase().indexOf('ipad') != -1);
	
	Adiamor.browser.XHR_ENABLED = Adiamor.browser.OPERA || Adiamor.browser.SAFARI || Adiamor.browser.MOZ || Adiamor.browser.IE || Adiamor.browser.CHROME;

	// This is a pretty liberal usage of the word unknown - we just don't care about other browsers.
	Adiamor.browser.UNKNOWN = !(Adiamor.browser.IE || Adiamor.browser.MOZ || Adiamor.browser.SAFARI || Adiamor.browser.CHROME);
	
	if(Adiamor.browser.UNKNOWN || Adiamor.browser.IPHONE || Adiamor.browser.IPAD)
	{
		window.location="http://www.adiamor.com/diamondsearch.aspx";
	}

	Adiamor.browser.DocumentWidth = getDocWidth();
	Adiamor.browser.DocumentHeight = getDocHeight();
};

Adiamor.browser.detect();
/**
 * Manages the browser back/forward button history.
 */
Adiamor.browser.History = function()
{
	/**
	 * The last page in the history.
	 */
	this.lastPage = "";
	/**
	 * The current page in the history.
	 */
	this.currentPage = "";
	/**
	 * Event that is fired when the page changes.
	 * Attaching to this enables one to restore the state.
	 * The arguments that are passed to subscribers are the unique path identifier and the full path.
	 */
	this.OnChange = new Adiamor.base.SubjectHelper();

	this.locked = false;

	if (!this.compat()) { return; }

	this.iframeObject = document.createElement('iframe');
	this.iframeObject.style.border = "solid 1px black";
	this.iframeObject.style.width = "100px";
	this.iframeObject.style.height = "100px";
	this.iframeObject.style.display = "none";
	this.iframeObject.setAttribute('name','ntb_history');
	this.iframeObject.setAttribute('id','ntb_history');
	document.body.appendChild(this.iframeObject);
	this.iframe = frames.ntb_history;

	this.monitor();
};

/**
 * Adds a new unique path to the history.
 */
Adiamor.browser.History.prototype.add = function(path)
{
	if (!this.compat()) { return; }
	this.locked = true;
	this.currentPage = path.substr(path.indexOf("#")+1);
	this.lagePage = this.currentPage;
	this.iframe.location.href = path;
	this.locked = false;
};

/**
 * Monitors the status of the iframe location. When the user clicks on the forward or backward button the location changes
 * and the monitor function with notice this change and alert all subscribers by firing the OnChange event.
 */
Adiamor.browser.History.prototype.monitor = function()
{
	if (!this.compat()) { return; }
	var alocation = this.iframe.location.href.split("#");
	this.currentPage = alocation[1];
	if (this.currentPage != this.lastPage && !this.locked)
	{
		this.OnChange.notify(alocation[0].substring(alocation[0].lastIndexOf("/")+1), this.currentPage);
		this.lastPage = this.currentPage;
	}
	window.setTimeout(Adiamor.lang.close(this, this.monitor), 500);
};

Adiamor.browser.History.prototype.compat = function()
{
	if (!Adiamor.browser.IE && !Adiamor.browser.MOZ)
	{
		return false;
	}
	return true;
};

Adiamor.lang.defineNs("Adiamor.html");

if (typeof(Adiamor.html) == "undefined")
{
	/**
	 * @constructor
	 */
	Adiamor.html = function() {};
}


/**
 * Adds the specified CSS class to the specified element.
 * @param {HTMLElement} element The HTML element to which the CSS class should be added.
 * @param {String} className The name of the class to add.
 */
Adiamor.html.addClass = function(element, className)
{
	var css = element.className;
	var re = new RegExp(className, 'gi');
	css = css.replace(re, "");
	element.className = css + ' ' + className;
};

/**
 * Removes the specified CSS class from the specified element.
 * @param {HTMLElement} element The HTML element from which the CSS class should be removed.
 * @param {String} className The name of the class to remove.
 */
Adiamor.html.removeClass = function(element, className)
{
	var css = element.className;
	var re = new RegExp(className, 'gi');
	css = css.replace(re, "");
	element.className = css;
};

/**
 * Retrieves the style from the stylesheet where the rule has a selector made of only the specified cssClass name.
 * @param {String} cssName The name of the class to retrieve.
 */
Adiamor.html.getClass = function(cssClass)
{
	cssClass = "."+cssClass.toLowerCase();
	for (var ss=0; ss<document.styleSheets.length; ss++) {
		var rules = document.styleSheets[ss].rules || document.styleSheets[ss].cssRules;
		for (var rule=0; rule<rules.length; rule++) {
			var ruleItem = rules.item(rule) || rules[rule];
			if (ruleItem.selectorText.toLowerCase() == cssClass) {
				return ruleItem.style;
			}
		}
	}	
};

/**
 * Returns the coords {"x":0,"y":0,"width":0,"height":0} of the specified element.
 */
Adiamor.html.getCoords = function(element)
{
    var coords = {'x': 0, 'y': 0, 'width': element.offsetWidth, 'height':element.offsetHeight };
    while (element)
    {
        if(!Adiamor.browser.SAFARI && !Adiamor.browser.MOZ && !Adiamor.browser.CHROME)
        {
            coords.x += element.offsetLeft;
			coords.y += element.offsetTop;
			element = element.offsetParent;    
        }
        else
        {
			if(typeof(element.offsetLeft) == "undefined") {}
			else {
				coords.x += element.offsetLeft;
			}
			if(typeof(element.offsetTop) == "undefined") {}
			else {
				coords.y += element.offsetTop;
			}
	       
			element = Adiamor.html.getParent(element);
		}
    }
    // Now account for the scroll positions of all the elements
    //for (;origElement != document.body; coords.x -= origElement.scrollLeft, coords.y -= origElement.scrollTop, origElement = origElement.parentNode);
    return coords;
};

Adiamor.html.getParent = function(element)
{
	var op = false;
	
	while (!op)
	{
		if(element.offsetParent == null)
		{
			if(element.parentNode != null)
			{
				element = element.parentNode;
			}
			else
			{
				element = null;
				op = true;
			}
		}
		else
		{
			op = true;
			element = element.offsetParent;
		}
	}
	return element;
};

Adiamor.html.getUniqueId = function(elem)
{
	if (elem.uniqueID)
	{
		return elem.uniqueID;
	}
	else
	{
		var t = (new Date()).getTime();
		// The element should remember the unique id since it is assigned once and based on time.
		elem.uniqueID = t;
		return t;
	}
};

if (Adiamor.browser.IE)
{
	Adiamor.html.getFirstChild = function(node)
	{
		if(node != null)
		{
			return node.firstChild;
		}
		else
		{
			return $('slider-extension-container').firstChild;
		}	
	};
}
else // This will be used for all other browsers ... does safari use whitespace nodes???
{
	Adiamor.html.getFirstChild = function(node)
	{
		var i = 0;
		while (i < node.childNodes.length && node.childNodes[i].nodeType == 3)
		{
			i++;
		}	
		return node.childNodes[i];
	};
}

Adiamor.html.align = function(source,target,AlignBit_HWTBLRCM,oh,ow,oy,ox)
{
	oh=oh || 0;
	ow=ow || 0;
	oy=oy || 0;
	ox=ox || 0;
	var a=AlignBit_HWTBLRCM;
	var td,sd,tt,tb,tl,tr,th,tw,st,sb,sl,sr,sh,sw;

	if (Adiamor.browser.IE)
	{
		td=target.getBoundingClientRect();
		sd=source.getBoundingClientRect();
		tt=td.top;
		tb=td.bottom;
		tl=td.left;
		tr=td.right;
		th=Math.abs(tb-tt);
		tw=Math.abs(tr-tl);

		st=sd.top;
		sb=sd.bottom;
		sl=sd.left;
		sr=sd.right;
		sh=Math.abs(sb-st);
		sw=Math.abs(sr-sl);
	}
	/*else if (Adiamor.browser.MOZ)
	{
		td = document.getBoxObjectFor(target);
		sd = document.getBoxObjectFor(source);

		tt = td.y;
		tl = td.x;
		tw = td.width;
		th = td.height;

		st = sd.y;
		sl = sd.x;
		sw = sd.width;
		sh = sd.height;
	} */
	else
	{
		td = Adiamor.html.getCoords(target);
		sd = Adiamor.html.getCoords(source);

		tt = td.y;
		tl = td.x;
		tw = td.width;
		th = td.height;

		st = sd.y;
		sl = sd.x;
		sw = sd.width;
		sh = sd.height;
	}
	var s = source.style;

	if (a&0x10000000) { s.height = (th+oh)+'px'; } // make same height
	if (a&0x01000000) { s.width = (tw+ow)+'px'; } // make same width
	if (a&0x00100000) { s.top = (parseInt(Adiamor.dom.getStyle(source,'top'),10)+tt-st+oy)+'px'; } // align top
	if (a&0x00010000) { s.top = (parseInt(Adiamor.dom.getStyle(source,'top'),10)+tt-st+th-sh+oy)+'px'; } // align bottom
	if (a&0x00001000) { s.left = (parseInt(Adiamor.dom.getStyle(source,'left'),10)-sl+tl+ox)+'px'; } // align left
	if (a&0x00000100) { s.left = (parseInt(Adiamor.dom.getStyle(source,'left'),10)-sl+tl+tw-sw+ox)+'px'; } // align right
	if (a&0x00000010) { s.top = (parseInt(Adiamor.dom.getStyle(source,'top'),10)+tt-st+oy+Math.floor((th-sh)/2))+'px'; } // align middle vertically
	if (a&0x00000001) { s.left = (parseInt(Adiamor.dom.getStyle(source,'left'),10)-sl+tl+ox+Math.floor((tw-sw)/2))+'px'; } // align middle horizontally
};

Adiamor.ah = 0x10000000;
Adiamor.aw = 0x01000000;
Adiamor.at = 0x00100000;
Adiamor.ab = 0x00010000;
Adiamor.al = 0x00001000;
Adiamor.ar = 0x00000100;
Adiamor.amv = 0x00000010;
Adiamor.amh = 0x00000001;

/**
 * @class Adiamor.html.Event is a cross-browser, globally accessible event object which is set when DOM events are fired through the EventManager.
 */
Adiamor.html.Event = function(){};

/**
 * @private
 */
Adiamor.html.handlerId = 0;
/**
 * @private
 */
Adiamor.html.elementId = 0;
/**
 * @private
 */
Adiamor.html.elements = [];
/**
 * @private
 */
Adiamor.html.unload = [];
/**
 * @private
 */
Adiamor.html.unloadCalled = false;

/**
 * Attaches multiple events to a single element
 * @param {HtmlElement} element The HTML element to which the events should be attached.
 * @param {Struct} events Structs of the events with type and handler properties.
 * @param {Object} context The context in which the handlers should be executed.
 */
Adiamor.html.attachEvents = function(element, events, context)
{
	for (var i=0; i<events.length; i++)
	{
		var e = events[i];
		Adiamor.html.attachEvent(element, e.type, e.handler, context, e.capture || false);
	}
};

/**
 * Attaches the specified handler to the DOM element for the specified event type.
 * @param {HtmlElement} element Element on which the event is to be registered.
 * @param {String} type Event type such as 'click', 'mouseover' etc. Note that the 'on' prefix is dropped.
 * @param {Object} context Object that the callback function will be called on. Optional.
 * @param {Function} handler Function pointer to the function that will handle the event.
 * @param {Boolean} capture Specifies if event capturing should be used. Optional.
 */
Adiamor.html.attachEvent = function(element, type, handler, context, capture)
{
	if(element == null)
		return;
	/*
	// Divert unload attachments to custom unload registration
	if (type == 'unload')
	{
		var funcRef = handler;
		if (context != null)
		{
			funcRef = function() {handler.call(context)};
		}
		this.addUnload(funcRef);
	}
	*/

	//	Increment our unique id to keep it unique
	var handlerGuid = this.handlerId++;
	var elementGuid = this.elementId++;

	//	Check if the handler already has a guid or not
	//	The guid is used again when we detach the handler for an event
	if (typeof(handler.ebaguid) != "undefined")
	{
		handlerGuid = handler.ebaguid;
	}
	else
	{
		handler.ebaguid = handlerGuid;
	}

	//	Allow people to pass in a node id or an actual DOM node.
	if (typeof(element) == "string")
	{
		element = document.getElementById(element);
	}


	//	Check the custom ebaguid property on the DOM Element object
	//	The ebaguid on the element is used to keep track of all elements that have had events attached
	if(this.elements == null)
			this.elements = [];
	
	if (typeof(element.ebaguid) == "undefined")
	{
		element.ebaguid = elementGuid;
		//	add a reference to the element in the elements hash - this could also just use array.push()
		this.elements[elementGuid] = element;
	}

	//	The custom eba_events property on the DOM Element object contains
	//	all the events that have been registered on this element.
	if (typeof(element.eba_events) == "undefined")
	{
		element.eba_events = {};
	}

	//	The 'eba_events' property on the DOM node is a hash of the event type
	//	ie store all the handlers defined for event type 'mouseover' in another hash
	if (element.eba_events[type] == null)
	{
		element.eba_events[type] = {};

		//	Browser checking for IE / Adiamor.browser.MOZ
		if (element.attachEvent)
		{
			element['eba_event_'+type] = function () {Adiamor.html.notify.call(element, window.event);};
			//	Detach will need to be called to get rid of this closure...
			element.attachEvent('on'+type, element['eba_event_'+type]);

			if (capture) { element.setCapture(true); }
		}
		else if (element.addEventListener)
		{
			element.addEventListener(type, function () {Adiamor.html.notify.call(element, arguments[0]);}, capture);
		}
	}

	//	Once we get here the event has been hooked up 
	//	or it is already hooked up - either way we need to
	//	add the handler to the list of handlers to fire
	element.eba_events[type][handlerGuid] = {handler: handler, context: context};


//	element = null;
//	context = null;
};

/**
 * @private
 */
Adiamor.html.notify = function(e)
{
	if (!Adiamor.browser.IE)
	{
		e.srcElement = e.target;
		e.fromElement = e.relatedTarget;
		e.toElement = e.relatedTarget;
	}
	Adiamor.html.Event = e;
	var element = this;
	Adiamor.html.Event.ebaEventSrc = element;

	for (var handlerGuid in element.eba_events[e.type])
	{
		if (element.eba_events[e.type].hasOwnProperty(handlerGuid))
		{
			var event_ = element.eba_events[e.type][handlerGuid];
			if (typeof(event_.context) == "object")
			{
				//	Call the handler in the context of the object located in context.
				event_.handler.call(event_.context, e, element);
			}
			else
			{
				event_.handler.call(element, e, element);
			}
		}	
	}
};

/**
 * Detaches multiple events to a single element
 * @param {HtmlElement} element The HTML element to which the events should be detached from.
 * @param {Struct} events Structs of the events with type and handler properties.
 */
Adiamor.html.detachEvents = function(element, events)
{
	for (var i=0; i<events.length; i++)
	{
		var e = events[i];
		Adiamor.html.detachEvent(element, e.type, e.handler);
	}
};

/**
 * Removes an event handler from an HTML element.
 * @param {HtmlElement} element The HTML element to remove the handler from.
 * @param {String} type The event type string such as "mouseover".
 * @param {Function} handler The event handler function reference.
 */
Adiamor.html.detachEvent = function(element, type, handler)
{
	//	Allow people to pass in a node id or an actual DOM node.
	if (typeof(element) == "string")
	{
		element = document.getElementById(element);
	}

	//	Check if the event type and handler combination are defined
	if (element.eba_events != null && element.eba_events[type] != null && element.eba_events[type][handler.ebaguid] != null)
	{

		var handlers = element.eba_events[type];
		// Remove it from the list of handlers
		handlers[handler.ebaguid] = null;
		delete handlers[handler.ebaguid];

		//	What actually needs to be done here is ..
		//	if this is the last handler for a certain event type on an element to be removed
		//	then we need to detach it...
		// element['eba_event_'+type]

		if (Adiamor.collections.isHashEmpty(handlers))
		{
			this.m_detach(element, type, element['eba_event_'+type]);
     		element['eba_event_'+type] = null;
     		element.eba_events[type] = null;
     		handlers = null;
     		if (element.nodeType == 3)
         	{
         		element.removeAttribute('eba_event_'+type);
         	}	
		}
	}
};

/**
 * @private
 */
Adiamor.html.m_detach = function(element, type, handler)
{
	//	Detach in IE
	if (element.detachEvent)
	{
		element.detachEvent('on' + type, handler);
	}
	//	Remove in Firefox
	else if (element.removeEventListener)
	{
		element.removeEventListener(type, handler, false);
	}
	element['on' + type] = null;

	if (type == "unload")
	{
		//	Here we are doing unload so call all the things that are manually registered for unload
		for (var i=0; i<this.unload.length; i++)
		{
			this.unload[i].call(this);
			this.unload[i] = null;
		}
	}
};

Adiamor.html.detachAllEvents = function()
{
	//	TODO: this needs to be fixed not to use the looping through the array and use the hash instead
	for (var i=0; i<Adiamor.html.elements.length; i++)
	{
		if (typeof(Adiamor.html.elements[i]) != "undefined")
		{
			for (var eventType in Adiamor.html.elements[i].eba_events)
			{
				if (Adiamor.html.elements[i].eba_events.hasOwnProperty(eventType))
				{
					//	Need to detach the Adiamor.html.event.notify method from the element.
					Adiamor.html.m_detach(Adiamor.html.elements[i], eventType, Adiamor.html.elements[i]['eba_event_'+eventType]);

					if (typeof(Adiamor.html.elements[i]) != "undefined" && Adiamor.html.elements[i].eba_events[eventType] != null)
					{
						for (var j=0; j<Adiamor.html.elements[i].eba_events[eventType].length; j++)
						{
							Adiamor.html.elements[i].eba_events[eventType][j] = null;
						}
					}

					Adiamor.html.elements[i]['eba_event_'+eventType] = null;
				}	
			}
		}
	}

	Adiamor.html.elements = null;
};

Adiamor.html.addUnload = function(funcRef)
{
	this.unload.push(funcRef);
};

/**
 * @private
 */
Adiamor.html.cancelEvent = function(evt)
{
	if (evt == null) { return; }

	if (Adiamor.browser.MOZ)
	{
		evt.preventDefault();
		evt.stopPropagation();
	}
	else if (Adiamor.browser.IE)
	{
		evt.cancelBubble = true;
		evt.returnValue = false;
	}
};

Adiamor.html.stopEvent = function(evt)
{
	if (evt == null) { return; }

	if (Adiamor.browser.MOZ) { evt.stopPropagation(); }
	else if (Adiamor.browser.IE) { evt.cancelBubble = true; }
};

//TODO: this should be moved into the Eba.EventManager object
Adiamor.html.cancelBubble = function (e,v)
{
	e.returnValue = false;
	e.cancelBubble = true;
	if (v!=null) { e.keyCode = v; }
};

Adiamor.html.getEventCoords = function(evt)
{
    var coords = {'x':evt.clientX,'y':evt.clientY};
    if (Adiamor.browser.IE) 
    {
        coords.x += document.documentElement.scrollLeft + document.body.scrollLeft;
        coords.y += document.documentElement.scrollTop + document.body.scrollTop;
    }
    else
    {
        coords.x += window.scrollX;
        coords.y += window.scrollY;
    }
    return coords;
};

//	first thing is to call unregisterAll onunload
//document.getElementsById('body').item(0)
Adiamor.html.attachEvent(window, "unload", Adiamor.html.detachAllEvents, Adiamor.html, false);

/**************************************************************************/
/*					Adiamor.com	     	      
/**************************************************************************/

Adiamor.lang.defineNs("Adiamor.dom");

Adiamor.dom.getTop = function(elem)
{
	return Number(elem.style.top.replace(/p.*/,''));
};


Adiamor.dom.getLeft = function(elem)
{
	return Number(elem.style.left.replace(/p.*/,''));
};

Adiamor.dom.getUniqueId = function(elem)
{
	if (elem.uniqueID)
	{
		return elem.uniqueID;
	}
	else
	{
		var t = (new Date()).getTime();
		// The element should remember the unique id since it is assigned once and based on time.
		elem.uniqueID = t;
		return t;
	}
};

/**
 * Sets the opacity of an element.
 * @param {Element} element The element on which to set the opacity.
 * @param {int} opacity The opacity, 0 - 100;
 */
Adiamor.dom.setOpacity = function(element, opacity)
{
    var s = element.style;
	if (opacity < 100)
	{
		s.filter = "alpha(opacity=" + opacity + ")";
		s.opacity = (opacity / 100);
	}
	else
	{
		//	previously s.filter = s.filter.replace(/alpha\(opacity\=.[^\)]*]\)/,'');
		if (s.filter != null) { s.filter = s.filter.replace(/alpha\(opacity\=\.\[\^\)\]\*\]\)/,''); }
		s.opacity = "1";
	}
    //objectStyle['-moz-opacity'] = (opacity / 100);
    //objectStyle.KhtmlOpacity = (opacity / 100);
};

/**
 * Gets the opacity of an element. This depends on the element having both a 
 * Mozilla and IE6 opacity set.
 */
Adiamor.dom.getOpacity = function(element)
{
	return Math.abs(element.style.opacity ? element.style.opacity * 100 : 0);
};

Adiamor.dom.getStyle = function (oElm, strCssRule)
{
    var strValue = "";
	if (oElm.style[strCssRule])
	{
		// inline style property
		return oElm.style[strCssRule];
	}
	else if (oElm.currentStyle)
	{
		// external stylesheet for Explorer
        strCssRule = strCssRule.replace(/([A-Z])/g, "-$1");
        strValue = oElm.currentStyle[strCssRule];
	}
	else if(document.defaultView && document.defaultView.getComputedStyle)
    {
		strValue = document.defaultView.getComputedStyle(oElm, "").getPropertyValue(strCssRule);
    }
    //if (strValue == 'auto' && console != null)
    //	console.log(strCssRule + ' is auto on ' + oElm);
    return strValue;
};


if (typeof(Adiamor.ajax) == "undefined")
{
	/**
	* The Adiamor.ajax namespace is the place to put anything related to the XMLHttpRequest object.
	* @namespace
	*/
	Adiamor.ajax = function() {};
}

/**
* Creates an XMLHttpRequest object.
* @private
* @returns {XMLHttpRequest}
*/
Adiamor.ajax.createXmlHttp = function()
{
	if (Adiamor.browser.IE)
	{
		//	TODO: try all the XML HTTP objects starting from 5...
		var reservedObj = null;
		try
		{
			reservedObj = new ActiveXObject("Msxml2.XMLHTTP");
		}
		catch(e)
		{
			try
			{
				reservedObj = new ActiveXObject("Microsoft.XMLHTTP");
			}
			catch(ee)
			{
			}
		}
		return reservedObj;
	}
	else if (Adiamor.browser.XHR_ENABLED)
	{
		return new XMLHttpRequest();
	}
};
Adiamor.lang.defineNs("Adiamor.ajax");

Adiamor.ajax.HttpRequestPool_MAXCONNECTIONS=64;

/**
 * @class Adiamor.ajax.HttpRequest
 * @constructor
 * Makes an XMLHttpRequest and processes the result.
 * <P>Normally web forms post data back to the server when the user clicks the "SUBMIT" button. The Adiamor Grid sends data to the server without the need for a form submission to occur. This means the browser does not navigate to a new page and the user can continue editing data on the current page. Some developers may wish to post data entered into the grid along with a form submission. This can be accomplished easily by copying the XML from the updategram into a hidden HTML form field before the form is submitted.</P><P>In addition some developers may wish to make the grid save "invisibly" or in other words, without the user clicking "Save". This is also easy to accomplish by calling the save() method during oncellmodified events or any other event you may wish to use.</P><P>The Grid transmits the updategrams to a "handler" which is a server-side script or program that accepts XML updates posted from the browser and processes the updates by updating a database, flat-file or external system. Many examples of handlers are included with the Grid but the developer may choose to implement his/her own custom handler to meet the specific needs of the application. </P>
 */
Adiamor.ajax.HttpRequest = function()
{
	/**
	 * This is the URL of the server resource that data is being posted to or
	 * retrieved from.
	 */
  	this.handler 		= '';
  	/**
  	 * This specifies if the requests should be made in an asynchronous or synchronous manner.
  	 */
	this.async 	= true;
	/**
	 * This specifies if XML data or general text data is being retrieved from the server. 
	 * Valid values are "xml", "text" or "". Using "text" can be used for returning JSON data or any other
	 * data format including XML. The data passed to the callback method with be an XmlDocument if "xml" is
	 * specified as the responseType, it will be a String if "text" is specified, and it will be an XMLHttpRequest object otherwise.
	 */
	this.responseType	= "xml";
	/**
	 * This is the underlying XMLHttpRequest object.
	 * @private
	 */
	this.httpObj      	= Adiamor.ajax.createXmlHttp();
	/**
	 * This is a function reference to a function that is executed after data has been 
	 * posted to the server and the asynchronous request has returned. The first argument passed to the postComplete 
	 * handler is the data returned from the server and the second argument is the params value of the HttpRequest object.
	 */
	this.OnPostComplete	= new Adiamor.base.SubjectHelper();
	/**
	 * This is a function reference to a function that is executed after data has been 
	 * retrieved from the server through an asynchronous request. The first argument passed to the getComplete 
	 * handler is the data returned from the server and the second argument is the params value of the HttpRequest object.
	 */
	this.OnGetComplete	= new Adiamor.base.SubjectHelper();
	/**
	 * This is a function reference to a function that is executed if there is an error during or after the request.
	 */	
	this.OnError		= new Adiamor.base.SubjectHelper();
	/**
	 * The length of time that can pass before the request is cancelled. A value of 0 indicates there is no timeout.
	 */
	this.timeout = 5000;
	this.retry = 2;
	/**
	 * The ID of the window.setTimeout registration.
	 */
	this.timeoutId = null;
	/**
	 * This is a parameter object that can contain any information needed to be passed
	 * to the postComplete or getComplete functions after an asynchronous request has returned.
	 * This can be used to maintain state across an asynchronous request.
	 */
	this.params			= null;
	/**
	 * A copy of the data that is sent to the server in a post
	 */
	 this.data		= "";
	 this.status = "complete";
};

Adiamor.lang.extend(Adiamor.ajax.HttpRequest, Adiamor.base.Object);

/**
 * This method takes the response from the server and checks the HTTP status 
 * to ensure that the server did not have any errors and returned valid XML.
 */
Adiamor.ajax.HttpRequest.prototype.handleResponse = function()
{
  	var result = null;
    try{
		if (this.responseType == "xml")
		{
			result = this.httpObj.responseXML;
		}
		else if (this.responseType == "text")
		{
			result = this.httpObj.responseText;
		}
		else
		{
			result = this.httpObj;
		}
	// try to clean up mem for GC
	} 
	catch(err) 
	{
		var message = (err.description) || err;
		// TODO: fire the onError handler ... 
		// This just alerts the same assert message as before
		//ebaErrorReport("handleResponse Exception " + message, EBA_XHR_RESPONSE_ERROR, EBA_ERROR);		
	}
	finally 
	{
		return result;
	}
};

/**
 * This method posts some data to the given url using the XMLHttpRequest object.
 * Various parameters such as asynchronous and handler should have already been set.
 * @param {string} data The only argument passed to this method is some data to post
 * to the server. It can be in any format such as XML or JSON.
 * @return {XmlElement}
 */
Adiamor.ajax.HttpRequest.prototype.post = function(data)
{
	// This is for debugging purposes in case the post fails.
	this.data = data;

	this.status = "pending";
	
	if(!this.httpObj) {	this.httpObj = Adiamor.ajax.createXmlHttp(); }

	this.httpObj.open("POST", this.handler, this.async, "", "");

    if (this.async)
    {
	    // Creating a inner function and assigning it to the ebaCallback instances httpObj.onreadystatechange
	    // This creates a closure (This is circular reference)
	    // 
	    this.httpObj.onreadystatechange = Adiamor.lang.close(this, this.postComplete);
	}
    if (this.responseType == "xml") { this.httpObj.setRequestHeader("Content-Type","text/xml"); }
	else { this.httpObj.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); }
    this.httpObj.send(data);
};

Adiamor.ajax.HttpRequest.prototype.postComplete = function()
{
    if(this.httpObj.readyState==4)
    {
    	this.status = "complete";
    	this.OnPostComplete.notify({'response':this.handleResponse(),'params':this.params});
	}
};

/**
 * This does various assertions on XMLData then calls postData.
 * If xmlData is has no valid child nodes the just return
 * @param {XmlNode} xmlData The single argument passed to this method is a valid XML DOM object.
 */
Adiamor.ajax.HttpRequest.prototype.postXml = function(xmlData)
{
	this.setTimeout();

    // validate the XML data parameter
    if(("undefined" == typeof(xmlData.documentElement)) || 
       (null == xmlData.documentElement) || 
       ("undefined" == typeof(xmlData.documentElement.childNodes)) ||
       (1 > xmlData.documentElement.childNodes.length))
    {
        ebaErrorReport("updategram is empty. No request sent. xmlData[" + xmlData + "]\nxmlData.xml[" + xmlData.xml + "]");
        // not sure that return is best here.
        return; 
    }

    //  get data from xml (null == xmlData.xml)
    if(null == xmlData.xml)
	{
            // looks like we are not running Adiamor.browser.ie
            // lets try to get xml data            
            var xmlSerializer = new XMLSerializer();
            xmlData.xml     = xmlSerializer.serializeToString(xmlData);
	}
	this.post(xmlData.xml);
};

/**
 * This is used to retrieve data from the server.
 * It will retrieve data from the URL specified by the handler property of the Callback object.
 */
Adiamor.ajax.HttpRequest.prototype.get = function()
{
	this.setTimeout();

	this.status = "pending";

	try{
	      this.httpObj.open("GET", this.handler, this.async);
    }
    catch(e) {
		throw(e);
	}

    if (this.async) { this.httpObj.onreadystatechange = Adiamor.lang.close(this, this.getComplete); }

	if (this.responseType == "xml") { this.httpObj.setRequestHeader("Content-Type","text/xml"); }

    this.httpObj.send(null);

	if (!this.async) { return this.handleResponse(); }
};

Adiamor.ajax.HttpRequest.prototype.setTimeout = function()
{
	if (this.timeout > 0)
	{
		this.timeoutId = window.setTimeout(Adiamor.lang.close(this, this.abort), this.timeout);
	}
};

/**
 * The OnReadyStateChange event is used internally for monitoring the 
 * readyState of the XMLHttpRequest when data is being retrieved from the server.
 * When the readyState is 4 then it will call the function pointer onGetComplete.
 */
Adiamor.ajax.HttpRequest.prototype.getComplete = function()
{
    if(this.httpObj.readyState==4)
    {
    	this.status = "complete";
    	this.OnGetComplete.notify({'response':this.handleResponse(),'params':this.params});
	}
};


Adiamor.ajax.HttpRequest.prototype.abort = function()
{
	this.httpObj.onreadystatechange = function () {};
	this.httpObj.abort();

	if (this.retry)
	{
		this.retry--;
		this.get();
	}
};

/**
 * This method clears the state of the Callback object to its initial state.
 */
Adiamor.ajax.HttpRequest.prototype.clear = function()
{
  	this.handler 		= '';
	this.async 	= true;
	this.onPostComplete	= null;
	this.onGetComplete	= null;
	this.params = null;
};

/**
 * Adds a cache-busting querystring parameter to the request.
 */
Adiamor.ajax.HttpRequest.prototype.cacheBust = function(url)
{
	var urlArray = url.split('?');
	var param = 'Adiamor_cachebust=' + (new Date().getTime());
	if (urlArray.length == 1) { url += '?' + param; }
	else { url += '&' + param; }
	return url;
};

/**
 * @class Adiamor.ajax.HttpRequestPool
 * @constructor
 * @param {Number} maxObjects The maximum number of HttpRequest objects in the pool.
 */
Adiamor.ajax.HttpRequestPool = function(maxObjects)
{
	/**
	 * @private
	 */
	this.inUse = [];
	/**
	 * @private
	 */
	this.free = [];
	/**
	 * @private
	 */
	this.max = maxObjects || Adiamor.ajax.HttpRequestPool_MAXCONNECTIONS;
	/**
	 * @private
	 */
	this.locked = false;
	/**
	 * @private
	 */
	this.context = null;
};

/**
 * Retrieves an HttpRequest object from the pool. If there are no available objects it will create a new one until the
 * maximum number of objects are created.
 * @return {Adiamor.ajax.HttpRequest}
 */
Adiamor.ajax.HttpRequestPool.prototype.reserve = function()
{
	// A blocking lock for thread safety
	//	TODO: This should be changed into a callback to prevent user interface locking ...
//		while (this.locked) {}

	this.locked = true;

	var reservedObj;

	if (this.free.length)
	{
		reservedObj = this.free.pop();
		reservedObj.clear();
		this.inUse.push(reservedObj);
	}
	else if(this.inUse.length < this.max)
	{
		try
		{
			reservedObj = new Adiamor.ajax.HttpRequest();
		}
		catch(e)
		{
			reservedObj=null;
		}

		this.inUse.push(reservedObj);
	}
	else
	{
		throw "No request objects available";
	}

	this.locked = false;
	return reservedObj;
};

/**
 * Returns an HttpRequest object back to the pool.
 * @param {Adiamor.ajax.HttpRequest} resource
 */
Adiamor.ajax.HttpRequestPool.prototype.release = function(resource)
{
	var found = false;
	// A blocking lock for thread safety - necessary in javascript?
	//while (this.locked) {}
	this.locked = true;
	if (null != resource)
	{
		for (var i=0; i < this.inUse.length; i++)
		{
			if (resource == this.inUse[i])
			{
				this.free.push(this.inUse[i]);
				this.inUse.splice(i,1);
				found = true;
				break;
			}
		}
	}
	this.locked = false;

	return null;
};

/**
 * @private
 */
Adiamor.ajax.HttpRequestPool.prototype.dispose = function()
{
	for (var i=0; i<this.inUse.length; i++)
	{
		this.inUse[i].dispose();
	}
	this.inUse = null;
	for (var j=0; j<this.free.length; j++)
	{
		this.free[i].dispose();
	}
	this.free = null;
};
Adiamor.lang.defineNs('Adiamor.data');

if (typeof(Adiamor.data) == "undefined")
{
	/**
	 * @constructor
	 */
	Adiamor.data = function() {};
}

/**
 * Mappings for values to text for the various diamond properties.
 */
var g_mappings = {	'Fluor':{'43':'F','44':'MB','42':'N','45':'SB','46':'VS'},
					'Cut':{'141':'Excellent','144':'Fair','143':'Good','147':'Ideal','146':'None','145':'Poor','142':'Very Good','211':'Premium','999':'Affinity'},
					'Shape':{'67':'Asscher','68':'Baguette','113':'Cushion','18':'Emerald','20':'Heart','19':'Marquise','65':'Oval','21':'Pear','17':'Princess','22':'Radiant','16':'Round','66':'Trilliant'},
					'Clar':{'31':'IF','36':'SI1','37':'SI2','34':'VS1','35':'VS2','32':'VVS1','33':'VVS2'},
					'Color':{'23':'D','24':'E','25':'F','26':'G','27':'H','28':'I','29':'J','30':'K'},
					'Cert':{'38':'GIA','39':'EGL','41':'AGS'},
					'Pol':{'61':'EX','64':'F','63':'G','136':'I','62':'VG'},
					'Sym':{'61':'EX','64':'F','63':'G','136':'I','62':'VG'},
					'Culet':{'58':'None','59':'Very Small','60':'Small','115':'Medium','116':'Large','135':'Pointed'},
					'Cut1':{'141':'EX','144':'F','143':'G','147':'I','146':'N','145':'P','142':'VG','211':'P','999':'AI'}};

var g_inverseMappings = {'Shape':{'asscher':'67','baguette':'68','cushion':'113','emerald':'18','heart':'20','marquise':'19','oval':'65','pear':'21','princess':'17','radiant':'22','round':'16','trilliant':'66'}};

/**
 * The JsonDataView repesents a client side JSON based datasource.
 * @constructor
 * @extends {Adiamor.base.Object}
 */
Adiamor.data.JsonDataView = function()
{
	/**
	 * Unique ID
	 */
	this.uid = Adiamor.base.getUid();

	/**
	 * Mapping of the field names to the index in each record of data. Each record of data is an Array itself.
	 */
	this.fieldMap = {"xi":0};

	/**
	 * The schema of the data expected from the server. The index of the field in the schema is that index in which
	 * the data is expected from the server.
	 */
	this.Schema = [	{'Name':'xi','Type':'number','Default':0,'Decimals':0},
					{'Name':'ID','Type':'text','Default':'0'},
					{'Name':'Shape','Type':'image','Default':''},
					{'Name':'Carat','Type':'number','Default':'','Decimals':2},
					{'Name':'Color','Type':'text','Default':''},
					{'Name':'Clar','Type':'text','Default':''},
					{'Name':'Cut','Type':'text','Default':''},
					{'Name':'Pol','Type':'text','Default':''},
					{'Name':'Sym','Type':'text','Default':''},
					{'Name':'Depth','Type':'number','Default':'','Decimals':1},
					{'Name':'Tbl','Type':'text','Default':''},
					{'Name':'Fluor','Type':'text','Default':''},
					{'Name':'Size','Type':'number','Default':'','Decimals':2},
					{'Name':'Cert','Type':'text','Default':''},
					{'Name':'SPrice','Type':'money','Default':'0'},
					{'Name':'Selected','Type':'boolean','Default':'0'},
					{'Name':'Info','Type':'button','Default':'link_url.html'},
					{'Name':'Girdle','Type':'text','Default':''},
					{'Name':'Meas','Type':'text','Default':''},
					{'Name':'Culet','Type':'text','Default':''}];

	/**
	 * Fires when the number of rows in the DataView changes.
	 */
	this.OnRowCountChanged = new Adiamor.base.SubjectHelper();
	/**
	 * Fires when data is retrieved from the server.
	 */
	this.OnDataReady = new Adiamor.base.SubjectHelper();
};

Adiamor.lang.extend(Adiamor.data.JsonDataView, Adiamor.base.Object);

/**
 * Initializes the datasource.
 */
Adiamor.data.JsonDataView.prototype.initialize = function(values) 
{
	this.flush();

	/**
	 * Associative array of parameters to be sent to the server.
	 */
	this.params = {};
	
	/**
	 * The url of the handler on the server that returns data to the client.
	 */
	this.getHandler = "";

	/**
	 * The pool for server requests.
	 */
	this.ajaxCallbackPool = new Adiamor.ajax.HttpRequestPool();

	/**
	 * Specifies if the communication with the server is synchronous or asynchronous.
	 */
	this.async = true;

	this.setValues(values);
};

/**
 * Loads a JavaScript Array into the JsonDataView.
 * @param {Array} oData Array of data.
 */
Adiamor.data.JsonDataView.prototype.initializeData = function(oData)
{
	this.data = oData;
};

/**
 * Replaces the current data with new data.
 * @param {Array} oData Array of data.
 */
Adiamor.data.JsonDataView.prototype.replaceData = function(oData)
{
	this.initializeData(oData);
};

/**
 * Takes data from the server and merges it with the current data on the client.
 * @param {Array} oData Array of data. There must be an XI field specified in the fieldMap hash to indicate the index field.
 */
Adiamor.data.JsonDataView.prototype.mergeData = function(oData)
{
	if (oData[0] == null)
	{
		this.data = [];
		return;
	}
    var startXi = oData[0][this.fieldMap.xi];
    this.data[startXi] = "";

	var remove = 0;
	var len = oData.length;
	for (var i=0; i<len; i++)
	{
		if (oData[i] != null) { remove = 1; }
		else { remove = 0; }

	    this.data.splice(oData[i][this.fieldMap.xi], remove, oData[i]);
	}
};

Adiamor.data.JsonDataView.prototype.flush = function()
{
	this.data = [];
};
/**
 * Returns the requested record from the JsonDataView.
 * @param {Number} index The index of the requested record in the JsonDataView.
 * @returns {Array} Returns the Array from the JsonDataView.
 */
Adiamor.data.JsonDataView.prototype.getRecord = function(index)
{
	var data = this.data[index];
	return data;
};

/**
 * Sets the number of rows that are in the remote datasource 
 */
Adiamor.data.JsonDataView.prototype.setRemoteRowCount = function(rows)
{
	var previousCount = this.remoteRowCount;
	this.remoteRowCount = rows;
	// This needs to be uncommented otherwise requests for data from the 
	// same dataset will cause the row count to change and the grid to clear.
  	if (this.remoteRowCount != previousCount || this.remoteRowCount == 0) { this.OnRowCountChanged.notify(rows); }
};
/**
 * Gets the number of rows that are in the remote datasource 
 * Note: We consider adding rows locally to increase the remote datasource size even if they haven't been saved yet. Same true for deletes
 * @returns {int}
 */
Adiamor.data.JsonDataView.prototype.getRemoteRowCount = function()
{
	return this.remoteRowCount;
};
/**
 * Returns the number of rows that are actually in the local recordset.
 * @returns {int}
 */
Adiamor.data.JsonDataView.prototype.getRows = function()
{
	return this.data.length;
};

/*
 * Capitalizes the first letter of a string
 * @param {String} obj The string which should be adjusted
 */
function capitalizeMe(obj) {       
        newVal = '';
        obj = obj.split(' ');
        for(var c=0; c < obj.length; c++) {
            newVal += obj[c].substring(0,1).toUpperCase() +
			obj[c].substring(1,obj[c].length);
        }
        return newVal;
}

/**
 * Retrieves a mapped value from the g_mappings array for the specified row and column indexes.
 * @param {Int} val The value for the data to be mapped from.
 * @param {Int} col The index of the col for the data to be mapped from.
 */
var getMappedValueByPosition = function(val, col)
{
	var colMappings = g_mappings[col];
	
	if (colMappings != null)
	{
		var mappedVal = colMappings[val];
		return mappedVal;
	}
	return null;
};

/**
 * Makes a request to the server for data.
 * @param {Function} callback The function that is executed when the request is completed.
 * @param {Function} errorCallback The function that is executed when the request is in error.
 * @param {Object} params An associative array of name/value pairs that is sent to the server in the querystring.
 */
Adiamor.data.JsonDataView.prototype.get = function(callback, errorCallback, params)
{
	this.errorCallback = errorCallback;

	var postData = '';
	if(document.getElementById('affinityinit') != null)
	{
		var index=0;
		
		for (var i=0; i<g_checkboxes.length; i++)
		{
			var g_cb = g_checkboxes[i];
			var n = g_cb.name;
			
			if (n == "round") { g_diamondData.setParam('shape_'+n,g_inverseMappings.Shape[n]); }
			else { g_diamondData.setParam('shape_'+n); }
		}	
		
		for (var name in this.params)
		{
			var column = capitalizeMe(name.substring(0, name.indexOf("_")));
			
			if(column == "Cut" || column == "Shape" || name == "sortcol" || name == "sortdir" || name == "start" || name == "page_size")
			{
				if(name == "cut_low")
				{
					if (this.params.hasOwnProperty(name)) {
						this.params[name] = 4;
						postData += escape(name) + "=" + escape(this.params[name]) + "&";
					}
				}
				else if(name == "cut_high")
				{
					if (this.params.hasOwnProperty(name)) {
						this.params[name] = 5;
						postData += escape(name) + "=" + escape(this.params[name]) + "&";
					}
				}
				else
				{
					if (this.params.hasOwnProperty(name)) {
						postData += escape(name) + "=" + escape(this.params[name]) + "&";
					}
				}
			}
			else
			{
				if (this.params.hasOwnProperty(name)) {
					this.params[name] = null;
				}	
			}
			index++;
		}
	}
	else
	{
		var shapes = '';
		for (var name in this.params)
		{
			if (this.params.hasOwnProperty(name)) {
				postData += escape(name) + "=" + escape(this.params[name]) + "&";
				var column = capitalizeMe(name.substring(0, name.indexOf("_")));
				
				if(column == "Shape")
				{
					pageTracker._trackEvent('Diamond Searches', 'Shape Search', capitalizeMe(name.substring(name.indexOf("_")+1)), 1);
				}	
				else if(column == "Price" || column == "Carat" || column == "Depth" || column == "Size" || column == "Table" || column == "Sortcol")
				{
					pageTracker._trackEvent('Diamond Searches', capitalizeMe(name)+' Search', this.params[name], 1);
				}	
				else if(column == "Color" || column == "Clarity" || column == "Fluor" || column == "Polish" || column == "Sym")
				{
					if(name.substring(name.indexOf("_")+1) == "high")
					{
						pageTracker._trackEvent('Diamond Searches', capitalizeMe(name)+' Search', getMappedValueByPosition(this.params[name]-1, column), 1);
					}	
					else
					{
						pageTracker._trackEvent('Diamond Searches', capitalizeMe(name)+' Search', getMappedValueByPosition(this.params[name], column), 1);
					}	
				}	
				else if(column == "Cut")
				{
					var val = this.params[name];
					if(name.substring(name.indexOf("_")+1) == "high")
					{
						val--;
					}	
					
					if(val == "0")
					{
						pageTracker._trackEvent('Diamond Searches', 'Cut Search', 'Fair', 1);
					}	
					else if(val == "1")
					{
						pageTracker._trackEvent('Diamond Searches', 'Cut Search', 'Good', 1);
					}	
					else if(val == "2")
					{
						pageTracker._trackEvent('Diamond Searches', 'Cut Search', 'Very Good', 1);
					}	
					else if(val == "3")
					{
						pageTracker._trackEvent('Diamond Searches', 'Cut Search', 'Premium', 1);
					}	
					else if(val == "4")
					{
						pageTracker._trackEvent('Diamond Searches', 'Cut Search', 'Ideal', 1);
					}
				}				
			}	
		}
	}
	postData = postData.substring(0, postData.length-1);

	var ajaxCallback = this.ajaxCallbackPool.reserve();

	ajaxCallback.handler = this.getHandler;
	ajaxCallback.OnPostComplete.subscribe(this.getComplete, this);
	ajaxCallback.async = this.async;
	ajaxCallback.responseType = "text";
	ajaxCallback.params = {'params':this.params, 'requestObject':ajaxCallback, 'source':this, 'callback':callback};

	return ajaxCallback.post(postData);
};

/**
 * Sets the getHandler url and parses out / preserves any querystring parameters.
 */
Adiamor.data.JsonDataView.prototype.setGetHandler = function(getHandler, preserve)
{
	var getHandlerArray = getHandler.split('?');
	var paramArray = getHandlerArray.length == 2 ? getHandlerArray[1].split('&') : [];
	if (preserve == null || !preserve) { this.params = {}; }
	for (var i=0; i < paramArray.length; i++)
	{
		var pair = paramArray[i].split('=');
		this.params[unescape(pair[0])] = unescape(pair[1]);
	}

	this.getHandler = getHandlerArray[0];	
};

/**
 * Sets a single name value pair to be sent to the server.
 */
Adiamor.data.JsonDataView.prototype.setParam = function(name, value)
{
	if (value == null) { delete this.params[name]; }
	else { this.params[name] = value; }
};


/**
 * Retrieves a mapped value from the g_mappings array for the specified row and column indexes.
 * @param {Int} row The index of the row for the data to be mapped from.
 * @param {Int} col The index of the col for the data to be mapped from.
 */
Adiamor.data.JsonDataView.prototype.getMappedValue = function(row, col)
{
	if (this.data.length == 0)
	{
		return "";
	}
	else
	{
		if(this.data[row] != null)
		{
			var rowData = this.data[row];
			
			if(rowData[col] != null)
			{
				var val = rowData[col];

				if(g_mappings != null)
				{	
					var colMappings = g_mappings[this.Schema[col].Name];
					
					if (colMappings != null)
					{
						var mappedVal = colMappings[val];
    					if (mappedVal != null) { val = mappedVal; }
						else { val = this.Schema[col].Default; }
					}
					return val;
				}
				else { return val; }
			}
			else { return ""; }
		}
		else { return ""; }
	}
};

/**
 * Retrieves a mapped value from the g_mappings array for the specified row and column indexes.
 * @param {Int} row The index of the row for the data to be mapped from.
 * @param {Int} col The index of the col for the data to be mapped from.
 */
Adiamor.data.JsonDataView.prototype.getMappedValueCut = function(row, col)
{
	if (this.data.length == 0)
	{
		return "";
	}
	else
	{
		if(this.data[row] != null)
		{
			var rowData = this.data[row];
			
			if(rowData[col] != null)
			{
				var val = rowData[col];

				if(g_mappings != null)
				{	
					var colMappings = g_mappings[this.Schema[col].Name+"1"];
					
					if (colMappings != null)
					{
						var mappedVal = colMappings[val];
    					if (mappedVal != null) { val = mappedVal; }
						else { val = this.Schema[col].Default; }
					}
					return val;
				}
				else { return val; }
			}
			else { return ""; }
		}
		else { return ""; }
	}
};

/**
 * Disposes of the DataView.
 */
Adiamor.data.JsonDataView.prototype.dispose = function()
{
	Adiamor.data.JsonDataView.base.dispose.call(this);
};
/**
 * A paging datasource based on a JsonDataView.
 * @extends {Adiamor.data.JsonDataView}
 */
Adiamor.data.PagedJsonDataView = function()
{
	Adiamor.data.PagedJsonDataView.baseConstructor.apply(this, arguments);

    this.dataCache = new Adiamor.collections.Map(-1,-1); //Note: applies only to mode=caching
	this.requestCache = new Adiamor.collections.Map(-1,-1);	
	this.requestQueue = [];
};

Adiamor.lang.extend(Adiamor.data.PagedJsonDataView, Adiamor.data.JsonDataView);

/**
 * Checks to see if the the records are already located in the datasource.
 */
Adiamor.data.PagedJsonDataView.prototype.inCache = function(start, pageSize)
{
	var firstRow = start, lastRow = start + pageSize - 1;

	// If we know the last row and are checking the cache past the end of
	// the data there is no way the data will be in cache so reduce the lastRow
	// to the lastKnownRow value instead.
	var lastKnownRow = this.getRemoteRowCount()-1;

	if (lastKnownRow < lastRow)
	{
		lastRow = lastKnownRow;
	}

	var cacheGaps = this.dataCache.gaps(firstRow, lastRow);
	var numCacheGaps = cacheGaps.length;
	return (numCacheGaps == 0 && lastKnownRow != -1);
};


/**
 * Makes a request to the server for data. Before making the request, it will check if the data is already on the client or not.
 * The params argument must have a start and a page_size property for it to work correctly.
 * @param {Function} callback The function that is executed when the request is completed.
 * @param {Function} errorCallback The function that is executed when the request is in error.
 * @param {Object} params An associative array of name/value pairs that is sent to the server in the querystring.
 */
Adiamor.data.PagedJsonDataView.prototype.get = function(callback, errorCallback, params)
{
	// ensure that the Start and PageSize are valid
	if (typeof this.params.start != "number" || typeof this.params.page_size != "number") { return; }

    var firstRow = this.params.start;
	var lastRow = firstRow + this.params.page_size - 1;

	var cacheGaps = this.dataCache.gaps(firstRow, lastRow);
	var numCacheGaps = cacheGaps.length;

	if (numCacheGaps > 0)
	{
		for (var i=0; i<numCacheGaps; i++)
		{
			var low = cacheGaps[i].low;
			var high = cacheGaps[i].high;

			var requestGaps = this.requestCache.gaps(low,high);

			//	There is a request outstanding for this data already ...
			if (requestGaps.length == 0)
			{
				var funcref = Adiamor.lang.close(this, this.get, arguments);
				this.requestQueue.push(funcref);
				return;
			}

			this.requestCache.insert(low,high);
//debugger;

//return this.getComplete({response:'{rows:1,data:[[0,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]]}',params:{pageSize:1,callback:callback}});

			// Return the result from the getRequest as it may be synchronous if no callback is specified.
        	Adiamor.data.PagedJsonDataView.base.get.apply(this, arguments);
		}
	}
	else
	{
		return this.data.slice(firstRow, lastRow);
	}
};

/**
 * This function is executed as the callback function when data has returned from the paging request.
 * This method will check the response for validity, check the data format for backwards compatibility, 
 * create a new XML doc if necessary, adjust the row #'s (xi's), remove the range from the request cache,
 * update the cachemap.
 * @param {Object} args The data that is returned from the server such as {"data":[...],"rows":0}
 */
Adiamor.data.PagedJsonDataView.prototype.getComplete = function(args)
{
	var xd = args.response;
	var getCompleteEvtArgs = args.params;
	
	var query = "?";
	
	if(getCompleteEvtArgs.params.shape_round != null)
	{	query += "shape_round=" + getCompleteEvtArgs.params.shape_round + "&";}
	if(getCompleteEvtArgs.params.shape_princess != null)
	{	query += "shape_princess=" + getCompleteEvtArgs.params.shape_princess + "&";}
	if(getCompleteEvtArgs.params.shape_emerald != null)
	{	query += "shape_emerald=" + getCompleteEvtArgs.params.shape_emerald + "&";}
	if(getCompleteEvtArgs.params.shape_marquise != null)
	{	query += "shape_marquise=" + getCompleteEvtArgs.params.shape_marquise + "&";}
	if(getCompleteEvtArgs.params.shape_heart != null)
	{	query += "shape_heart=" + getCompleteEvtArgs.params.shape_heart + "&";}
	if(getCompleteEvtArgs.params.shape_cushion != null)
	{	query += "shape_cushion=" + getCompleteEvtArgs.params.shape_cushion + "&";}
	if(getCompleteEvtArgs.params.shape_asscher != null)
	{	query += "shape_asscher=" + getCompleteEvtArgs.params.shape_asscher + "&";}
	if(getCompleteEvtArgs.params.shape_oval != null)
	{	query += "shape_oval=" + getCompleteEvtArgs.params.shape_oval + "&";}
	if(getCompleteEvtArgs.params.shape_radiant != null)
	{	query += "shape_radiant=" + getCompleteEvtArgs.params.shape_radiant + "&";}
	if(getCompleteEvtArgs.params.shape_pear != null)
	{	query += "shape_pear=" + getCompleteEvtArgs.params.shape_pear + "&";}
	if(getCompleteEvtArgs.params.diamond != null)
	{	query += "diamond=" + getCompleteEvtArgs.params.diamond + "&";}
	if(getCompleteEvtArgs.params.price_low != null)
	{	query += "price_low=" + getCompleteEvtArgs.params.price_low + "&";}
	if(getCompleteEvtArgs.params.price_high != null)
	{	query += "price_high=" + getCompleteEvtArgs.params.price_high + "&";}
	if(getCompleteEvtArgs.params.carat_low != null)
	{	query += "carat_low=" + getCompleteEvtArgs.params.carat_low + "&";}
	if(getCompleteEvtArgs.params.carat_high != null)
	{	query += "carat_high=" + getCompleteEvtArgs.params.carat_high + "&";}
	if(getCompleteEvtArgs.params.cut_low != null)
	{	query += "cut_low=" + getCompleteEvtArgs.params.cut_low + "&";}
	if(getCompleteEvtArgs.params.cut_high != null)
	{	query += "cut_high=" + getCompleteEvtArgs.params.cut_high + "&";}
	if(getCompleteEvtArgs.params.color_low != null)
	{	query += "color_low=" + getCompleteEvtArgs.params.color_low + "&";}
	if(getCompleteEvtArgs.params.color_high != null)
	{	query += "color_high=" + getCompleteEvtArgs.params.color_high + "&";}
	if(getCompleteEvtArgs.params.clarity_low != null)
	{	query += "clarity_low=" + getCompleteEvtArgs.params.clarity_low + "&";}
	if(getCompleteEvtArgs.params.clarity_high != null)
	{	query += "clarity_high=" + getCompleteEvtArgs.params.clarity_high + "&";}
	if(getCompleteEvtArgs.params.polish_low != null)
	{	query += "polish_low=" + getCompleteEvtArgs.params.polish_low + "&";}
	if(getCompleteEvtArgs.params.polish_high != null)
	{	query += "polish_high=" + getCompleteEvtArgs.params.polish_high + "&";}
	if(getCompleteEvtArgs.params.sym_low != null)
	{	query += "sym_low=" + getCompleteEvtArgs.params.sym_low + "&";}
	if(getCompleteEvtArgs.params.sym_high != null)
	{	query += "sym_high=" + getCompleteEvtArgs.params.sym_high + "&";}
	if(getCompleteEvtArgs.params.depth_low != null)
	{	query += "depth_low=" + getCompleteEvtArgs.params.depth_low + "&";}
	if(getCompleteEvtArgs.params.depth_high != null)
	{	query += "depth_high=" + getCompleteEvtArgs.params.depth_high + "&";}
	if(getCompleteEvtArgs.params.table_low != null)
	{	query += "table_low=" + getCompleteEvtArgs.params.table_low + "&";}
	if(getCompleteEvtArgs.params.table_high != null)
	{	query += "table_high=" + getCompleteEvtArgs.params.table_high + "&";}
	if(getCompleteEvtArgs.params.size_low != null)
	{	query += "size_low=" + getCompleteEvtArgs.params.size_low + "&";}
	if(getCompleteEvtArgs.params.size_high != null)
	{	query += "size_high=" + getCompleteEvtArgs.params.size_high + "&";}
	if(getCompleteEvtArgs.params.fluor_low != null)
	{	query += "fluor_low=" + getCompleteEvtArgs.params.fluor_low + "&";}
	if(getCompleteEvtArgs.params.fluor_high != null)
	{	query += "fluor_high=" + getCompleteEvtArgs.params.fluor_high + "&";}
	if(getCompleteEvtArgs.params.page_size != null)
	{	query += "page_size=" + getCompleteEvtArgs.params.page_size + "&";}
		
	document.getElementById("imgRSS").href = "createRSS.aspx"+query;
	document.getElementById("txtRSS").href = "createRSS.aspx"+query;
	
	document.getElementById("imgExcel").href = "createexcel.aspx"+query;
	document.getElementById("txtExcel").href = "createexcel.aspx"+query;
	
	document.getElementById("imgEmail").href = "diamond-search-email.aspx"+query;
	document.getElementById("txtEmail").href = "diamond-search-email.aspx"+query;

	if (null == xd)
	{
		if (this.errorCallback)	
		{
			this.errorCallback.call(this.context);
		}
		return getCompleteEvtArgs;
	}
	
	var data;
	try {
		xd = eval('('+xd+')');
    	data = xd.data;
	}
	catch(e)
	{
		xd = {'data':[],'rows':0};
		data = xd.data;
	}
	getCompleteEvtArgs.payload = xd;
	
	this.setRemoteRowCount(xd.rows);

	// This gets set to the index of the last row that was returned.
	var lastRowReturned;
	// This gets set to the number of rows returned.
	var numRowsReturned = data.length;
	var startXi = 0;
	var endXi = -1;
	
	if (0 < numRowsReturned)
	{
		startXi = data[0][this.fieldMap.xi];
		endXi = data[data.length-1][this.fieldMap.xi];

		this.dataCache.insert(startXi, endXi);
	}
	else
	{
		getCompleteEvtArgs.pageSize=0;
		var pnlNoResults = $('no-results');
		
		if(xd.suggestions != null)
		{
			var htmString = "";
			var tempMin = "";
			var tempMax = "";
			htmString = '<div style="width: 386px; height: 74px; background-image: url(../images/adiamor_t/noresults.gif); position: absolute; top: 100px; left: 183px; padding-top: 15px; padding-right: 15px; padding-left: 8px;">';
			if(xd.suggestions.price != null)
			{
				if(xd.suggestions.price.min < 250)
				{	xd.suggestions.price.min = 250; }
				if(xd.suggestions.price.max > 500000)
				{	xd.suggestions.price.max = 500000; }
					
				htmString += "No results were found.  However, if you increase your search to ";
				htmString += "include a price range of $" + xd.suggestions.price.min + " to $" + xd.suggestions.price.max + ", the search will ";
				htmString += "return " + xd.suggestions.rows + " results.  <a href=\"javascript:runSuggest(0,"+xd.suggestions.price.min+","+xd.suggestions.price.max+")\">Click here</a> to do so, ";
				htmString += "or give us a call at 1-877-627-5094.";
				htmString += "</div>";
				pnlNoResults.innerHTML = htmString;
			}
			else if(xd.suggestions.carat != null)
			{
				if(xd.suggestions.carat.min < 0.30)
				{	xd.suggestions.carat.min = 0.30; }
				if(xd.suggestions.carat.max > 15.0)
				{	xd.suggestions.carat.max = 15.0; }
					
				htmString += "No results were found.  However, if you increase your search to ";
				htmString += "include carat weights between " + xd.suggestions.carat.min + " and " + xd.suggestions.carat.max + ", the search will ";
				htmString += "return " + xd.suggestions.rows + " results.  <a href=\"javascript:runSuggest(1,"+xd.suggestions.carat.min+","+xd.suggestions.carat.max+")\">Click here</a> to do so, ";
				htmString += "or give us a call at 1-877-627-5094.";
				htmString += "</div>";
				pnlNoResults.innerHTML = htmString;
			}
			else if(xd.suggestions.clar != null)
			{
				tempMin = g_mappings.Clar[xd.suggestions.clar.min];
				tempMax = g_mappings.Clar[xd.suggestions.clar.max];
				
				if(xd.suggestions.clar.min > 37)
				{	xd.suggestions.clar.min = 37; }
				if(xd.suggestions.clar.max < 31)
				{	xd.suggestions.clar.max = 31; }
					
				htmString += "No results were found.  However, if you increase your search to ";
				htmString += "include clarity grades between " + tempMin + " and " + tempMax + ", the search will ";
				htmString += "return " + xd.suggestions.rows + " results.  <a href=\"javascript:runSuggest(4,"+xd.suggestions.clar.min+","+xd.suggestions.clar.max+")\">Click here</a> to do so, ";
				htmString += "or give us a call at 1-877-627-5094.";
				htmString += "</div>";
				pnlNoResults.innerHTML = htmString;
			}
			else if(xd.suggestions.color != null)
			{
				tempMin = g_mappings.Color[xd.suggestions.color.min];
				tempMax = g_mappings.Color[xd.suggestions.color.max];
				
				if(xd.suggestions.color.min > 29)
				{	xd.suggestions.color.min = 29; }
				if(xd.suggestions.color.max < 22)
				{	xd.suggestions.color.max = 22; }
					
				htmString += "No results were found.  However, if you increase your search to ";
				htmString += "include color grades between " + tempMin + " and " + tempMax + ", the search will ";
				htmString += "return " + xd.suggestions.rows + " results.  <a href=\"javascript:runSuggest(3,"+xd.suggestions.color.min+","+xd.suggestions.color.max+")\">Click here</a> to do so, ";
				htmString += "or give us a call at 1-877-627-5094.";
				htmString += "</div>";
				pnlNoResults.innerHTML = htmString;
			}
			else
			{
				pnlNoResults.innerHTML = "No results were found. Use the sliders above to broaden your search<BR>, give us a call at 1-877-627-5094 or click  <a href=\"javascript:clearSearch();\">here</a> to reset your search.</div>";
			}	
		}
	}

	getCompleteEvtArgs.numRowsReturned = numRowsReturned;
	getCompleteEvtArgs.lastRowReturned = endXi;

	this.mergeData(xd.data);

	this.requestCache.remove(startXi, endXi);

	if (null != getCompleteEvtArgs.requestObject)
	{
		//	We need to check that the ajaxCallback is not null before relaesing it
		//	It could be the case the ajaxCallback object was not needed because the
		//	data was already present in the DataSource
		this.ajaxCallbackPool.release(getCompleteEvtArgs.requestObject);
	}

//TODO: What to do with this ...
//	this.executeRequests();

	this.OnDataReady.notify(getCompleteEvtArgs);

	if (null != getCompleteEvtArgs.callback)
	{
		getCompleteEvtArgs.callback.call(this, getCompleteEvtArgs);
		getCompleteEvtArgs = null;
	}
	else
	{
		// return the getCompleteEvtArgs to the caller ... 
		return getCompleteEvtArgs;
	}
};

function checkNonRound()
{
	var bool = false;
	if(document.getElementById("princess-qr_cb").checked) { bool=true; }
	if(document.getElementById("emerald-qr_cb").checked) { bool=true; }
	if(document.getElementById("marquise-qr_cb").checked) { bool=true; }
	if(document.getElementById("heart-qr_cb").checked) { bool=true; }
	if(document.getElementById("pear-qr_cb").checked) { bool=true; }
	if(document.getElementById("radiant-qr_cb").checked) { bool=true; }
	if(document.getElementById("oval-qr_cb").checked) { bool=true; }
	if(document.getElementById("asscher-qr_cb").checked) { bool=true; }
	if(document.getElementById("cushion-qr_cb").checked) { bool=true; }		
	return bool;
}

function checkNonAffinity()
{
	var bool = false;
	//if(document.getElementById("princess-qr_cb").checked) { bool=true; }
	//if(document.getElementById("emerald-qr_cb").checked) { bool=true; }
	if(document.getElementById("marquise-qr_cb").checked) { bool=true; }
	if(document.getElementById("heart-qr_cb").checked) { bool=true; }
	if(document.getElementById("pear-qr_cb").checked) { bool=true; }
	if(document.getElementById("radiant-qr_cb").checked) { bool=true; }
	if(document.getElementById("oval-qr_cb").checked) { bool=true; }
	//if(document.getElementById("asscher-qr_cb").checked) { bool=true; }
	if(document.getElementById("cushion-qr_cb").checked) { bool=true; }		
	return bool;
}

function checkNumShapes()
{
	var num = 0;
	if(document.getElementById("round-qr_cb").checked) { num++; }
	if(document.getElementById("princess-qr_cb").checked) { num++; }
	if(document.getElementById("emerald-qr_cb").checked) { num++; }
	if(document.getElementById("marquise-qr_cb").checked) { num++; }
	if(document.getElementById("heart-qr_cb").checked) { num++; }
	if(document.getElementById("pear-qr_cb").checked) { num++; }
	if(document.getElementById("radiant-qr_cb").checked) { num++; }
	if(document.getElementById("oval-qr_cb").checked) { num++; }
	if(document.getElementById("asscher-qr_cb").checked) { num++; }
	if(document.getElementById("cushion-qr_cb").checked) { num++; }		
	return num;
}

/**
 * Global variable for keepin track of whether or not the small sliders have
 * been created and updated with the extents returned from the server for the main sliders.
 */
var g_miniSlidersSync = false;

/**
 * Updates the mini and main sliders so they have the same values.
 * This occurs when the user goes between the first and second pages.
 */
function updateSliders(dir)
{
	var src = g_mainSliders;
	var dest = g_miniSliders;

	if (dir)
	{
		src = g_miniSliders;
		dest = g_mainSliders;
	}
	
	if(document.getElementById("round-qr_cb").checked || document.getElementById("princess-qr_cb").checked ||
		document.getElementById("emerald-qr_cb").checked || document.getElementById("asscher-qr_cb").checked)
	{
		if(checkNonAffinity())
		{
			$('label-size').style.display="block";
			
			$('ntb-sliderAdiamor__uid__11').className="slider-bg-repeat slider-element slider-cut-mini";
			$('ntb-sliderAdiamor__uid__6').className="slider-bg-repeat slider-element slider-cut";
		}
		else
		{
			$('label-size').style.display="none";
			
			$('ntb-sliderAdiamor__uid__11').className="slider-bg-repeat slider-element slider-cut-mini-both";
			$('ntb-sliderAdiamor__uid__6').className="slider-bg-repeat slider-element slider-cut-both";
		}
		$('cutmarkings').src="http://www.adiamor.com/images/Adiamor_T/cutmarkings.gif";
	}
	else
	{
		$('label-size').style.display="block";
			
		$('ntb-sliderAdiamor__uid__11').className="slider-bg-repeat slider-element slider-cut-mini-noround";
		$('ntb-sliderAdiamor__uid__6').className="slider-bg-repeat slider-element slider-cut-noround";
		$('cutmarkings').src="http://www.adiamor.com/images/Adiamor_T/cutmarkings2.gif";
	}

	for (var i=0; i<g_miniSliders.length; i++)
	{
		dest[i].Slider.Ticks = src[i].Slider.Ticks;
		dest[i].Ticks = src[i].Ticks;
		
		dest[i].Slider.Max = src[i].Slider.Max;
		dest[i].Slider.Min = src[i].Slider.Min;
		
		dest[i].Slider.setMinValue(src[i].Slider.getMinValue());
		dest[i].Slider.setMaxValue(src[i].Slider.getMaxValue());
	}
	
	if (dir == 0)
	{
		g_miniSlidersSync = true;
	}
	
	if(checkNonRound())
	{
		$('label-size').style.display="block";
	}
	else
	{
		$('label-size').style.display="none";
	}
}

/**
 * The DataView containing all the diamond data from the server
 */
var g_diamondData;

/**
 * Updates the parameters on the JsonDataView such that all the correct query parameters are sent to the server.
 */
 
function updateDataViewSliderParams(evtArgs, name)
{
	name = name.replace('-mini', '');
	var minValue = evtArgs.slider.getMinValue();
	var maxValue = evtArgs.slider.getMaxValue();
	
	if (evtArgs.slider.Discrete)
	{
		minValue = Math.floor(minValue);
		maxValue = Math.floor(maxValue);
		
		/*if(evtArgs.slider.ClassPostFix == "-small")
		{
			minValue--;
			maxValue--;
		}*/
	}
	else if(evtArgs.slider.TooltipEnabled)
	{
		if(evtArgs.slider.LeftTooltip == null)
		{
			minValue = evtArgs.slider.BottomTooltip.m_HtmlElementHandle.value.replace(/[^0-9|\.]/gi,'');
			maxValue = evtArgs.slider.TopTooltip.m_HtmlElementHandle.value.replace(/[^0-9|\.]/gi,'');
		}
		else
		{
			minValue = evtArgs.slider.LeftTooltip.m_HtmlElementHandle.value.replace(/[^0-9|\.]/gi,'');
			maxValue = evtArgs.slider.RightTooltip.m_HtmlElementHandle.value.replace(/[^0-9|\.]/gi,'');
		}	
	}
	// clear the diamond param since this is an update due to a slider.
	//g_diamondData.setParam('diamond','1');

	//Set the params for the particular slider on the dataview
	g_diamondData.setParam(name + '_low', minValue);
	g_diamondData.setParam(name + '_high', maxValue);

	g_activeSlider = null;
}

function runSuggest(row, min, max)
{
	var sliders = g_mainSliders;
	
	sliders[row].Slider.setMinValue(min);
	sliders[row].Slider.setMaxValue(max);
	
	updateSliders(0);
	updateSliders(1);
	updateDataViewSliderParams({"slider":sliders[row].Slider}, sliders[row].name);
	sliders[row].Slider.OnRangeChanged.notify({'slider':sliders[row].Slider});
}

function clearSearch()
{
	hideElement($('gridlist-overlay'));
	
	var sliders = g_mainSliders;
	
	for (i=0; i<sliders.length; i++)
	{
		sliders[i].Slider.setMinValue(sliders[i].sliderParams.Min);
		sliders[i].Slider.setMaxValue(sliders[i].sliderParams.Max);
		updateDataViewSliderParams({"slider":sliders[i].Slider}, sliders[i].name);
	}
	
	sliders[sliders.length-1].Slider.OnRangeChanged.notify({'slider':sliders[sliders.length-1].Slider});
	
	sliders = g_smallSliders;
	for (i=0; i<sliders.length; i++)
	{
		if(sliders[i].Slider.Discrete)
		{
			sliders[i].Slider.setMinValue(sliders[i].sliderParams.Min);
			sliders[i].Slider.setMaxValue(sliders[i].sliderParams.Max);
		}
		else
		{
			sliders[i].Slider.setMinValue(sliders[i].sliderParams.Min);
			sliders[i].Slider.setMaxValue(sliders[i].sliderParams.Max);
		}
		updateDataViewSliderParams({"slider":sliders[i].Slider}, sliders[i].name);
	}
	
	sliders[sliders.length-1].Slider.OnRangeChanged.notify({'slider':sliders[sliders.length-1].Slider});
	
	if(checkNonRound())
	{}
	else
	{
		document.getElementById("round-qr_cb").checked = true;
		document.getElementById("round_cb").checked = true;
		document.getElementById("round-qr_img").src = g_imagePath+'round_d.gif';
		document.getElementById("round_img").src = g_imagePath+'round_d.gif';
		g_diamondData.setParam('shape_round', 16);
	}
	
	updateSliders(0);
	updateSliders(1);
}

/**
 * This is used by the DataView when there are multiple requests for the same data such that 
 * only one request is made to the server yet all the request callbacks are executed once the data is ready.
 */
Adiamor.data.PagedJsonDataView.prototype.executeRequests = function() 
{
	// Execute all the functions on the request queue, then reset the queue.
	var oldRequests = this.requestQueue;
	this.requestQueue = [];
	for (var i=0; i < oldRequests.length; i++)
	{
		oldRequests[i].call();
	}
};

/**
 * Clears the cache.
 */
Adiamor.data.PagedJsonDataView.prototype.flush = function()
{
	this.requestCache.flush();
	this.dataCache.flush();
	this.requestQueue = [];
	Adiamor.data.PagedJsonDataView.base.flush.call(this);
};

/**
 * Dispose of the PagedJsonDataView.
 */
Adiamor.data.PagedJsonDataView.prototype.dispose = function()
{
	this.requestCache.flush();
	this.requestCache = null;
	this.requestQueue = null;
	//Adiamor.data.PagedJsonDataView.base.dispose.call(this);
};
/**************************************************************************/
/*					Adiamor.ui.Effects	     	      
/**************************************************************************/


Adiamor.lang.defineNs("Adiamor.ui");

Adiamor.ui.Effects = {};

Adiamor.ui.Effects.appearFromBottom = function(panel, options, duration, callback)
{
	if (typeof options.endTop == "undefined")
	{	options.endTop = 0; }
	if (typeof options.startTop == "undefined")
	{	options.startTop = panel.Container.offsetHeight; }

	options.deltaTop = (options.endTop - options.startTop) / (duration / Adiamor.ui.Effects.ANIMATION_INTERVAL);

	var count = 1;
	while (duration > 0)
	{
		duration -= Adiamor.ui.Effects.ANIMATION_INTERVAL;

		options.startTop = options.startTop + options.deltaTop;

		window.setTimeout(Adiamor.lang.close(panel, panel.setSurfaceTop, [eval(options.startTop)]), Adiamor.ui.Effects.ANIMATION_INTERVAL*count);
		count++;
	}
	window.setTimeout(Adiamor.lang.close(panel, panel.setSurfaceTop, [eval(options.endTop)]), Adiamor.ui.Effects.ANIMATION_INTERVAL*count);
};

Adiamor.ui.Effects.disappearFromTop = function(panel, options, duration, callback, callbackContext)
{
	if (typeof options.endTop == "undefined") {	options.endTop = panel.Container.offsetHeight; }
	if (typeof options.startTop == "undefined") { options.startTop = 0; }

	options.deltaTop = (options.endTop - options.startTop) / (duration / Adiamor.ui.Effects.ANIMATION_INTERVAL);

	var count = 1;
	while (duration > 0)
	{
		duration -= Adiamor.ui.Effects.ANIMATION_INTERVAL;

		options.startTop = options.startTop + options.deltaTop;

		window.setTimeout(Adiamor.lang.close(panel, panel.setSurfaceTop, [eval(options.startTop)]), Adiamor.ui.Effects.ANIMATION_INTERVAL*count);
		count++;
	}
	window.setTimeout(Adiamor.lang.close(panel, panel.setSurfaceTop, [eval(options.endTop)]), Adiamor.ui.Effects.ANIMATION_INTERVAL*count);
	if (callback != null)
	{
		window.setTimeout(Adiamor.lang.close(callbackContext || {}, callback, [panel]), Adiamor.ui.Effects.ANIMATION_INTERVAL*count);
	}
};

/**
 * Shrinks the given HTML DOM element to the size specified by 
 * <CODE>options</CODE> in <CODE>duration</CODE> milliseconds.
 * @param {Object} options The dimensions after shrinking <CODE>{width: <int> x, height: <int> y, left: <int> x, top: <int> y}</CODE>.
 * @param {Element} domElement The unique ID of this Pane.
 * @param {int} duration How long the effect will take.
 * @param {function} callback A function to call after shrink completes
 */
Adiamor.ui.Effects.shrink = function(options, domElements, duration, callback)
{
	var domElement = domElements[0];
	
	var deltaHeight_Doctype = 0 - parseInt("0"+Adiamor.dom.getStyle(domElement, "border-top-width"),10) - parseInt("0"+Adiamor.dom.getStyle(domElement, "border-bottom-width"),10) - 
									parseInt("0"+Adiamor.dom.getStyle(domElement, "padding-top"),10) - parseInt("0"+Adiamor.dom.getStyle(domElement, "padding-bottom"),10); 
	var deltaWidth_Doctype = 0 - parseInt("0"+Adiamor.dom.getStyle(domElement, "border-left-width"),10) - parseInt("0"+Adiamor.dom.getStyle(domElement, "border-right-width"),10) - 
									parseInt("0"+Adiamor.dom.getStyle(domElement, "padding-left"),10) - parseInt("0"+Adiamor.dom.getStyle(domElement, "padding-right"),10);

	var coords = Adiamor.html.getCoords(domElement);
	options.oldHeight = coords.height + deltaHeight_Doctype;
	if (options.up) { options.oldY = coords.y; }
	options.oldWidth = coords.width + deltaWidth_Doctype;
	if (options.left) { options.oldX = coords.x; }

	if (!(typeof(options.width) == "undefined"))
	{
		options.deltaWidth = (options.width - options.oldWidth) / (duration / Adiamor.ui.Effects.ANIMATION_INTERVAL);
	}
	else
	{
		options.width = options.oldWidth;
		options.deltaWidth = null;
	}
	
	if (!(typeof(options.height) == "undefined"))
	{
		options.deltaHeight = (options.height - options.oldHeight) / (duration / Adiamor.ui.Effects.ANIMATION_INTERVAL);
	}
	else
	{
		options.height = options.oldHeight;
		options.deltaHeight = null;
	}
	Adiamor.ui.Effects.resize(options, domElements, duration, callback);
};

/**
 * Shrinks the given HTML DOM element to the size specified by 
 * <CODE>options</CODE> in <CODE>duration</CODE> milliseconds.
 * @param {Object} options The dimensions after shrinking <CODE>{width: <int> x, height: <int> y, left: <int> x, top: <int> y}</CODE>.
 * @param {Element} domElement The unique ID of this Pane.
 * @param {int} duration How long the effect will take.
 * @param {function} callback A function to call after shrink completes
 */
Adiamor.ui.Effects.tutorial = function(options, domElements, duration, callback)
{
	var domElement = domElements[0];
	//debugger;
	var deltaHeight_Doctype = 0 - parseInt("0"+Adiamor.dom.getStyle(domElement, "border-top-width"),10) - parseInt("0"+Adiamor.dom.getStyle(domElement, "border-bottom-width"),10) - 
									parseInt("0"+Adiamor.dom.getStyle(domElement, "padding-top"),10) - parseInt("0"+Adiamor.dom.getStyle(domElement, "padding-bottom"),10); 
	var deltaWidth_Doctype = 0 - parseInt("0"+Adiamor.dom.getStyle(domElement, "border-left-width"),10) - parseInt("0"+Adiamor.dom.getStyle(domElement, "border-right-width"),10) - 
									parseInt("0"+Adiamor.dom.getStyle(domElement, "padding-left"),10) - parseInt("0"+Adiamor.dom.getStyle(domElement, "padding-right"),10);

	var coords = Adiamor.html.getCoords(domElement);
	options.oldHeight = coords.height + deltaHeight_Doctype;
	if (options.up) { options.oldY = coords.y; }
	options.oldWidth = coords.width + deltaWidth_Doctype;
	if (options.left) { options.oldX = coords.x; }

	if (!(typeof(options.width) == "undefined"))
	{
		options.deltaWidth = (options.width - options.oldWidth) / (duration / Adiamor.ui.Effects.ANIMATION_INTERVAL);
	}
	else
	{
		options.width = options.oldWidth;
		options.deltaWidth = null;
	}
	
	if (!(typeof(options.height) == "undefined"))
	{
		options.deltaHeight = (options.height - options.oldHeight) / (duration / Adiamor.ui.Effects.ANIMATION_INTERVAL);
	}
	else
	{
		options.height = options.oldHeight;
		options.deltaHeight = null;
	}
	Adiamor.ui.Effects.resize(options, domElements, duration, callback);
};

/**
 * Shrinks the given HTML DOM element to the size specified by 
 * <CODE>options</CODE> in <CODE>duration</CODE> milliseconds.
 * @param {Object} options The dimensions after shrinking <CODE>{width: <int> x, height: <int> y, left: <int> x, top: <int> y}</CODE>.
 * @param {Element} domElement The unique ID of this Pane.
 * @param {int} duration How long the effect will take.
 * @param {function} callback A function to call after shrink completes
 */
Adiamor.ui.Effects.grow = function(options, domElements, duration, callback)
{
	var domElement = domElements[0];
	
	var deltaHeight_Doctype = 0 - parseInt("0"+Adiamor.dom.getStyle(domElement, "border-top-width"),10) - parseInt("0"+Adiamor.dom.getStyle(domElement, "border-bottom-width"),10) - 
									parseInt("0"+Adiamor.dom.getStyle(domElement, "padding-top"),10) - parseInt("0"+Adiamor.dom.getStyle(domElement, "padding-bottom"),10); 
	var deltaWidth_Doctype = 0 - parseInt("0"+Adiamor.dom.getStyle(domElement, "border-left-width"),10) - parseInt("0"+Adiamor.dom.getStyle(domElement, "border-right-width"),10) - 
									parseInt("0"+Adiamor.dom.getStyle(domElement, "padding-left"),10) - parseInt("0"+Adiamor.dom.getStyle(domElement, "padding-right"),10);

	var coords = Adiamor.html.getCoords(domElement);
	options.oldHeight = coords.height + deltaHeight_Doctype;
	if (options.up) { options.oldY = coords.y; }
	options.oldWidth = coords.width + deltaWidth_Doctype;
	if (options.left) { options.oldX = coords.x; }

	if (!(typeof(options.width) == "undefined"))
	{
		options.deltaWidth = (options.width - options.oldWidth) / (duration / Adiamor.ui.Effects.ANIMATION_INTERVAL);
	}
	else
	{
		options.width = options.oldWidth;
		options.deltaWidth = null;
	}
	
	if (!(typeof(options.height) == "undefined"))
	{
		options.deltaHeight = (options.height - options.oldHeight) / (duration / Adiamor.ui.Effects.ANIMATION_INTERVAL);
	}
	else
	{
		options.height = options.oldHeight;
		options.deltaHeight = null;
	}
	Adiamor.ui.Effects.resize(options, domElements, duration, callback);
};

/**
 * Shrinks the given DOM element to zero height and hides it.
 */
Adiamor.ui.Effects.shrinkAndHide = function(domElement, duration, callback)
{
	if (!Adiamor.ui.Effects.isHidden(domElement))
	{
		Adiamor.ui.Effects.shrink({height:0}, domElement, duration, function(){Adiamor.ui.Effects.hide(domElement); if (callback) { callback(); }});
	}
};

/**
 * Grows the given HTML DOM element to its <CODE>automatic</CODE> height.
 * @param {Element} domElement The unique ID of this Pane.
 * @param {int} duration How long the effect will take.
 * @param {function} callback A function to call after shrink completes
 */
Adiamor.ui.Effects.growToAutomatic = function(domElement, duration, callback)
{
	var options = {};
	// We assume that the domElement is hidden using Effects.hide
	
	var elementHeight = domElement.offsetHeight - parseInt("0"+Adiamor.dom.getStyle(domElement, "border-top-width"),10) - parseInt("0"+Adiamor.dom.getStyle(domElement, "border-bottom-width"),10) - 
		parseInt("0"+Adiamor.dom.getStyle(domElement, "padding-top"),10) - parseInt("0"+Adiamor.dom.getStyle(domElement, "padding-bottom"),10);

	var elementWidth = domElement.offsetWidth - parseInt("0"+Adiamor.dom.getStyle(domElement, "border-left-width"),10) - parseInt("0"+Adiamor.dom.getStyle(domElement, "border-right-width"),10) - 
		parseInt("0"+Adiamor.dom.getStyle(domElement, "padding-left"),10) - parseInt("0"+Adiamor.dom.getStyle(domElement, "padding-right"),10);

	//options.height = elementHeight;
	options.width = 272;//elementWidth;
	
	Adiamor.ui.Effects.grow(options, [domElement], duration, function() { domElement.style.height = ""; domElement.style.width = ""; if (callback) { callback(); }});	
};

/**
 * Grows the given HTML DOM element to its <CODE>automatic</CODE> height.
 * @param {Element} domElement The unique ID of this Pane.
 * @param {int} duration How long the effect will take.
 * @param {function} callback A function to call after shrink completes
 */
Adiamor.ui.Effects.shrinkToAutomatic = function(domElement, duration, callback)
{
	var options = {};
	// We assume that the domElement is hidden using Effects.hide
	
	var elementHeight = domElement.offsetHeight - parseInt("0"+Adiamor.dom.getStyle(domElement, "border-top-width"),10) - parseInt("0"+Adiamor.dom.getStyle(domElement, "border-bottom-width"),10) - 
		parseInt("0"+Adiamor.dom.getStyle(domElement, "padding-top"),10) - parseInt("0"+Adiamor.dom.getStyle(domElement, "padding-bottom"),10);

	var elementWidth = domElement.offsetWidth - parseInt("0"+Adiamor.dom.getStyle(domElement, "border-left-width"),10) - parseInt("0"+Adiamor.dom.getStyle(domElement, "border-right-width"),10) - 
		parseInt("0"+Adiamor.dom.getStyle(domElement, "padding-left"),10) - parseInt("0"+Adiamor.dom.getStyle(domElement, "padding-right"),10);

	//options.height = elementHeight;
	options.width = 17;//elementWidth;
	
	Adiamor.ui.Effects.shrink(options, [domElement], duration, function() { domElement.style.height = ""; domElement.style.width = ""; if (callback) { callback(); }});	
};

/**
 * A helper function that resizes <CODE>domElement</CODE> over a given duration by deltas given by 
 * <CODE>options.deltaWidth</CODE> and <CODE>options.deltaHeight</CODE> every 
 * <CODE>Adiamor.ui.Effects.ANIMATION_INTERVAL</CODE> milliseconds.  Once complete, the function reference 
 * <CODE>callback</CODE> is called. 
 * @param {Object} options
 * @param {Element} domElement
 * @param {int} duration
 * @param {Function} callback
 * @private
 */
Adiamor.ui.Effects.resize = function(options, domElements, duration, callback)
{
	duration -= Adiamor.ui.Effects.ANIMATION_INTERVAL;
	var newHeight = null;
	var newWidth = null;
	var newX = null;
	var newY = null;

	if (duration <=0)
	{
		if (options.deltaHeight != null)
		{
			newHeight = options.height;
			newY = options.top || null;
		}
		if (options.deltaWidth != null)
		{
			newWidth = options.width;
			newX = options.left;
		}
	}
	else
	{
		if (options.deltaHeight != null)
		{
			newHeight = options.oldHeight + options.deltaHeight;
			newHeight = Math.max(newHeight,0);
			options.oldHeight = newHeight;
			newY = (options.oldY - options.deltaHeight) || null;
			options.oldY = newY;
		}

		if (options.deltaWidth != null)
		{
			newWidth = options.oldWidth + options.deltaWidth;
			newWidth = Math.max(newWidth,0);
			options.oldWidth = newWidth;
			newX = options.oldX + options.deltaWidth;
			options.oldX = newX;
		}
		window.setTimeout(Adiamor.lang.close(this, Adiamor.ui.Effects.resize, [options, domElements, duration, callback]), Adiamor.ui.Effects.ANIMATION_INTERVAL);
	}

	Adiamor.ui.Effects.executeNextPulse.push(Adiamor.lang.close({},Adiamor.ui.Effects.resizeFunc,[domElements,newHeight,newWidth,newY,newX,duration,CompleteOpener]));
};

Adiamor.ui.Effects.resizeFunc = function(domElements, newHeight, newWidth, newY, newX, duration, callback)
{
	for (var i=0; i<domElements.length; i++)
	{
		var domElement = domElements[i];
		if (newHeight != null)
		{
			domElement.style.height = Math.floor(newHeight) + "px";
		}
		if (newWidth != null)
		{
			domElement.style.width = Math.floor(newWidth) + "px"; 
		}
/*
		if (newY != null)
		{
			domElement.style.top = Math.floor(newY - topOffset) + "px";
		}
		if (newX != null)
		{
			domElement.style.left = Math.floor(newX) + "px"; 
		}
*/
	}
	if (duration <= 0)
	{
		if (callback)
		{
			window.setTimeout(callback,0);
		}
	}	
};
/**
 * A stack of function references that will be called every animation pulse.
 * @private
 */
Adiamor.ui.Effects.executeNextPulse = [];

/**
 * Executes every function reference in {@link Adiamor.ui.Effects#executeNextPulse} and clears its contents.
 */
Adiamor.ui.Effects.pulse = function()
{
	var p;
	while (p = Adiamor.ui.Effects.executeNextPulse.shift())
	{
		p.call();
	}
};

/**
 * The number of milliseconds between executions of {@link Adiamor.ui.Effects#pulse}.
 * @private
 * @final
 */
Adiamor.ui.Effects.PULSE_INTERVAL = 40;
/**
 * The number of milliseconds between calculating new animation frames.
 * @private
 * @final
 */
Adiamor.ui.Effects.ANIMATION_INTERVAL = 25;


if (Adiamor.browser.IE)
{
	//IE has a far better performance when animating transitions so we can use a lower interval.
	Adiamor.ui.Effects.PULSE_INTERVAL = 10;
	Adiamor.ui.Effects.ANIMATION_INTERVAL = 10;
}

window.setInterval(Adiamor.ui.Effects.pulse, Adiamor.ui.Effects.PULSE_INTERVAL);

/**
 * Gradually shows an element.
 * @param {Element} element The element to fade in.
 * @param {function} completeCallback Optional. Executed when the fade finishes.
 * @param {reference} context The context in which the call will be executed.
 * @param {int} currentOpacity Optional. The opacity to start at.
 */
Adiamor.ui.Effects.fade = function(element, options, duration, func, funcContext, callback, callbackContext)
{
	options.deltaValue = (options.endValue - options.startValue) / (duration / Adiamor.ui.Effects.ANIMATION_INTERVAL);

	var count = 1;
	while (duration > 0)
	{
		duration -= Adiamor.ui.Effects.ANIMATION_INTERVAL;

		options.startValue = options.startValue + options.deltaValue;

		window.setTimeout(Adiamor.lang.close(funcContext, func, [element, eval(options.startValue)]), Adiamor.ui.Effects.ANIMATION_INTERVAL*count);
		count++;
	}
	window.setTimeout(Adiamor.lang.close(funcContext, func, [element, eval(options.endValue)]), Adiamor.ui.Effects.ANIMATION_INTERVAL*count);
	if (callback != null)
	{
		window.setTimeout(Adiamor.lang.close(callbackContext || this, callback, [element, eval(options.startValue)]), Adiamor.ui.Effects.ANIMATION_INTERVAL*count);
	}	
};

/**
 * WARNING: This may blow away any style properties on the domElement
 */
Adiamor.ui.Effects.hide = function(domElement)
{
	Adiamor.html.Css.addClass(domElement, "Adiamor-ui-effects-hidden");
	domElement.style.height = "";
	domElement.style.width = "";
};

Adiamor.ui.Effects.isHidden = function(domElement)
{
	if (Adiamor.html.Css.hasClass(domElement, "Adiamor-ui-effects-hidden"))// || ((domElement.style.visibility == 'hidden') && (domElement.style.position == 'absolute')))
	{
		return true;
	}
	else
	{
		return false;
	}
};

Adiamor.ui.Effects.show = function(domElement, options)
{
	domElement.style.display = "none";
	
	for (o in options)
	{
		if (options.hasOwnProperty(o)) {
			domElement.style[o] = options[o];
		}	
	}
	domElement.style.display = "";
};

/**
 * The number of milliseconds between calculating new fade frames.
 * @private
 * @final
 */
Adiamor.ui.Effects.FADE_INTERVAL = 5;
/**
 * The number by which to adjust the opacity. Must evenly div into 100;
 * @private
 * @final
 */
Adiamor.ui.Effects.FADE_STEP = 25;

/**************************************************************************/
/*					Adiamor.ui.DragDrop	     	      
/**************************************************************************/

Adiamor.lang.defineNs("Adiamor.ui");

/**
 * A Drag and Drop library that allows the user to drag an element around the page.
 * @constructor
 * @param element {object} The element to drag.
 * @param event {object} Mozilla event object.
 */
Adiamor.ui.DragDrop = function(element, allowVertDrag, allowHorizDrag)
{
	this.allowVertDrag = (allowVertDrag!=null ? allowVertDrag : true);
	this.allowHorizDrag = (allowHorizDrag!=null ? allowHorizDrag : true);

	if (Adiamor.browser.IE)
	{
		/**
		 * The surface here is slipped underneath the 
		 * darg object to provide a smooth drag surface. Otherwise
		 * IE hooks on other tags. A little trick. The opacity is set to 1
		 * because if the bg is set to transparent, IE treats the element like 
		 * its not there.
		 * @private
		 * @type object
		 */
		this.surface = document.getElementById("ebadragdropsurface_");
		if (this.surface == null)
		{
			this.surface = document.createElement("div");
			this.surface.id = "ebadragdropsurface_";
			var s = this.surface.style;
			s.filter="alpha(opacity=1)";
			s.backgroundColor="white";
			s.position="absolute";
			s.visibility="hidden";
			s.top="-5000";
			s.left="-5000";
			s.width="100";
			s.height="100";
			s.zIndex="500";
			document.body.appendChild(this.surface);
		}
	}

	this.object = null;

	if (element.getDragElement != null)
	{
		this.object = element;
		element = element.getDragElement(); 
	}

	/**
	 * @ignore
	 */
	this.element = element;

	/**
	 * @ignore
	 */
	this.zIndex = this.element.style.zIndex;
  	this.element.style.zIndex=900;

    this.Ticks = 10;
    this.Discrete = false;

	this.OnMouseMove = new Adiamor.base.SubjectHelper();
	this.OnDragStart = new Adiamor.base.SubjectHelper();
	this.OnDragStop = new Adiamor.base.SubjectHelper();

    /**
     * These are the events for the drag and drop that are attached / detached all the time
     */
    this.events = [{"type":"mouseup","handler":this.onMouseUp}, {"type":"mousemove","handler":this.onMouseMove}];
};

Adiamor.ui.DragDrop.prototype.startDrag = function()
{
	// First we get the _relative_ coords top and left.
	/**
	 * @ignore
	 */
  	this.originTop  = parseInt(this.object.getY(),10);
  	/**
	 * @ignore
	 */
  	this.originLeft = parseInt(this.object.getX(),10);

  	if (isNaN(this.originLeft)) { this.originLeft = 0; }
  	if (isNaN(this.originTop)) { this.originTop = 0; }

	// Next we get the _obsolute_ coords Y and X.
	var coords = Adiamor.html.getCoords(this.element);
    
  	/**
  	 * The x coordinate from where the object was dragged.
  	 * @type int 
  	 */	
	this.originX = coords.x;
	 /**
  	 * The y coordinate from where the object was dragged.
  	 * @type int 
  	 */	
  	this.originY = coords.y;
  	this.originWidth = coords.width;
  	this.originHeight = coords.height;

    if (Adiamor.browser.IE) 
    {
        this.surface.style.visibility="visible";
        this.surface.style.width = document.body.clientWidth;
        this.surface.style.height = document.body.clientHeight;
    }

    Adiamor.html.attachEvents(document, this.events, this);

	this.OnDragStart.notify();
};


/**
 * @ignore
 */
Adiamor.ui.DragDrop.prototype.onMouseMove = function (evt) 
{
	// Get the absolute coords of the event.
  	var coords = Adiamor.html.getEventCoords(evt);
  	var x = coords.x;
  	var y = coords.y;
  	
  	if (this.allowHorizDrag)
    {
		var offset = 0;
		var xoffset = 0;
		// Check extents
		
		//Section added to fix alignment issues when the window is resized but was not completed.
		//Currently page refreshes on window resize
    	/*if(Adiamor.browser.DocumentWidth > getDocWidth())
    	{
    		offset -= ((Adiamor.browser.DocumentWidth-getDocWidth())/2);
    		xoffset += 67;//((Adiamor.browser.DocumentWidth-this.maxX)-offset);
    	}
    	else if(Adiamor.browser.DocumentWidth < getDocWidth())
    	{
    		offset += ((Adiamor.browser.DocumentWidth-getDocWidth())/2);
    		xoffset += 67;//((Adiamor.browser.DocumentWidth-this.maxX)-offset);
    	}*/
    	//End of alignment code
    	
		if (x+xoffset <= this.minX)
        {
        	x = this.minX+xoffset;
        }
        else if (x+xoffset >= this.maxX)
        {
        	x = this.maxX-xoffset;
        }
    	
    	var newLeft = (this.originLeft + x - this.originX - this.originWidth/2);
    	
    	this.object.setX(newLeft);
    }
    else if (this.allowVertDrag)
    {
		var offset = 0;
		//if(this.object.Position=="Top")
		//	offset = this.originHeight-2;
			
		/*if((this.originTop*-1 <= this.originHeight) && this.object.Position=="Top")
			offset = 0;*/

		// Check extents
        if (y + offset >= this.minY)
        {
        	y = this.minY;
        }
        else if (y <= this.maxY)
        {
        	y = this.maxY;
        }
    	
        var newBottom = (y - this.originTop - this.originY - this.originHeight - offset);
		this.object.setY(newBottom);
	}
	
    Adiamor.html.cancelEvent(evt);

	//this.OnMouseMove.notify();
};

/**
 * @ignore
 */
Adiamor.ui.DragDrop.prototype.onMouseUp = function(evtObj)
{
	if (Adiamor.browser.IE) { this.surface.style.visibility="hidden"; }

    Adiamor.html.detachEvents(document, this.events);

	this.element.style.zIndex = this.zIndex;
//  this.element.object = null; 
//  this.element = null;

	this.OnDragStop.notify({'DragElement':this.object,'DragManager':this,'Event':evtObj});
};

Adiamor.ui.DragDrop.prototype.setXBounds = function(min, max)
{
	this.minX = min;
	this.maxX = max;
    this.Step = Math.floor((this.maxX - this.minX)/this.Ticks);
};

Adiamor.ui.DragDrop.prototype.setMaxX = function(val)
{
	this.maxX = val;
};

Adiamor.ui.DragDrop.prototype.setMinX = function(val)
{
	this.minX = val;
};

Adiamor.ui.DragDrop.prototype.setYBounds = function(min, max)
{
	this.minY = min;
	this.maxY = max;
    this.Step = Math.floor((this.maxY - this.minY)/this.Ticks);
};

Adiamor.ui.DragDrop.prototype.setMaxY = function(val)
{
	this.maxY = val;
};

Adiamor.ui.DragDrop.prototype.setMinY = function(val)
{
	this.minY = val;
};

/**
 * Defines an interface for Adiamor UI classes that are to be draggable.
 * @param {HTMLElement} element The HTML element that is draggable.
 */
Adiamor.ui.IDraggable = function Adiamor_ui_IDraggable(element)
{
	this.DragElement = element;
};

/**
 * Returns a reference to the HTML element that is draggable.
 */
Adiamor.ui.IDraggable.prototype.getDragElement = function()
{
	return this.DragElement;
};


function createFunction(obj, func)
{
	return function() {return func.apply(obj, arguments);};
}
/**
 * Makes the specified object draggable.
 * @param {Object} obj A Adiamor object like an instance of a Adiamor.ui.Panel.
 */
Adiamor.ui.IDraggable.makeDraggable = function(obj, element)
{
	obj.DragElement = element;
	obj.getDragElement = createFunction(obj, Adiamor.ui.IDraggable.prototype.getDragElement);
};

//		Adiamor.ui.Element	     	      

Adiamor.lang.defineNs("Adiamor.ui");

/**
 * A abstract class the represents a UI element on the screen.
 * @param {string} template string that defines the element's markup
 * @param {object} templateFunctions a hash of functions that can be used in the template
 * @param {string} id the id of the object
 */
Adiamor.ui.Element = function (template,templateFunctions,id)
{
	if (arguments.length > 0)
	{
		this.initialize(template,templateFunctions,id);	
	}
};

Adiamor.lang.extend(Adiamor.ui.Element, Adiamor.base.Object);

/**
 * Initializes the object.
 * @private
 */
Adiamor.ui.Element.prototype.initialize = function (template,templateFunctions,id)
{
	this.template = template;
	this.templateFunctions = templateFunctions;
	this.templateExternals = null;
	this.id = id;
	this.m_HtmlElementHandle=$(id);
};

/**
 * The Id of the element.
 * @return {string} The id of the element. 
 */
Adiamor.ui.Element.prototype.getId = function ()
{
	return this.id;
};

/**
 * The Id of the element.
 * @param id {string} The Id. It must be unique on the page.
 */
Adiamor.ui.Element.prototype.setId = function (id)
{
	this.id = id;
};

/**
 * The height of the element.
 * @return {string} The height of the object including the type of unit used, e.g., 10px.
 */
Adiamor.ui.Element.prototype.getHeight = function ()
{
	var elem = this.getHtmlElementHandle();
	return parseInt(elem.style.height || elem.offsetHeight, 10);
};

/**
 * Sets the height of the element.
 * @param height {string} The height of the element including its units, e.g., 10px.
 */
Adiamor.ui.Element.prototype.setHeight = function (height)
{
	if (typeof height == "number") { height = height + 'px'; }
	this.getHtmlElementHandle().style.height = height;
};

/**
 * The width of the element.
 * @return {string} The width of the element including its units, e.g., 10px.  
 */
Adiamor.ui.Element.prototype.getWidth = function ()
{
	var elem = this.getHtmlElementHandle();
	return parseInt(elem.style.width || elem.offsetWidth, 10);
};

/**
 * The width of the element.
 * @param width {string} The width of the element including its units, e.g., 10px.
 */
Adiamor.ui.Element.prototype.setWidth = function (width)
{
	if (typeof width == "number") { width = width + 'px'; }
	this.getHtmlElementHandle().style.width = width;
};

/**
 * Returns the template for rendering.
 * @type string
 */
Adiamor.ui.Element.prototype.getTemplate = function()
{
	return this.template;
};

/**
 * Sets the template for rendering.
 * @param {string} template The new template.
 */
Adiamor.ui.Element.prototype.setTemplate = function(template)
{
	this.template = template;
};

/**
 * Returns the template functions as a hash of function references.
 * @type object
 */
Adiamor.ui.Element.prototype.getTemplateFunctions = function()
{
	return this.templateFunctions;
};

/**
 * Set the hash of function references that will be used in the template.
 * @param {object} templateFunctions the new hash of function references.
 */
Adiamor.ui.Element.prototype.setTemplateFunctions = function(templateFunctions)
{
	this.templateFunctions = templateFunctions;
};

/**
 * Returns the hash of external variables that can be used in the template.
 * @type object
 */
Adiamor.ui.Element.prototype.getTemplateExternals = function()
{
	return this.templateExternals;
};

/**
 * Returns the hash of external variables that can be used in the template.
 * @type object
 */
Adiamor.ui.Element.prototype.setTemplateExternals = function(templateExternals)
{
	this.templateExternals = templateExternals;
};

/**
 * A handle to the html element that represents this UI object.
 * @return {object} An HTML element reference.
 */
Adiamor.ui.Element.prototype.getHtmlElementHandle = function ()
{
	if (this.m_HtmlElementHandle == null)
	{
		this.m_HtmlElementHandle = document.getElementById(this.getId());
	}
	return this.m_HtmlElementHandle;
};


/**
 * @private
 */
Adiamor.ui.Element.prototype.setHtmlElementHandle = function (htmlElementHandle)
{
	this.m_HtmlElementHandle = htmlElementHandle;
};


/**
 * Hides the element.
 */
Adiamor.ui.Element.prototype.hide = function ()
{
	var tag = this.getHtmlElementHandle();
	tag.style.display = "none";
	//tag.style.visibility="hidden";
	//tag.style.position="absolute";
};

/**
 * Shows the element.
 */
Adiamor.ui.Element.prototype.show = function ()
{
	var tag = this.getHtmlElementHandle();
	tag.style.display = "block";
	//tag.style.visibility="visible";
	//tag.style.position="relative";
};

Adiamor.ui.Element.prototype.align = function(element)
{
	var tag = this.getHtmlElementHandle();
	tag.style.top = '-10000px';
	tag.style.left = '-10000px';
	tag.style.visibility = 'hidden';
	tag.style.display = 'block';
};

/**
 * Determines if the element is visible or not.
 */
Adiamor.ui.Element.prototype.isVisible = function()
{
	var disp = this.getHtmlElementHandle().style.display;
	if (disp == "none" || disp == "") { return false; }
	return true;
};

/**
 * Toggles the visibility of the element.
 */
Adiamor.ui.Element.prototype.toggle = function()
{
	if (this.isVisible()) { this.hide(); }
	else { this.show(); }
};

/**
 * Makes the element float in absolute position mode.
 */
Adiamor.ui.Element.prototype.beginFloatMode = function ()
{
	var tag = this.getHtmlElementHandle();
	tag.style.position="absolute";
};

/**
 * If the element is floating, sets the x position.
 * @param x {string} The x position including its units.
 */
Adiamor.ui.Element.prototype.setX = function (x)
{
	var anum=/(^\d+$)|(^\d+\.\d+$)/;
	if (anum.test(x))
	{
		var tag = this.getHtmlElementHandle();
		tag.style.left = parseInt(x,10) + "px";
	}
};


/**
 * If the element is floating, gets the x position.
 * @return {string} The x position including its units.
 */
Adiamor.ui.Element.prototype.getX = function ()
{
	var tag = this.getHtmlElementHandle();
	return parseInt(tag.style.left,10);
};

/**
 * If the element is floating, sets the y position.
 * @param y {string} The y position including its units.
 */
Adiamor.ui.Element.prototype.setY = function (y)
{
	var tag = this.getHtmlElementHandle();
	tag.style.top = parseInt(y,10) + "px";
};

/**
 * If the element is floating, gets the y position.
 * @return {string} The y position including its units.
 */
Adiamor.ui.Element.prototype.getY = function ()
{
	var tag = this.getHtmlElementHandle();
	return parseInt(tag.style.top,10);
};

/**
 * Renders the Element using the template, and object and possibly the htmlElement.
 * @param {object} htmlElement A handle to the HTML element on the page inside
 * which the UiElement is rendered. If htmlElement is null, the UiElement is appended
 * to the end of the body.
 * @param {string} templateString the template to render the object with, defaults to <CODE>this.template</CODE> 
 * @param {object} inputObject the object to render, defaults to <CODE>this</CODE>
 * @param {object} extensions a Hash of functions to use with the template
 * @param {object} external a hash of values external to the inputObject to use in the template
 */
Adiamor.ui.Element.prototype.render = function (htmlElement,templateString,inputObject, extensions, external)
{
	templateString = templateString == null ? this.getTemplate() : htmlElement;
	inputObject = inputObject == null ? this : inputObject;
	htmlElement = htmlElement == null ? this.getHtmlElementHandle() : htmlElement;
	extensions = extensions == null ? this.getTemplateFunctions() : extensions;
	external = external == null ? this.getTemplateExternals() : external;

	var html = Adiamor.templating.applyTemplate(templateString, inputObject, extensions, external);

	if (null == htmlElement)
	{
		document.body.insertAdjacentHTML("beforeEnd",html);
		var tag = document.body.childNodes[document.body.childNodes.length-1];
		if (tag.id == "")
		{
			tag.id = this.getId();
		}
	}
	else
	{
		htmlElement.innerHTML = html;
	}
	
	this.attachToTag();
};


/**
 * Attaches the javascript object to the HTML tag. Once this is called after render,
 * you can access the object by using the javascriptObject property on the HTML tag.
 */
Adiamor.ui.Element.prototype.attachToTag = function ()
{

	var domNode = this.getHtmlElementHandle();
	if (domNode != null)
	{
		domNode.AdiamorObject=this;
	}
};

Adiamor.ui.Element.prototype.dispose = function()
{
	Adiamor.ui.Element.base.dispose.call(this);
};
Adiamor.ui.Panel = function(contents)
{
    this.Contents = contents || "";
	this.OnMouseOver = new Adiamor.base.SubjectHelper();
	this.OnMouseOut = new Adiamor.base.SubjectHelper();
};

Adiamor.lang.extend(Adiamor.ui.Panel, Adiamor.ui.Element);

Adiamor.ui.Panel.prototype.attachToParent = function(container)
{
    this.Container = container;
    if (this.Container.innerHTML != "") { this.Contents = this.Container.innerHTML; }
	this.Frame = Adiamor.html.getFirstChild(this.Container);
	if (this.Frame != null)
	{
		this.Frame.style.position = 'relative';
		this.Surface = Adiamor.html.getFirstChild(this.Frame);
	}
    this.setId(container.id);
    this.attachEvents();
    this.render();
};

Adiamor.ui.Panel.prototype.attachEvents = function()
{
	Adiamor.html.attachEvent(this.Container, 'mouseover', this.OnMouseOver.notify, this.OnMouseOver);
	Adiamor.html.attachEvent(this.Container, 'mouseout', this.OnMouseOut.notify, this.OnMouseOut);
};

Adiamor.ui.Panel.prototype.render = function()
{
	if (this.Container.innerHTML == "") { this.Container.innerHTML = this.Contents; }
};

Adiamor.ui.Panel.prototype.setBackgroundImage = function(bgImage, options)
{
	if (bgImage.indexOf(".png" > 0))
	{
		if (Adiamor.browser.IE6)
		{
			this.Container.style.filter += "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+bgImage+"')";
			bgImage = 'none';
		}
		else { bgImage = "url('"+bgImage+"')"; }
	}
	this.Container.style.backgroundImage = bgImage;
	for (var item in options)
	{
		if (options.hasOwnProperty(item)) {
			this.Container.style[item] = options[item];
		}	
	}
	//;bacground-repeat: no-repeat;}
};

Adiamor.ui.Panel.prototype.setSurfaceTop = function(scrollTop)
{
	this.Surface.style.top = scrollTop + 'px';
};

Adiamor.ui.Panel.prototype.getSurfaceTop = function()
{
	return this.Surface.style.top;
};

Adiamor.lang.defineNs('Adiamor.ui');

//	This is to help with selection by scrolling a bit more than needed
//	so that the user can mouseover the next cell easily enough
//	TODO: this should vary as we scroll over otherwise it goes _really_ fast.
var EBA_SELECTION_BUFFER = 15;
/**
 * How much time to wait after a scroll event before request data from the server.
 */
var g_renderDelay = 50;

Adiamor.ui.Viewport = function()
{
  	//	This array is used to hold closures that remove any memory leaks
	this.disposal = [];
	this.RowHeight = 22;																							//DEPENDENCY - Adiamor.Grid and model - DETANGLE Adiamor.Grid						
	this.uid = Adiamor.base.getUid();

	this.lastScrollTop=-1;

	this.rows = 500;

	this.cacheMap = new Adiamor.collections.Map(-1,-1);

	this.DataSource = {};

	/**
	 * The DOM node that represents the outer bounds of the viewport
	 */
	this.element = null;
	/**
	 * The DOM node that is the "clipping" DIV since if you have a relatively
	 * positioned DIV inside another DIV it does not obey overflow rules.
	 * So you need 
	 * 	<div id="element" style="overflow:hidden;"><div id="frame" style="position:relative;"><div id="surface" style="position:relative;top:-200px;"></div></div></div>
	 */
	this.frame = null;
	/**
	 * The DOM node that the data is rendered on. This is the one that is inside 
	 * the Frame and gets moved around for scrolling. 
	 */
	this.surface = null;

    this.RowHoverColor = "#E3E8F2";

    this.OnRenderComplete = new Adiamor.base.SubjectHelper();
};

/**
 * 
 */
Adiamor.ui.Viewport.prototype.mapToHtml = function(element, frame, surface)
{
	this.surface = surface;
	this.frame = frame;
	this.element = element;
};

/**
 *
 */
Adiamor.ui.Viewport.prototype.clear = function()
{
	this.surface.innerHTML = '';
	this.lastScrollTop=-1;
	this.flushCache();
};

Adiamor.ui.Viewport.prototype.setSurfaceHeight = function(height)
{
	this.surface.style.height = height + 'px';
};

Adiamor.ui.Viewport.prototype.setScrollTopRelative=function(offset) {
	this.setScrollTop(this.scrollTop+offset);
};
Adiamor.ui.Viewport.prototype.setScrollTopPercent=function(scrollPercent) {
	this.scrollTopPercent = scrollPercent;
	this.setScrollTop(Math.round((this.surface.offsetHeight - this.frame.clientHeight) * scrollPercent));
};
Adiamor.ui.Viewport.prototype.setScrollTop=function(scrollTop)
{
	this.scrollTop=scrollTop;
	this.frame.scrollTop = scrollTop;
	this.render();
};

Adiamor.ui.Viewport.prototype.render=function()
{
	if (this.surface.scrollTop != this.lastScrollTop)
	{
		var visibleRowRange = this.getRowRange();
		if (!this.rendered(visibleRowRange))
		{
			// Wait a little bit before rendering, just in case the user has scrolled past this position.
			// This enables quickly scrolling through large data sets without rendering every record.

			var funcRef = Adiamor.lang.close(this, this.renderReady, [visibleRowRange]);
			window.clearTimeout(this.lastTimeoutId);
			this.lastTimeoutId = window.setTimeout(funcRef, g_renderDelay);
		}
		else
		{
			// We may have requested data and displayed the acitivty indicator but we have scrolled to a rendered region.
			this.hideIndicator();
		}
	}
};

Adiamor.ui.Viewport.prototype.rendered= function(visibleRowRange)
{
	if (visibleRowRange == null)
	{
		visibleRowRange = this.getRowRange();
	}

	var myGaps = this.cacheMap.gaps(visibleRowRange.first,visibleRowRange.last);

	return Boolean(myGaps[0]==null);
};

/**
 * Returns a row range of what should currently be rendered in the grid. When paging is not being used,
 * it simply returns the total number of rows in the Grid. For LiveScrolling it calculates the rows 
 * to show based on the scroll position. Finally, for Standard paging it returns the rowsPerPage offset
 * by the index of the current page. 
 * @return {Pair} A struct range with first and last values which are the start and end of the row range.
 */
Adiamor.ui.Viewport.prototype.getRowRange=function()
{
	//	Get the rows from metadata and calculate the first visible row
	var firstVisibleRow = 0;
	//	Set scrollTop to be the current amount of scrolling plus the height of the top frozen rows
	//	minus the height of the indicators

	firstVisibleRow += Math.floor(this.frame.scrollTop/this.RowHeight);

	//	Get the rows from metadata and calculate the last visible row
	var lastVisibleRow = 0;
	lastVisibleRow += Math.ceil(this.frame.clientHeight/this.RowHeight) + firstVisibleRow + 40;

	// changed to this.rows-1 since lastVisibleRow is zero based.
	//lastVisibleRow = Math.min(this.rows-1,lastVisibleRow);

	// We check if standard paging is being used, and if so apply an offset 
	// of the page size * the current page to the first visible row.
	return {first : firstVisibleRow, last: lastVisibleRow};
};

//***********************************************
//******** HELPER FUNCTIONS *********************
//***********************************************

function hideElement(element)
{
	var s = element.style;
	s.left = "-10000px";
	s.visibility = "hidden";
	s.display = "none";
}

function showElement(element)
{
	var s = element.style; 
	s.visibility = "visible";
	s.display = "block";
	Adiamor.dom.setOpacity(element, 100);
}

function positionElement(element, top, left)
{
	element.style.top = top + "px";
	element.style.left = left + "px";
}

function isElementVisible(element)
{
	var left = parseInt(Adiamor.dom.getStyle(element, "left"),10);
	var disp = Adiamor.dom.getStyle(element, "display");
	var vis = Adiamor.dom.getStyle(element, "visibility");
	if (disp == "none" || vis == "hidden" || left <-500) { return false; }
	return true;
}

Adiamor.ui.Viewport.prototype.renderReady = function(visibleRowRange)
{
	var myGaps = this.cacheMap.gaps(visibleRowRange.first,visibleRowRange.last);// + (visibleRowRange.last - visibleRowRange.first) + 5); // Logic for increasing gap size moved into scroller

	if (myGaps[0] != null)
	{
		var low = myGaps[0].low;
		var high = myGaps[0].high;

		var rows = high - low + 1;

		if (!this.DataSource.inCache(low, rows)) 
		{
			if ($('gridlist-indicator').style.visibility == 'visible' && this.rows == 0) { this.hideIndicator(); }
			else { this.showIndicator(); }
			this.DataSource.setParam("start", low);
			this.DataSource.setParam("page_size", rows);
			this.DataSource.get();
			return false;
		}
		else
		{
			this.hideIndicator();
			hideElement($('gridlist-overlay'));
			this.cacheMap.insert(low, high);
			this.renderGap(low, high);
		}
	}
	return (myGaps[0] != null);
};

Adiamor.ui.Viewport.prototype.showIndicator = function()
{
	$('gridlist-indicator').style.visibility = 'visible';
};

Adiamor.ui.Viewport.prototype.hideIndicator = function()
{
	$('gridlist-indicator').style.visibility = 'hidden';
};

Adiamor.ui.Viewport.renderImage = function(val)
{
	return '<div style="width: 100%; text-align: left;"><img align="left" src="'+g_imagePath+val+'_sm.gif" style="vertical-align:middle;">&nbsp;&nbsp;'+val+'</div>';
};

Adiamor.ui.Viewport.renderImageOnly = function(val)
{
	return '<div style="width: 100%; text-align: center;"><img align="center" src="'+g_imagePath+val+'_sm.gif" style="vertical-align:middle;"></div>';
};

Adiamor.ui.Viewport.renderBoolean = function(val)
{
	return '<div class="gridlist-column-boolean-value"></div>';
};

Adiamor.ui.Viewport.renderNumber = function(val, schema, type)
{
	if (schema.Decimals != null)
	{
		return Adiamor.lang.formatNumber(val, schema.Decimals);
	}
	else 
	{
		return Adiamor.lang.formatNumber(val);
	}	
};

Adiamor.ui.Viewport.renderButton = function(val, schema, g_type)
{
	//var royal = "'#0000ff'";
	//var midnight = "'#25407b'";
	// onmouseover="this.style.color='+royal+';" onmouseout="this.style.color='+midnight+';"
	return '<a href="D-'+val+'.htm" class="view"><img border="0" src="../images/buttons/viewOff.gif" onmouseover="this.src=\'images/buttons/viewOn.gif\'" onmouseout="this.src=\'images/buttons/viewOff.gif\'" onmousedown="this.src=\'images/buttons/viewClick.gif\'"></a>';
};

Adiamor.ui.Viewport.renderMoney = function(val)
{
	var ca = document.cookie.split(';');
	var currency;
	for(var i=0; i < ca.length; i++)
	{
		var c = ca[i].replace(/\s/g,'');
		if(c.indexOf("country") == 0) { currency = unescape(c.substring(("country=").length, c.length)); }
	}
	
	if(currency == "BP") { return '£' + Adiamor.lang.formatNumber(val,0); }
	else { return '$' + Adiamor.lang.formatNumber(val,0); }
};

var g_types = {"image":{"Class":"gridlist-column-image","Formatter":Adiamor.ui.Viewport.renderImage},
				"boolean":{"Class":"gridlist-column-boolean","Formatter":Adiamor.ui.Viewport.renderBoolean},
				"number":{"Class":"gridlist-column-number","Formatter":Adiamor.ui.Viewport.renderNumber},
				"money":{"Class":"gridlist-column-money","Formatter":Adiamor.ui.Viewport.renderMoney},
				"button":{"Class":"gridlist-column-button","Formatter":Adiamor.ui.Viewport.renderButton}};

Adiamor.ui.Viewport.prototype.renderGap = function(top, bottom)
{
	var lastRow = bottom;
	var rows = Math.min(lastRow - top + 1, this.DataSource.data.length);
	var sRows = [];
	var h = 0;
	//	This gets the currently active row and column for possible style changes during rendering
	
	//	var s = this.rowRenderer.render(top, rows, 0, 0, this.sortColumn, this.sortDir);
	var s = [];
	var schema = this.DataSource.Schema;
	s.push("<table cellspacing=\"0\" border=\"0\" cellpadding=\"0\" class=\"gridlist-datablock\">");
	for (var i=0; i<rows; i++)
	{
		var className = "ListDataRow";
		if (i % 2 == 0) { className = "ListDataRowAlt"; }
	    
		if(Adiamor.browser.IE6)
		{
			s.push("<tr id=\"list_row_"+i+"\" class=\""+className+" \" onmouseover=\"this.style.backgroundColor='"+this.RowHoverColor+"';\" onmouseout=\"this.style.backgroundColor='transparent'\" row=\""+(top+i)+"\" Adiamortype=\"row\">");
		}
		else
		{
			s.push("<tr id=\"list_row_"+i+"\" class=\""+className+" \" onmouseover=\"this.style.backgroundColor='"+this.RowHoverColor+"';\" onmouseout=\"this.style.backgroundColor=''\" row=\""+(top+i)+"\" Adiamortype=\"row\">");
		}
		
		if(this.DataSource.getMappedValue(top+i, 15) == "True")
		{
			sRows[h] = i;
			h++;
		}

		for (var j=0; j<schema.length; j++)
		{
    		var val = this.DataSource.getMappedValue(top+i, j);

			var type = schema[j].Type;
			if (g_types[type] != null)
			{
				className = g_types[type].Class;
				val = g_types[type].Formatter.call(this, val, schema[j], g_types[type]);
				
				if(g_types[type].Class == "gridlist-column-money") { val = val.replace('£', '&pound;'); }
			}
			
			if(g_grid.Columns[j].Width != g_grid.Columns[j].OriginalWidth)
			{
				var pd="";
				if(g_grid.Columns[j].Name == "Cut" && (g_grid.Columns[j].OriginalWidth - g_grid.Columns[j].Width) > 5)
				{
					val = this.DataSource.getMappedValueCut(top+i, j);
				}
				else if(g_grid.Columns[j].Name == "Info")
				{
					pd = "padding-left: 0px;";
				}
				if(!Adiamor.browser.SAFARI && !Adiamor.browser.MOZ)
				{
					s.push("<td class=\"gridlist-column"+j+" gridlist-columndata"+j+"\" style=\"width: "+g_grid.Columns[j].Width+";\" width=\""+g_grid.Columns[j].Width+"\" Adiamortype=\"cell\" row=\""+(top+i)+"\" column=\""+j+"\"><div class=\"gridlist-cell gridlist-column"+j+"\" style=\"width: "+(g_grid.Columns[j].Width)+";"+pd+"\">" + val + "</div></td>");
				}
				else
				{
					s.push("<td class=\"gridlist-column"+j+" gridlist-columndata"+j+"\" style=\"width: "+g_grid.Columns[j].Width+";\" width=\""+g_grid.Columns[j].Width+"\" Adiamortype=\"cell\" row=\""+(top+i)+"\" column=\""+j+"\"><div class=\"gridlist-cell gridlist-column"+j+"\" style=\"width: "+(g_grid.Columns[j].Width-10)+";\">" + val + "</div></td>");
				}
			}
			else
			{
				s.push("<td class=\"gridlist-column"+j+" gridlist-columndata"+j+"\" Adiamortype=\"cell\" row=\""+(top+i)+"\" column=\""+j+"\"><div class=\"gridlist-cell gridlist-column"+j+" "+className+"\">" + val + "</div></td>");
			}
		}
		s.push("</tr>");
	}
	s.push("</table>");
	s = s.join('');

	var pixelTop = top * this.RowHeight;

	var o = document.createElement("div");

	o.style.position="absolute";

	o.style.top = pixelTop+'px';

	o.top = top;
	o.bottom = lastRow;
	o.rows = rows;

	o.setAttribute('id','Adiamor_grid_block_'+top+'_'+bottom);
	o.innerHTML = s;

	this.surface.appendChild(o);
	
	for(h=0; h<sRows.length; h++)
	{
		var domRow = $("list_row_"+sRows[h]);
		
		domRow.className = "gridlist-rowselected";
		g_grid.SelectedRows[sRows[h]] = domRow;
	}
		        
	var count = 0;
	for (var item in g_grid.SelectedRows)
	{
		count++;
	}
	
	$('numCompare').innerHTML=count+" Diamonds";

	this.OnRenderComplete.notify();
};

/**
 *
 */
Adiamor.ui.Viewport.prototype.flushCache = function()
{
	this.cacheMap.flush();
};

Adiamor.ui.Viewport.prototype.setDataSource = function(oDataSource)
{
	this.DataSource = oDataSource;
};

Adiamor.ui.Viewport.prototype.getDataSource = function()
{
	return this.DataSource;
};

Adiamor.lang.defineNs("Adiamor.collections");
Adiamor.lang.defineNs("Adiamor.drawing");

if (typeof(Adiamor.drawing) == "undefined")
{
	/**
	 * @constructor
	 */
	Adiamor.drawing = function() {};
}

if (typeof(Adiamor.collections) == "undefined")
{
	/**
	 * @constructor
	 */
	Adiamor.collections = function() {};
}


/**
 * Contains (x,y) pairs accessable via their respective properties: samplePoint.x and samplePoint.y
 */
Adiamor.drawing.Point = function(x,y)
{
	this.x = x;
	this.y = y;
};

Adiamor.drawing.Point.prototype.toString = function()
{
	return "("+this.x+","+this.y+")";
};

/**
 * @class Adiamor.collections.CellSet is a contiguous set of cells. The endpoints can be specified in any fashion, but the set will be addressed from top left to botom right.
 * @constructor
 * @param owner {Adiamor.Grid} The Adiamor.Grid object on whose cells the set sits. (Note: owner must implement getCellObject(x,y))
 * @param startRow {int} The row index of the start cell of the set.
 * @param startColumn {int} The column index of the start column of the set.
 * @param endRow {int} The row index of the end cell of the set.
 * @param endColumn {int} The column index of the end cell of the set.
 */
Adiamor.collections.CellSet = function(owner, startRow, startColumn, endRow, endColumn)
{
	this.owner = owner;
	if (startRow != null && startColumn != null && endRow != null && endColumn != null)
	{
		this.setRange(startRow, startColumn, endRow, endColumn);
	}
	else
	{
		this.setRange(0,0,0,0);
	}
};

Adiamor.collections.CellSet.prototype.toString = function()
{
	var str = "";
	for (var i = this._topRow; i <= this._bottomRow; i++)
	{
		str += "[";
		for (var j = this._leftColumn; j <= this._rightColumn; j++)
		{
			str += "("+i+","+j+")";
		}
		str += "]";
	}
	return str;
};

/**
 * Sets the endpoints of the set of cells on the grid to which the cellset refers.
 * @param startRow {int} The row index of the start cell of the set.
 * @param startColumn {int} The column index of the start column of the set.
 * @param endRow {int} The row index of the end cell of the set.
 * @param endColumn {int} The column index of the end cell of the set.
 */
Adiamor.collections.CellSet.prototype.setRange = function(startRow, startColumn, endRow, endColumn)
{
	this._startRow = startRow;
	this._startColumn = startColumn;
	this._endRow = endRow;
	this._endColumn = endColumn;
	
	this._leftColumn = Math.min(startColumn, endColumn);
	this._rightColumn = Math.max(startColumn, endColumn);
	this._topRow = Math.min(startRow, endRow);
	this._bottomRow = Math.max(startRow, endRow);
};

/**
 * Increases or decreases the size of the CellSet by changing the location of the starting cell.
 * @param startRow {int} The row index of the start cell of the set.
 * @param startColumn {int} The column index of the start cell of the set.
 */
Adiamor.collections.CellSet.prototype.changeStartCell = function(startRow, startColumn)
{
	this._startRow = startRow;
	this._startColumn = startColumn;
	
	this._leftColumn = Math.min(startColumn, this._endColumn);
	this._rightColumn = Math.max(startColumn, this._endColumn);
	this._topRow = Math.min(startRow, this._endRow);
	this._bottomRow = Math.max(startRow, this._endRow);
};

/**
 * Increases or decreases the size of the CellSet by changing the location of the ending cell.
 * @param startRow {int} The row index of the end cell of the set.
 * @param startColumn {int} The column index of the end cell of the set.
 */
Adiamor.collections.CellSet.prototype.changeEndCell = function(endRow, endColumn)
{
	this._endRow = endRow;
	this._endColumn = endColumn;
	
	this._leftColumn = Math.min(endColumn, this._startColumn);
	this._rightColumn = Math.max(endColumn, this._startColumn);
	this._topRow = Math.min(endRow, this._startRow);
	this._bottomRow = Math.max(endRow, this._startRow);
};


/**
 * Returns the number of rows in the CellSet
 * @type int
 */
Adiamor.collections.CellSet.prototype.getRowCount = function()
{
	return this._bottomRow - this._topRow + 1;
};

/**
 * Returns the number of columns in the CellSet
 * @type int
 */
Adiamor.collections.CellSet.prototype.getColumnCount = function()
{
	return this._rightColumn - this._leftColumn +1 ;
};

/**
 * An inline object where object.top is the Adiamor.drawing.Point object for the top left cell and object.bottom 
 * is the Adiamor.drawing.Point object for the bottom right cell
 * @type Object
 * @see Adiamor.drawing.Point
 */
Adiamor.collections.CellSet.prototype.getCoords = function()
{
	return {'top':new Adiamor.drawing.Point(this._leftColumn,this._topRow), 'bottom':new Adiamor.drawing.Point(this._rightColumn,this._bottomRow)};
};

/**
 * Returns the cell object at a position in the container offset from the top left cell in the CellSet
 * @param relRow {int} The row index (indexed from 0 at the top of the CellSet) of the desired cell.
 * @param relColumn {int} The column index (indexed from 0 at the leftmost column in the CellSet) of the desired cell.
 * @type Adiamor.components.grid.Cell
 */
Adiamor.collections.CellSet.prototype.getCellObjectByOffset = function(relRow, relColumn)
{
	return this.owner.getCellObject(this._topRow+relRow, this._leftColumn + relColumn);
};

///**
// * Clears the contents of the cells in the CellSet
// */
//Adiamor.collections.CellSet.prototype.clear = function()
//{
//	// Out of scope for 2006-06-09 sprint http://portal:8090/cgi-bin/trac.cgi/milestone/Grid%203.1%20-%20Copy%20%26%20Paste%20Sprint
//}
//
///**
// * Fills the cells in the cellset with a specified value
// * @param {String} fillString The string that each cell in the CellSet will contain when fill() completes
// */
//Adiamor.collections.CellSet.prototype.fill = function(fillString)
//{
//	// Out of scope for 2006-06-09 sprint http://portal:8090/cgi-bin/trac.cgi/milestone/Grid%203.1%20-%20Copy%20%26%20Paste%20Sprint
//}
Adiamor.ui.ActivityIndicator = function()
{
};

Adiamor.ui.ActivityIndicator.prototype.initialize = function()
{
};
/**************************************************************************/
/*					Adiamor.ui.GridList	     	      
/**************************************************************************/

Adiamor.lang.defineNs("Adiamor.ui");

/**
 * @constructor
 */
Adiamor.ui.GridList = function() 
{
	/**
	 * 
	 * @type ListColumnCollection
	 * @private
	 */
	this.Columns = [];

	this.Columns.push(new Adiamor.ui.GridListColumn({'Name':'xi','Label':'','Width':75,'Display':false,'Type':'text','Sortable':false}));
	this.Columns.push(new Adiamor.ui.GridListColumn({'Name':'ID','Label':'ID','Width':75,'Display':false,'Type':'text','Sortable':true}));
	this.Columns.push(new Adiamor.ui.GridListColumn({'Name':'Shape','Label':'<div id="hShape" style="padding-top: 2px">Shape</div>','Width':80,'Display':true,'Type':'image','Sortable':true}));
	this.Columns.push(new Adiamor.ui.GridListColumn({'Name':'Carat','Label':'<div id="hCarat" style="padding-top: 2px">Carat</div>','Width':75,'Display':true,'Type':'text','Sortable':true}));
	this.Columns.push(new Adiamor.ui.GridListColumn({'Name':'Color','Label':'<div id="hColor" style="padding-top: 2px">Color</div>','Width':74,'Display':true,'Type':'text','Sortable':true}));
	this.Columns.push(new Adiamor.ui.GridListColumn({'Name':'Clar','Label':'<div id="hClar" style="padding-top: 2px">Clarity</div>','Width':80,'Display':true,'Type':'text','Sortable':true}));
	this.Columns.push(new Adiamor.ui.GridListColumn({'Name':'Cut','Label':'<div id="hCut" style="padding-top: 2px">Cut</div>','Width':79,'Display':true,'Type':'text','Sortable':false}));
	this.Columns.push(new Adiamor.ui.GridListColumn({'Name':'Pol','Label':'<div id="hPol" style="padding-top: 2px">Pol.</div>','Width':40,'Display':false,'Type':'text','Sortable':true}));
	this.Columns.push(new Adiamor.ui.GridListColumn({'Name':'Sym','Label':'<div id="hSym" style="padding-top: 2px">Sym.</div>','Width':40,'Display':false,'Type':'text','Sortable':true}));
	this.Columns.push(new Adiamor.ui.GridListColumn({'Name':'Depth','Label':'<div id="hDepth" style="padding-top: 2px">Depth</div>','Width':40,'Display':false,'Type':'text','Sortable':true}));
	this.Columns.push(new Adiamor.ui.GridListColumn({'Name':'Tbl','Label':'<div id="hTbl" style="padding-top: 2px">Table</div>','Width':40,'Display':false,'Type':'text','Sortable':true}));
	this.Columns.push(new Adiamor.ui.GridListColumn({'Name':'Fluor','Label':'<div id="hFluor" style="padding-top: 2px">Fluor.</div>','Width':40,'Display':false,'Type':'text','Sortable':true}));
	this.Columns.push(new Adiamor.ui.GridListColumn({'Name':'Size','Label':'<div id="hSize" style="padding-top: 2px">L/W</div>','Width':40,'Display':false,'Type':'text','Sortable':true}));
	this.Columns.push(new Adiamor.ui.GridListColumn({'Name':'Cert','Label':'<div id="hCert" style="padding-top: 2px">Certificate</div>','Width':75,'Display':true,'Type':'text','Sortable':false}));
	this.Columns.push(new Adiamor.ui.GridListColumn({'Name':'SPrice','Label':'<div id="hSPrice" style="padding-top: 2px">Price</div>','Width':75,'Display':true,'Type':'money','Sortable':true}));
	this.Columns.push(new Adiamor.ui.GridListColumn({'Name':'Selected','Label':'<img id="hSelected" onclick="compareDiamonds();" style="padding-top: 2px" src="../images/Adiamor_T/compareoff.gif" onmouseover="this.src=\'images/Adiamor_T/compareon.gif\'" onmousedown="this.src=\'images/Adiamor_T/compareclick.gif\'" onmouseup="this.src=\'images/Adiamor_T/compareon.gif\'" onmouseout="this.src=\'images/Adiamor_T/compareoff.gif\'">','Width':78,'Display':true,'Type':'boolean','Sortable':false}));
	this.Columns.push(new Adiamor.ui.GridListColumn({'Name':'Info','Label':'<div id="hInfo" style="padding-top: 2px">Details</div>','Width':62,'Display':true,'Type':'button','Sortable':false}));
	this.Columns.push(new Adiamor.ui.GridListColumn({'Name':'Girdle','Label':'<div id="hGirdle" style="padding-top: 2px">Girdle</div>','Width':50,'Display':false,'Type':'text','Sortable':true}));
	this.Columns.push(new Adiamor.ui.GridListColumn({'Name':'Meas','Label':'<div id="hMeas" style="padding-top: 2px">Measurements</div>','Width':75,'Display':false,'Type':'text','Sortable':true}));
	this.Columns.push(new Adiamor.ui.GridListColumn({'Name':'Culet','Label':'<div id="hCulet" style="padding-top: 2px">Culet</div>','Width':50,'Display':false,'Type':'text','Sortable':true}));

	this.ColumnsMap = {};

	for (var i=0; i<this.Columns.length; i++)
	{
		this.ColumnsMap[this.Columns[i].Name] = i;
	}

	/**
	 * 
	 * @type int
	 * @private
	 */
	this.RowCount = 500;
	/**
	 * 
	 * @type int
	 * @private
	 */
	this.RowHeight = 23;
	/**
	 * 
	 * @type VerticalScrollbar
	 * @private
	 */
	this.Scrollbar = null;
	/**
	 * 
	 * @type int
	 * @private
	 */
	this.SortColumn = null;
	/**
	 * 
	 * @type char
	 * @private
	 */
	this.SortDirection = null;

	this.Template = '<table id="myGridList" class="List" border="0" cellpadding="0" cellspacing="0" >{$Header}{$Grid}{$Footer}</table>';

	this.Header = null;

    this.SelectedRows = {};

	this.MouseOverRow = null;
	this.MouseOverColumn = null;
 
	this.OnScrollVertical = new Adiamor.base.SubjectHelper();
	this.OnDataSourceConnected = new Adiamor.base.SubjectHelper();
    this.OnMouseOver = new Adiamor.base.SubjectHelper();
	this.OnMouseOut = new Adiamor.base.SubjectHelper();
	this.OnSort = new Adiamor.base.SubjectHelper();

	this.ViewEvents = [{'type':'click','handler':this.mouseClickHandler},
						{'type':'mouseover','handler':this.mouseOverHandler},
						{'type':'mouseout','handler':this.mouseOutHandler}];

	this.createChildren();
};

Adiamor.lang.extend(Adiamor.ui.GridList, Adiamor.ui.Element);

Adiamor.ui.GridList.prototype.createChildren = function()
{
	this.View = new Adiamor.ui.Viewport();
	this.View.mapToHtml($("ListDataElement"), $("ListDataFrame"), $("ListDataSurface"));

    Adiamor.html.attachEvents($("ListDataElement"), this.ViewEvents, this);

	// only connect the scrolled setDataTable method to the tableconnected event
	// once we know the scroller is defined.
	this.OnDataSourceConnected.subscribe(this.View.setDataSource, this.View);
	// Since we may already have connected a datatable to the grid we need to explicitly
	// connect update the scroller when we create it
	// TODO: should this be a constructor / initialize argument instead? 
	this.View.setDataSource(this.DataSource);

	// First we will create the styles for the columns ...
	this.setupColumnClasses();

    this.Header = new Adiamor.ui.GridListColumnHeader();
    this.Header.Columns = this.Columns;
    this.Header.attachToParent($("gridlist-columnheader"));
    
    this.Header.OnClick.subscribe(this.sort, this);
};

Adiamor.ui.GridList.prototype.sort = function(columnIndex)
{
	if (this.Columns[columnIndex] == null || this.Columns[columnIndex].Sortable == false) { return; }
	var oldSortDir = this.SortDirection;
	var oldSortCol = this.SortColumn;
	var newSortDir = "ASC";
	var newSortCol = columnIndex;
	if (this.SortColumn == columnIndex)
	{
		newSortDir = (this.SortDirection == "ASC"?("DESC"):("ASC"));
	}

	this.setSort(newSortCol, newSortDir, oldSortCol, oldSortDir);

	this.OnSort.notify(this.SortColumn, this.SortDirection);

	this.render();
};

Adiamor.ui.GridList.prototype.setSort = function(sortCol, sortDir, oldSortCol, oldSortDir)
{
	if(sortCol==141) { sortCol=14; }
	
	this.SortColumn = sortCol;
	this.SortDirection = sortDir;
	if (oldSortCol != null)
	{
		Adiamor.html.removeClass(Adiamor.html.getFirstChild($('gridlist-columnheader'+oldSortCol)), 'gridlist-columnheader-sort'+oldSortDir);
	}	
	Adiamor.html.addClass(Adiamor.html.getFirstChild($('gridlist-columnheader'+sortCol)), 'gridlist-columnheader-sort'+this.SortDirection);

	this.DataSource.setParam("sortcol", this.Columns[sortCol].Name);
	this.DataSource.setParam("sortdir", sortDir);
};

Adiamor.ui.GridList.prototype.render = function()
{
	this.DataSource.flush();
	this.View.clear();
	this.View.setScrollTop(0);
};

Adiamor.ui.GridList.prototype.setupColumnClasses = function()
{
	for (var i=0; i<this.Columns.length; i++)
	{
		var col = this.Columns[i];
		col.cssStyle = Adiamor.html.getClass('gridlist-column' + i);
		if (!col.Display) { col.cssStyle.display = 'none'; }
		col.cssStyle.width = col.Width + 'px';
		col.OriginalWidth = col.Width;
	}
};

//***********************************************
//******** COOKIE OPERATIONS ********************
//***********************************************

function getAdiamorCookie()
{
	var ca = document.cookie.split(';');
	var cookieValues = [];
	for(var i=0; i < ca.length; i++)
	{
		var c = ca[i].replace(/\s/g,'');
		if(c.indexOf("adiamor") == 0 && c.indexOf("adiamor2") != 0 && c.indexOf("Adiamor2") != 0)
		{
			cookieValues = unescape(c.substring(("adiamor=").length, c.length)).split(";");
		}	
    }
    return cookieValues;
}

/**
 * Creates a cookie with the given name and value and exiry time.
 */
function createCookie(name, value, days)
{
	var expires;
	if (days)
	{
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		expires = "; expires="+date.toGMTString();
    }
	else { expires = ""; }

	var cookieValues = getAdiamorCookie();

	var destroy = (value == null || value == "null" || value == "");
	var found = false;
	var nameEQ = name + "=";
	for(var i=0; i < cookieValues.length; i++)
	{
		var c = cookieValues[i].replace(/\s/g,'');
		if(c.indexOf(nameEQ) == 0)
		{
			found = true;
			cookieValues[i] = name + "=" + value;
			if (destroy) { cookieValues.splice(i,1); }
		}
    }
    if (!found && !destroy)
    {
    	cookieValues.push(name + "=" + value);
    }

	document.cookie = "adiamor=" + escape(cookieValues.join(";")) + expires + "; path=/";
}

/**
 * Reads the value of the cookie with the specified name
 */
function readCookie(name)
{
	var cookieValues = getAdiamorCookie();

	var nameEQ = name + "=";
	for(var i=0; i < cookieValues.length; i++)
	{
		var c = cookieValues[i].replace(/\s/g,'');
		if(c.indexOf(nameEQ) == 0) { return c.substring(nameEQ.length, c.length); }
    }

	return null;
}

Adiamor.ui.GridList.prototype.mouseClickHandler = function(evtObj, element)
{
	var domCell = this.findCell(evtObj.srcElement);
    if (domCell != null)
    {
		var domRow = domCell.parentNode;
	    if (domRow != null)
	    {
	        var row = domCell.getAttribute("row");
	        var col = domCell.getAttribute("column");
	
			if (this.Columns[col].Name == "Selected")
			{
				var cookieValue, id, id2;
		        
		        if (this.SelectedRows[row] != null)
		        {
		            cookieValue = readCookie("compare");
		            id = "D|" + this.DataSource.data[row][this.ColumnsMap.ID] + "-";
		            id2 = "T|" + this.DataSource.data[row][this.ColumnsMap.ID] + "-";
		            
		            if(cookieValue != null)
		            {
						cookieValue = cookieValue.replace(id, id2);
						createCookie("compare", cookieValue, 90);
					}	
		            
		            this.setRowClass(this.SelectedRows[row], row);
		            delete this.SelectedRows[row];
		        }
		        else
		        {
					cookieValue = readCookie("compare") || "";
		            id = "D|" + this.DataSource.data[row][this.ColumnsMap.ID] + "-";
		            id2 = "T|" + this.DataSource.data[row][this.ColumnsMap.ID] + "-";
		            
		            cookieValue = cookieValue.replace(id2, id);
		            createCookie("compare", cookieValue, 90);
		            
		            domRow.className = "gridlist-rowselected";
		            this.SelectedRows[row] = domRow;
		        }
		        
		        var count = 0;
				for (var item in this.SelectedRows)
				{
					count++;
				}
				
				$('numCompare').innerHTML=count+" Diamonds";
			}
			else
			{
				window.open("D-"+this.DataSource.data[row][this.ColumnsMap.ID]+".htm", '_self');
			}
	    }
    }
};

Adiamor.ui.GridList.prototype.setRowClass = function(rowElement, rowNumber)
{
    var className = "ListDataRow";
    if (rowNumber % 2 == 0) { className = "ListDataRowAlt"; }

    rowElement.className = className;
};

Adiamor.ui.GridList.prototype.mouseOverHandler = function(evtObj, element)
{
    var domRow = this.findRow(evtObj.srcElement);
    var domCell = this.findCell(evtObj.srcElement);
    if (domCell != null && domRow != null)
    {
		var newRow = domRow.getAttribute("row");
		var newColumn = domCell.getAttribute("column");

        if (this.MouseOverRow != newRow || this.MouseOverColumn != newColumn)
        {
        	this.OnMouseOver.notify({'row':domRow,'cell':domCell,'event':evtObj});
        	this.MouseOverRow = newRow;
        }
    }
};

Adiamor.ui.GridList.prototype.mouseOutHandler = function(evtObj, element)
{
	var domCell = this.findRow(evtObj.srcElement);
    var toElement = this.findRow(evtObj.toElement);
    // Check if the toElement is not a valid row yet somehow it can still be the document...
	if ((toElement == null || toElement.nodeType == 9))
	{
		this.OnMouseOut.notify({'row':domCell});
		this.MouseOverRow = null;
		this.MouseOverColumn = null;
	}
};

function findElement(elem, type)
{
	var breakOut = 5;
	for (var i=0; i<breakOut && (elem != null && elem.getAttribute && elem.getAttribute('Adiamortype') != type); i++) 
	{
		elem = elem.parentNode;
	}
	//	Do a quick check to see if we maxed out on trying to find the proper grid tag.
	if (i==breakOut || elem == document)
	{
		elem = null;
	}
	return elem;
}

Adiamor.ui.GridList.prototype.findRow = function(elem)
{
	return findElement(elem, 'row');
};

Adiamor.ui.GridList.prototype.findCell = function(elem)
{
	return findElement(elem, 'cell');
};

Adiamor.ui.GridList.prototype.setDataSource = function(datasource)
{
	this.DataSource = datasource;
	if (typeof this.DataSource == "object" && this.DataSource.OnRowCountChanged != null)
	{
		this.DataSource.OnRowCountChanged.subscribe(this.setRowCount, this);
		this.DataSource.OnDataReady.subscribe(this.View.render, this.View);
	}
	this.OnDataSourceConnected.notify(this.DataSource);
};

Adiamor.ui.GridList.prototype.setRowCount = function(rows)
{
	this.RowCount = rows;
	this.View.rows = rows;
	this.View.clear();
	// Add one so that the scrollbar always appears
	var newHeight = Math.max(rows * this.RowHeight, this.View.frame.clientHeight+1);
	this.View.setSurfaceHeight(newHeight);
	this.Scrollbar.setRange(newHeight);
};

Adiamor.ui.GridList.prototype.setScrollbar = function(scrollbar)
{
	this.Scrollbar = scrollbar;
	this.Scrollbar.OnScroll.subscribe(this.scrollVertical, this);
	this.OnScrollVertical.subscribe(this.Scrollbar.setScrollPercent, this.Scrollbar);
};

Adiamor.ui.GridList.prototype.scrollVertical= function(percent)
{
	var origPct = this.scrollVerticalPercent;
	this.scrollVerticalPercent = percent;
	this.View.setScrollTopPercent(percent);
	this.OnScrollVertical.notify(percent);
};

Adiamor.ui.GridList.prototype.attachToParent = function(HtmlContainer, HtmlElement)
{
	this.HtmlContainer = HtmlContainer;
	this.HtmlElement = HtmlElement || Adiamor.html.getFirstChild(this.HtmlContainer.firstChild);
	if (this.HtmlElement == null) { this.render(); }

	// Attach events
};

Adiamor.ui.GridList.prototype.getColumns = function()
{
	return this.Columns;
};

Adiamor.ui.GridList.prototype.dispose = function()
{
	Adiamor.ui.GridList.base.dispose.call(this);
};

Adiamor.ui.GridListColumnHeader = function()
{
    this.Columns = null;
    this.Container = null;
    this.OnClick = new Adiamor.base.SubjectHelper();
};

Adiamor.lang.extend(Adiamor.ui.GridListColumnHeader, Adiamor.ui.Panel);

Adiamor.ui.GridListColumnHeader.prototype.attachToParent = function(container)
{
    this.Container = container;
    this.render();
};

Adiamor.ui.GridListColumnHeader.prototype.render = function()
{
    var s = [];
    s.push("<table id=\"Adiamor-ui-gridlistcolumnheader\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\"><tr>");
    for (var i=0; i<this.Columns.length; i++)
    {
    	var clazz = '';
    	if (i == this.SortColumn) { clazz = 'gridlist-columnheader-sort'+this.SortDirection; }
        s.push("<td id=\"gridlist-columnheader"+i+"\" class=\"gridlist-columnheader"+i+" gridlist-column"+i+" "+clazz+"\" Adiamortype=\"header\" column=\""+i+"\"><div class=\"gridlist-columnheader gridlist-column"+i+"\">"+this.Columns[i].Label+"</div></td>");
    }
    s.push("</tr></table>");
    s = s.join("");
    this.Container.innerHTML = s;

	Adiamor.html.attachEvent($('Adiamor-ui-gridlistcolumnheader'), 'click', this.mouseClickHandler, this);
};

Adiamor.ui.GridListColumnHeader.prototype.mouseClickHandler = function(evtObj, element)
{
	var domCell = this.findHeader(evtObj.srcElement);
	if (domCell != null)
	{
		this.OnClick.notify(domCell.getAttribute("column"));
	}
};

Adiamor.ui.GridListColumnHeader.prototype.findHeader = function(elem)
{
	return findElement(elem, 'header');
};

Adiamor.ui.GridListColumn = function(values)
{
	this.Name = "";
	this.Label = "";
	this.Width = 100;
	this.DataField = "";
	this.Display = true;
	this.Type = "text";
	this.Template = "{$Value}";
	this.setValues(values);
};

Adiamor.lang.extend(Adiamor.ui.GridListColumn, Adiamor.base.Object);


Adiamor.ui.Slider = function(values)
{
    this.uid = Adiamor.base.getUid();
    this.Container = null;
    this.LeftStart = 0;
    this.RightStart = 0;
    this.LeftGrabby = null;
    this.RightGrabby = null;
    this.LeftOverlay = null;
    this.RightOverlay = null;
    this.Max = 100;
    this.Min = 0;
    this.Ticks = 10;
    this.Width = 230;
    this.Height = 47;
    this.OverlayHeight = null;
    this.OnRangeChanged = new Adiamor.base.SubjectHelper();
    this.OnStartDrag = new Adiamor.base.SubjectHelper();
    this.OnDrag = new Adiamor.base.SubjectHelper();
    this.Discrete = false;
    this.GrabbyWidth = 15;
    this.GrabbyHeight = 53;
    this.ElementClassName = '';
    this.ClassPostFix = "";
    this.Coords = null;
    this.TooltipEnabled = false;
    this.LeftTooltipOffsetTop = -10;
    this.RightTooltipOffsetTop = -10;
    this.LeftTooltipOffsetLeft = 0;
    this.RightTooltipOffsetLeft = 0;
    this.Slope = 1;

	this.LeftTooltip = null;
    this.setValues(values);

	this.LeftValue = this.Min;
	this.RightValue = this.Max;
	
	if (this.OverlayHeight == null) { this.OverlayHeight = this.Height; }
};

Adiamor.lang.extend(Adiamor.ui.Slider, Adiamor.ui.Element);

/**
 * Attaches the slider to a DOM node.
 */
Adiamor.ui.Slider.prototype.attachToParent = function(container)
{
    this.Container = container;
    this.render();
};


function exchangeSetter(method1, method2, object1, object2, filter)
{
	var srcMethod = object1[method1];
	if (filter instanceof Function)
	{
		object1[method1] = function()
		{
			val = filter.apply(this, arguments);
			return method2.apply(object2, arguments);
		};
	}
	else
	{
		object1[method1] = function()
		{
			return method2.apply(object2, arguments);
		};
	}
}

function exchangeGetter(method1, method2, object1, object2, filter)
{
	var srcMethod = object1[method1];
	if (filter instanceof Function)
	{
		object1[method1] = function()
		{
			var val = method2.call(object2);
			val = filter.call(this, val);
			return val;
		};
	}
	else
	{
		object1[method1] = function()
		{
			var val = method2.call(object2);
			return val;
		};
	}
}

function highlightTooltip(evtArgs, elem, saveState, fragment)
{
	this.style.border="1px solid gray";
}
function dimTooltip(evtArgs, elem, saveState, fragment)
{
	this.style.border="1px solid gray";
}

/**
 * Generates the HTML for the slider and inserts it into the web page.
 */
Adiamor.ui.Slider.prototype.render = function()
{
    var s = '<div id="ntb-slider'+this.uid+'" class="slider-bg-repeat slider-element'+this.ClassPostFix+' '+this.ElementClassName+'" style="width:'+this.Width+'px;height:'+this.Height+'px;">';
	
    var type = this.ElementClassName.substring(7);
	/*if(type=="polish" || type=="sym" || type=="depth" || type=="table" || type=="size" || type=="fluor")
	{
		if(!Adiamor.browser.SAFARI && !Adiamor.browser.MOZ) //&& !Adiamor.browser.IE8)
		{
			s += '  <div style="position:relative;top:0;left:1;z-index:120;">';
		}	
		else
		{
			s += '  <div style="position:relative;top:0;padding-left: 24px;posLeft:24;left:0;z-index:120;">';
		}	
		s += '		<div id="ntb-slider-to'+this.uid+'" class="slider-overlay'+this.ClassPostFix+'" style="width:'+this.GrabbyWidth+'px;height:0px;z-index:105;"></div>';
		s += '		<div id="ntb-slider-tg'+this.uid+'" class="slider-grabby'+this.ClassPostFix+' slider-grabbytop'+this.ClassPostFix+'" style="margin: 0px; overflow: hidden; width:'+this.GrabbyWidth+'px;height:'+this.GrabbyHeight+'px;z-index:120;"></div>';
		s += '	</div>';
		if(!Adiamor.browser.SAFARI && !Adiamor.browser.MOZ) //&& !Adiamor.browser.IE8)
		{
			s += '  <div style="position:absolute;top:0;left:24;z-index:110;">';
		}	
		else
		{
			s += '  <div style="position:absolute;top:0;padding-left: 24px;posLeft:24;left:24;z-index:110;">';
		}	
		s += '		<div id="ntb-slider-bo'+this.uid+'" class="slider-overlay'+this.ClassPostFix+'" style="width:'+this.GrabbyWidth+'px;height:0px;z-index:105;"></div>';
		s += '		<div id="ntb-slider-bg'+this.uid+'" class="slider-grabby'+this.ClassPostFix+' slider-grabbybottom'+this.ClassPostFix+'" style="margin: 0px; overflow: hidden; width:'+this.GrabbyWidth+'px;height:'+this.GrabbyHeight+'px;z-index:110;"></div>';
		s += '	</div>';
		if (this.TooltipEnabled && !Adiamor.browser.SAFARI)
		{
			s += '	<input tabindex="'+ti+'" type="text" id="ntb-slider-tt'+this.uid+'" style="text-align:center;border:1px solid gray;z-index:125;line-height:10px;font-size:10px;font-family:arial, sans-serif;height:10px;width:44px;position:absolute;left:'+(this.TopTooltipOffsetLeft)+'px;top:'+(this.TopTooltipOffsetTop)+'px;" />';
			ti++;
			s += '	<input tabindex="'+ti+'" type="text" id="ntb-slider-bt'+this.uid+'" style="text-align:center;border:1px solid gray;z-index:125;line-height:10px;font-size:10px;font-family:arial, sans-serif;height:10px;width:44px;position:absolute;left:'+(this.BottomTooltipOffsetLeft)+'px;top:'+(this.BottomTooltipOffsetTop)+'px;" />';
			ti++;
		}
		else if(this.TooltipEnabled)
		{
			s += '	<input tabindex="'+ti+'" type="text" id="ntb-slider-tt'+this.uid+'" style="text-align:center;border:1px solid gray;line-height:10px;font-size:10px;font-family:arial, sans-serif;height:10px;width:44px;position:absolute;left:'+(this.TopTooltipOffsetLeft)+'px;top:'+(this.TopTooltipOffsetTop)+'px;" />';
			ti++;
			s += '	<input tabindex="'+ti+'" type="text" id="ntb-slider-bt'+this.uid+'" style="text-align:center;border:1px solid gray;line-height:10px;font-size:10px;font-family:arial, sans-serif;height:10px;width:44px;position:absolute;left:'+(this.BottomTooltipOffsetLeft)+'px;top:'+(this.BottomTooltipOffsetTop)+'px;" />';
			ti++;
		}
		s += '</div>';
	}	
	else
	{*/
		var inputWidth = "55";
		if(type=="depth" || type=="table")
		{
			inputWidth = "41";
		}
			
		if(Adiamor.browser.IE6)
		{
			s += '	<div id="ntb-slider-lo'+this.uid+'" class="slider-overlay-ie6" style="float:left;width:0px;height:'+this.OverlayHeight+'px;"></div>';
		}	
		else
		{
			s += '	<div id="ntb-slider-lo'+this.uid+'" class="slider-overlay'+this.ClassPostFix+'" style="float:left;width:0px;height:'+this.OverlayHeight+'px;"></div>';
		}	
		s += '	<div id="ntb-slider-lg'+this.uid+'" class="slider-grabby slider-grabbyleft'+this.ClassPostFix+'" style="float:left;z-index:452;width:'+this.GrabbyWidth+'px;height:'+this.GrabbyHeight+'px;"></div>';

		if(Adiamor.browser.IE6)
		{
			s += '	<div id="ntb-slider-ro'+this.uid+'" class="slider-overlay-ie6" style="float:right;width:0px;height:'+this.OverlayHeight+'px;"></div>';
		}	
		else
		{
			s += '	<div id="ntb-slider-ro'+this.uid+'" class="slider-overlay'+this.ClassPostFix+'" style="float:right;width:0px;height:'+this.OverlayHeight+'px;"></div>';
		}	
		s += '	<div id="ntb-slider-rg'+this.uid+'" class="slider-grabby slider-grabbyright'+this.ClassPostFix+'" style="float:right;z-index:452;width:'+this.GrabbyWidth+'px;height:'+this.GrabbyHeight+'px;"></div>';
		
		if (this.TooltipEnabled && !Adiamor.browser.SAFARI && !Adiamor.browser.MOZ)
		{
			s += '	<input tabindex="'+ti+'" type="text" id="ntb-slider-lt'+this.uid+'" style="text-align:center;border:1px solid gray;line-height:10px;font-size:10px;font-family:arial, sans-serif;height:10px;width:'+inputWidth+'px;position:absolute;left:'+(this.LeftTooltipOffsetLeft)+'px;top:'+(this.LeftTooltipOffsetTop+this.Height)+'px;float:left;" />';
			ti++;
			s += '	<input tabindex="'+ti+'" type="text" id="ntb-slider-rt'+this.uid+'" style="text-align:center;border:1px solid gray;line-height:10px;font-size:10px;font-family:arial, sans-serif;height:10px;width:'+inputWidth+'px;position:absolute;left:'+(this.RightTooltipOffsetLeft+this.Width)+'px;top:'+(this.RightTooltipOffsetTop+this.Height)+'px;float:right;" />';
			ti++;
		}
		else if (this.TooltipEnabled && !Adiamor.browser.SAFARI && Adiamor.browser.MOZ)
		{
			s += '	<input tabindex="'+ti+'" type="text" id="ntb-slider-lt'+this.uid+'" style="text-align:center;padding-bottom: 3px;border:1px solid gray;line-height:10px;font-size:10px;font-family:arial, sans-serif;height:10px;width:'+inputWidth+'px;position:absolute;left:'+(this.LeftTooltipOffsetLeft)+'px;top:'+(this.LeftTooltipOffsetTop+this.Height)+'px;float:left;" />';
			ti++;
			s += '	<input tabindex="'+ti+'" type="text" id="ntb-slider-rt'+this.uid+'" style="text-align:center;padding-bottom: 3px;border:1px solid gray;line-height:10px;font-size:10px;font-family:arial, sans-serif;height:10px;width:'+inputWidth+'px;position:absolute;left:'+(this.RightTooltipOffsetLeft+this.Width)+'px;top:'+(this.RightTooltipOffsetTop+this.Height)+'px;float:right;" />';
			ti++;
		}
		else if(this.TooltipEnabled)
		{
			s += '	<input tabindex="'+ti+'" type="text" id="ntb-slider-lt'+this.uid+'" style="text-align:center;border:1px solid gray;line-height:10px;font-size:10px;font-family:arial, sans-serif;height:10px;width:'+inputWidth+'px;position:absolute;left:'+(this.LeftTooltipOffsetLeft)+'px;top:'+(this.LeftTooltipOffsetTop+this.Height)+'px;float:left;" />';
			ti++;
			s += '	<input tabindex="'+ti+'" type="text" id="ntb-slider-rt'+this.uid+'" style="text-align:center;border:1px solid gray;line-height:10px;font-size:10px;font-family:arial, sans-serif;height:10px;width:'+inputWidth+'px;position:absolute;left:'+(this.RightTooltipOffsetLeft+this.Width)+'px;top:'+(this.RightTooltipOffsetTop+this.Height)+'px;float:right;" />';
			ti++;
		}
		s += '</div>';
	//}

    this.Container.innerHTML = s;

    this.Element = $('ntb-slider'+this.uid);

	// Make the slider background clickable
	Adiamor.html.attachEvent(this.Element, "mousedown", this.handleSliderClick, this);

    this.setBounds();

	//handleMouseover is written to work with the sliders themselves.  handleMouseoverP is for the containers
	//and their siblings (which includes the labels)
	
	/*Adiamor.html.attachEvent(this.Element, "mouseover", this.handleMouseover, this);
    Adiamor.html.attachEvent(this.Element, "mouseout", this.handleMouseout, this);*/
    
    if(this.ClassPostFix != "-small")
    {
		var parent = null;
		if(typeof(this.Element.parentElement) != "undefined")
		{
			parent = this.Element.parentElement.parentElement;
		}
		else
		{
			parent = this.Element.parentNode.parentNode;
		}
	    
		Adiamor.html.attachEvent(parent, "mouseover", this.handleMouseoverP, this);
		Adiamor.html.attachEvent(parent, "mouseout", this.handleMouseoutP, this);
    }

	/*if(type=="polish" || type=="sym" || type=="depth" || type=="table" || type=="size" || type=="fluor")
	{
		this.BottomGrabby = new Adiamor.ui.Element(null, null, 'ntb-slider-bg'+this.uid);
		this.BottomGrabby.Position = 'Bottom';

		this.TopGrabby = new Adiamor.ui.Element(null, null, 'ntb-slider-tg'+this.uid);
		this.TopGrabby.Position = 'Top';

		this.BottomOverlay = new Adiamor.ui.Element(null, null, 'ntb-slider-bo'+this.uid);
		this.TopOverlay = new Adiamor.ui.Element(null, null, 'ntb-slider-to'+this.uid);

		// Make the overlay area clickable to move the grabby
		//Adiamor.html.attachEvent(this.BottomOverlay.m_HtmlElementHandle, "click", this.handleBottomOverlayClick, this);
		Adiamor.html.attachEvent(this.TopOverlay.m_HtmlElementHandle, "click", this.handleTopOverlayClick, this);

		// Make the grabby cancel any click events.
		Adiamor.html.attachEvent(this.BottomGrabby.m_HtmlElementHandle, "click", function(evtArgs){Adiamor.html.cancelEvent(evtArgs);}, this);
		Adiamor.html.attachEvent(this.TopGrabby.m_HtmlElementHandle, "click", function(evtArgs){Adiamor.html.cancelEvent(evtArgs);}, this);

		// makeDraggable simply adds some methods / properties to an object that the DD manager expects.
		Adiamor.ui.IDraggable.makeDraggable(this.BottomGrabby, this.BottomGrabby.m_HtmlElementHandle);
		Adiamor.ui.IDraggable.makeDraggable(this.TopGrabby, this.TopGrabby.m_HtmlElementHandle);
	
		this.BottomGrabbyDD = new Adiamor.ui.DragDrop(this.BottomGrabby, true, false);
		this.TopGrabbyDD = new Adiamor.ui.DragDrop(this.TopGrabby, true, false);

	//    this.BottomGrabbyDD.setYBounds(this.MinYCoord, this.MaxYCoord - this.GrabbyWidth);
		this.BottomGrabbyDD.setYBounds(this.MinYCoord, this.MaxYCoord + this.GrabbyHeight*2);
		this.BottomGrabbyDD.OnDragStop.subscribe(this.stopBottomDrag, this);

	//    this.TopGrabbyDD.setYBounds(this.MinYCoord + this.GrabbyWidth, this.MaxYCoord);
		this.TopGrabbyDD.setYBounds(this.MinYCoord - this.GrabbyHeight*2, this.MaxYCoord + this.GrabbyHeight);
		this.TopGrabbyDD.OnDragStop.subscribe(this.stopTopDrag, this);

		if (this.TooltipEnabled)
		{
			this.BottomTooltip = new Adiamor.ui.Element(null, null, 'ntb-slider-bt'+this.uid);
			this.TopTooltip = new Adiamor.ui.Element(null, null, 'ntb-slider-tt'+this.uid);    

			Adiamor.html.attachEvent(this.BottomTooltip.m_HtmlElementHandle, "blur", this.updateBottomGrabby, this);
			Adiamor.html.attachEvent(this.TopTooltip.m_HtmlElementHandle, "blur", this.updateTopGrabby, this);

			Adiamor.html.attachEvent(this.BottomTooltip.m_HtmlElementHandle, "focus", this.focusBottomGrabby, this);
			Adiamor.html.attachEvent(this.TopTooltip.m_HtmlElementHandle, "focus", this.focusTopGrabby, this);
			
			//Adiamor.html.attachEvent(this.BottomTooltip.m_HtmlElementHandle, 'mouseover', highlightTooltip);
			//Adiamor.html.attachEvent(this.TopTooltip.m_HtmlElementHandle, 'mouseover', highlightTooltip);
			
			//Adiamor.html.attachEvent(this.BottomTooltip.m_HtmlElementHandle, 'mouseout', dimTooltip);
			//Adiamor.html.attachEvent(this.TopTooltip.m_HtmlElementHandle, 'mouseout', dimTooltip);
			
			Adiamor.html.attachEvent(this.BottomTooltip.m_HtmlElementHandle, "keydown", function(evtArgs){if (evtArgs.keyCode == 13) {this.blur();}}, this.BottomTooltip.m_HtmlElementHandle);
			Adiamor.html.attachEvent(this.TopTooltip.m_HtmlElementHandle, "keydown", function(evtArgs){if (evtArgs.keyCode == 13) {this.blur();}}, this.TopTooltip.m_HtmlElementHandle);

			exchangeSetter("setY", this.setBottomGrabbyYT, this.BottomGrabby, this);
			exchangeSetter("setY", this.setTopGrabbyYT, this.TopGrabby, this);
		}
		else
		{
			exchangeSetter("setY", this.setBottomGrabbyY, this.BottomGrabby, this);
			exchangeSetter("setY", this.setTopGrabbyY, this.TopGrabby, this);
		}

		this.offset = 2;
		this.BottomGrabby.setY(0);
		this.TopGrabby.setY(0);

		//this.BottomGrabby.getY = Adiamor.lang.close(this.BottomOverlay, this.BottomOverlay.getHeight);

		exchangeGetter("getY", this.TopOverlay.getHeight, this.TopGrabby, this.TopOverlay, function(val) {return -parseInt(val,10);});
		exchangeGetter("getY", this.BottomOverlay.getHeight, this.BottomGrabby, this.BottomOverlay, function(val) {return -parseInt(val,10);});

		Adiamor.html.attachEvent(this.BottomGrabby.m_HtmlElementHandle, "mousedown", this.startDragBottom, this);
		Adiamor.html.attachEvent(this.TopGrabby.m_HtmlElementHandle, "mousedown", this.startDragTop, this);

	}
	else
	{*/
		this.LeftGrabby = new Adiamor.ui.Element(null, null, 'ntb-slider-lg'+this.uid);
		this.LeftGrabby.Position = 'Left';
		
		this.RightGrabby = new Adiamor.ui.Element(null, null, 'ntb-slider-rg'+this.uid);
		this.RightGrabby.Position = 'Right';

		this.LeftOverlay = new Adiamor.ui.Element(null, null, 'ntb-slider-lo'+this.uid);
		this.RightOverlay = new Adiamor.ui.Element(null, null, 'ntb-slider-ro'+this.uid);

		// Make the overlay area clickable to move the grabby
		Adiamor.html.attachEvent(this.LeftOverlay.m_HtmlElementHandle, "click", this.handleLeftOverlayClick, this);
		Adiamor.html.attachEvent(this.RightOverlay.m_HtmlElementHandle, "click", this.handleRightOverlayClick, this);

		// Make the grabby cancel any click events.
		Adiamor.html.attachEvent(this.LeftGrabby.m_HtmlElementHandle, "click", function(evtArgs){Adiamor.html.cancelEvent(evtArgs);}, this);
		Adiamor.html.attachEvent(this.RightGrabby.m_HtmlElementHandle, "click", function(evtArgs){Adiamor.html.cancelEvent(evtArgs);}, this);

		// makeDraggable simply adds some methods / properties to an object that the DD manager expects.
		Adiamor.ui.IDraggable.makeDraggable(this.LeftGrabby, this.LeftGrabby.m_HtmlElementHandle);
		Adiamor.ui.IDraggable.makeDraggable(this.RightGrabby, this.RightGrabby.m_HtmlElementHandle);

		this.LeftGrabbyDD = new Adiamor.ui.DragDrop(this.LeftGrabby, false, true);
		this.RightGrabbyDD = new Adiamor.ui.DragDrop(this.RightGrabby, false, true);

	//    this.LeftGrabbyDD.setXBounds(this.MinXCoord, this.MaxXCoord - this.GrabbyWidth);
		this.LeftGrabbyDD.setXBounds(this.MinXCoord - this.GrabbyWidth/2, this.MaxXCoord - this.GrabbyWidth/2);
		this.LeftGrabbyDD.OnDragStop.subscribe(this.stopLeftDrag, this);

	//    this.RightGrabbyDD.setXBounds(this.MinXCoord + this.GrabbyWidth, this.MaxXCoord);
		this.RightGrabbyDD.setXBounds(this.MinXCoord + this.GrabbyWidth/2, this.MaxXCoord + this.GrabbyWidth/2);
		this.RightGrabbyDD.OnDragStop.subscribe(this.stopRightDrag, this);

		if (this.TooltipEnabled)
		{
			this.LeftTooltip = new Adiamor.ui.Element(null, null, 'ntb-slider-lt'+this.uid);
			this.RightTooltip = new Adiamor.ui.Element(null, null, 'ntb-slider-rt'+this.uid);    

			Adiamor.html.attachEvent(this.LeftTooltip.m_HtmlElementHandle, "blur", this.updateLeftGrabby, this);
			Adiamor.html.attachEvent(this.RightTooltip.m_HtmlElementHandle, "blur", this.updateRightGrabby, this);

			Adiamor.html.attachEvent(this.LeftTooltip.m_HtmlElementHandle, "focus", this.focusLeftGrabby, this);
			Adiamor.html.attachEvent(this.RightTooltip.m_HtmlElementHandle, "focus", this.focusRightGrabby, this);
			
			//Adiamor.html.attachEvent(this.LeftTooltip.m_HtmlElementHandle, 'mouseover', highlightTooltip);
			//Adiamor.html.attachEvent(this.RightTooltip.m_HtmlElementHandle, 'mouseover', highlightTooltip);
			
			//Adiamor.html.attachEvent(this.LeftTooltip.m_HtmlElementHandle, 'mouseout', dimTooltip);
			//Adiamor.html.attachEvent(this.RightTooltip.m_HtmlElementHandle, 'mouseout', dimTooltip);

			Adiamor.html.attachEvent(this.LeftTooltip.m_HtmlElementHandle, "keydown", function(evtArgs){if (evtArgs.keyCode == 13) {this.blur();}}, this.LeftTooltip.m_HtmlElementHandle);
			Adiamor.html.attachEvent(this.RightTooltip.m_HtmlElementHandle, "keydown", function(evtArgs){if (evtArgs.keyCode == 13) {this.blur();}}, this.RightTooltip.m_HtmlElementHandle);

			exchangeSetter("setX", this.setLeftGrabbyXT, this.LeftGrabby, this);
			exchangeSetter("setX", this.setRightGrabbyXT, this.RightGrabby, this);
		}
		else
		{
			exchangeSetter("setX", this.setLeftGrabbyX, this.LeftGrabby, this);
			exchangeSetter("setX", this.setRightGrabbyX, this.RightGrabby, this);
		}

		this.LeftGrabby.setX(0);
		this.RightGrabby.setX(0);

		this.LeftGrabby.getX = Adiamor.lang.close(this.LeftOverlay, this.LeftOverlay.getWidth);

		exchangeGetter("getX", this.RightOverlay.getWidth, this.RightGrabby, this.RightOverlay, function(val) {return -parseInt(val,10);});

		Adiamor.html.attachEvent(this.LeftGrabby.m_HtmlElementHandle, "mousedown", this.startDragLeft, this);
		Adiamor.html.attachEvent(this.RightGrabby.m_HtmlElementHandle, "mousedown", this.startDragRight, this);

		this.offset = 2;

		if(this.Discrete && this.ElementClassName.indexOf("mini") == -1) { this.offset = 5; }
	//}
};

Adiamor.ui.Slider.prototype.updateLeftGrabby = function(evtObj)
{
	var val = this.LeftTooltip.m_HtmlElementHandle.value.replace(/[^0-9|\.]/gi,'');
	
	if(val != tooltip)
	{
		if(val.substring(0,1) == '.') { val = "0"+val; }
		if (parseValues(this.getMaxValue()) >= parseValues(val))
		{
			this.setMinValue(val);
		}
		else
		{
			this.setMinValue(this.getMaxValue());
			this.setMaxValue(val);
		}
		this.stopLeftDrag({"DragElement":this.LeftGrabby,"Event":evtObj,"Tooltip":true});
	}	
	tooltip = null;
};

Adiamor.ui.Slider.prototype.focusLeftGrabby = function(evtObj)
{
	var val = this.LeftTooltip.m_HtmlElementHandle.value.replace(/[^0-9|\.]/gi,'');
	
	tooltip = val;
};

Adiamor.ui.Slider.prototype.updateRightGrabby = function(evtObj)
{
	var val = this.RightTooltip.m_HtmlElementHandle.value.replace(/[^0-9|\.]/gi,'');
	
	if(val != tooltip)
	{
		if(val.substring(0,1) == '.') { val = "0"+val; }
		// convert this.RightGrabbyDD.minX to a relative value across the slider eg 0.25
		if (parseValues(this.getMinValue()) <= parseValues(val))
		{
			this.setMaxValue(val);
		}
		else
		{
			this.setMaxValue(this.getMinValue());
			this.setMinValue(val);
		}
		this.stopRightDrag({"DragElement":this.RightGrabby,"Event":evtObj,"Tooltip":true});
	}
	tooltip = null;
};

Adiamor.ui.Slider.prototype.focusRightGrabby = function(evtObj)
{
	var val = this.RightTooltip.m_HtmlElementHandle.value.replace(/[^0-9|\.]/gi,'');
	tooltip = val;
};

Adiamor.ui.Slider.prototype.setLeftGrabbyX = function(val)
{
	var step = Math.floor((this.getWidth())/this.Ticks);
	if(isNaN(val))
	{
		val = 0;
	}

	if (this.Discrete)
	{
		var mod = (val % step);
		var div = Math.floor(val / step);

		// Snap the x value here
		if (val > (div * step + step/2)) { val = (div+1)*step; }
		else if (val <= div * step + step/2) { val = (div)*step; }
		
		if ((val + 6) > (this.getWidth() + this.RightGrabby.getX()))
		{
			val -= step;
		}
		
		if(val != 0)
		{
			val += 6;
		}
	}
	
	var anum=/(^\d+$)|(^\d+\.\d+$)/;
	if (anum.test(val))
	{
		this.LeftOverlay.m_HtmlElementHandle.style.width = (Math.max(0,val))+'px';
		if(this.ClassPostFix == "-small")
		{
			this.RightGrabbyDD.setMinX(val + this.MinXCoord + this.GrabbyWidth/2 + 10);
		}
		else
		{
			this.RightGrabbyDD.setMinX(val + this.MinXCoord + this.GrabbyWidth/2);
		}
	}
};

Adiamor.ui.Slider.prototype.setLeftGrabbyXT = function(val, displayValue)
{
	val = Math.round(val);
	this.setLeftGrabbyX(val);

	//if(this.ClassPostFix!="-small")
	//{
		this.LeftTooltip.setX(Math.min(Math.max(val + this.LeftTooltipOffsetLeft, 0), this.getWidth()-90));
	//}
	this.LeftTooltip.m_HtmlElementHandle.value = this.formatTooltipValue(displayValue || Math.max(this.getValueFunction(val/this.getWidth()),this.Min));
	
	
	var ca = document.cookie.split(';');
	var currency;
	for(var i=0; i < ca.length; i++)
	{
		var c = ca[i].replace(/\s/g,'');
		if(c.indexOf("country") == 0) { currency = unescape(c.substring(("country=").length, c.length)); }
	}
	
	if(currency == "BP")
	{
		this.LeftTooltip.m_HtmlElementHandle.value = this.LeftTooltip.m_HtmlElementHandle.value.replace('$','\u00A3');
	}
};

Adiamor.ui.Slider.prototype.setRightGrabbyX = function(val)
{
	var step = Math.floor((this.getWidth())/this.Ticks);
	if(isNaN(val))
	{
		val = 0;
	}

	if (this.Discrete)
	{
		var mod = (val % step);
		var div = Math.floor(val / step);
	
		// Snap the x value here
		if (val > (div * step + step/2)) { val = (div+1)*step; }
		else if (val <= div * step + step/2) { val = (div)*step; }
		
		if ((this.LeftGrabby.getX() + 6) > this.getWidth() + val)
		{
			val += step;
		}

		if(val != 0)
		{
			val -= 6;
		}
	}
		
	//var anum=/(^\d+$)|(^\d+\.\d+$)/;
	//if (anum.test(val))
	//{
		this.RightOverlay.setWidth(Math.max(0,-val));
		if(this.ClassPostFix == "-small")
		{
			this.LeftGrabbyDD.setMaxX(this.MinXCoord + this.getWidth() + val - this.GrabbyWidth/2 + 10);
		}
		else
		{
			this.LeftGrabbyDD.setMaxX(this.MinXCoord + this.getWidth() + val - this.GrabbyWidth/2);
		}
	//}
};

Adiamor.ui.Slider.prototype.setRightGrabbyXT = function(val, displayValue)
{
	val = Math.round(val);
	var width = this.getWidth();
	this.setRightGrabbyX(val);
	//if(this.ClassPostFix!="-small")
	//{
		this.RightTooltip.setX(Math.max(Math.min(width + val + this.RightTooltipOffsetLeft, width-30), 60));
	//}
	this.RightTooltip.m_HtmlElementHandle.value = this.formatTooltipValue(displayValue || Math.min(this.getValueFunction((width + val)/width),this.Max));
	
	
	var ca = document.cookie.split(';');
	var currency;
	for(var i=0; i < ca.length; i++)
	{
		var c = ca[i].replace(/\s/g,'');
		if(c.indexOf("country") == 0) { currency = unescape(c.substring(("country=").length, c.length)); }
	}
	
	if(currency == "BP")
	{
		this.RightTooltip.m_HtmlElementHandle.value = this.RightTooltip.m_HtmlElementHandle.value.replace('$','\u00A3');
	}	
};

Adiamor.ui.Slider.prototype.updateBottomGrabby = function(evtObj)
{
	var val = this.BottomTooltip.m_HtmlElementHandle.value.replace(/[^0-9|\.]/gi,'');
	if(tooltip != val)
	{
		if(val.substring(0,1) == '.') { val = "0"+val; }
		if (parseInt(this.getMaxValue(),10) >= parseInt(val,10))
		{
			this.setMinValue(val);
		}
		this.stopBottomDrag({"DragElement":this.BottomGrabby,"Event":evtObj,"Tooltip":true});
	}
	tooltip = null;
};

Adiamor.ui.Slider.prototype.focusBottomGrabby = function(evtObj)
{
	var val = this.BottomTooltip.m_HtmlElementHandle.value.replace(/[^0-9|\.]/gi,'');
	tooltip = val;
};

Adiamor.ui.Slider.prototype.updateTopGrabby = function(evtObj)
{
	var val = this.TopTooltip.m_HtmlElementHandle.value.replace(/[^0-9|\.]/gi,'');
	if(tooltip != val)
	{
		if(val.substring(0,1) == '.') { val = "0"+val; }
		// convert this.RightGrabbyDD.minX to a relative value across the slider eg 0.25
		if (parseInt(this.getMinValue(),10) <= parseInt(val,10))
		{
			this.setMaxValue(val);
		}
		this.stopTopDrag({"DragElement":this.TopGrabby,"Event":evtObj,"Tooltip":true});
	}
	tooltip = null;
};

Adiamor.ui.Slider.prototype.focusTopGrabby = function(evtObj)
{
	var val = this.TopTooltip.m_HtmlElementHandle.value.replace(/[^0-9|\.]/gi,'');
	tooltip = val;
};

Adiamor.ui.Slider.prototype.setBottomGrabbyY = function(val)
{
	var anum=/(^\d+$)|(^\d+\.\d+$)/;
	if (anum.test(val))
	{
		this.BottomOverlay.m_HtmlElementHandle.style.height = (Math.max(0,val))+'px';
		this.TopGrabbyDD.setMinY(this.MaxYCoord + val - this.GrabbyHeight - 5);
	}
};

Adiamor.ui.Slider.prototype.setBottomGrabbyYT = function(val, displayValue)
{
	val = Math.round(val);
	var height = this.getHeight();
	this.setBottomGrabbyY(Math.min(val,(this.getHeight()+2)));
	this.BottomTooltip.setY(Math.min(val + this.BottomTooltipOffsetTop, (this.getHeight()+2 + this.BottomTooltipOffsetTop)));
	
	this.BottomTooltip.m_HtmlElementHandle.value = this.formatTooltipValue(displayValue || Math.max(this.getSmallValueFunction((val - (this.GrabbyHeight*3)+4)/(height - (this.GrabbyHeight*3)+4)),this.Min));
	
	var ca = document.cookie.split(';');
	var currency;
	for(var i=0; i < ca.length; i++)
	{
		var c = ca[i].replace(/\s/g,'');
		if(c.indexOf("country") == 0) { currency = unescape(c.substring(("country=").length, c.length)); }
	}
	
	if(currency == "BP")
	{
		this.BottomTooltip.m_HtmlElementHandle.value = this.BottomTooltip.m_HtmlElementHandle.value.replace('$','\u00A3');
	}	
};

Adiamor.ui.Slider.prototype.setTopGrabbyY = function(val)
{
	this.TopOverlay.setHeight(Math.max(0,val));
	val = Math.max(val,this.GrabbyHeight*1.5);
	if(Adiamor.browser.IE6)
	{
		this.BottomGrabbyDD.setMaxY(this.MaxYCoord + val + this.GrabbyHeight/2 + this.offset);
	}	
	else
	{
		this.BottomGrabbyDD.setMaxY(this.MaxYCoord + val + this.GrabbyHeight/2 - 4 + this.offset);
	}	
};

Adiamor.ui.Slider.prototype.setTopGrabbyYT = function(val, displayValue)
{
	val = Math.round(val);
	var height = this.getHeight();
	
	this.setTopGrabbyY(val);
	this.TopTooltip.setY(Math.max(val + this.TopTooltipOffsetTop, -5));
	
	if(this.Discrete == false)
	{
		this.TopTooltip.m_HtmlElementHandle.value = this.formatTooltipValue(displayValue || Math.min(this.getSmallValueFunction((val - (this.GrabbyHeight*2))/(height - (this.GrabbyHeight*3)+1)),this.Max));
	}
	else
	{
		this.TopTooltip.m_HtmlElementHandle.value = this.formatTooltipValue(displayValue || Math.min(this.getSmallValueFunction((height + val + (this.GrabbyHeight)+1)/height)+this.Min,this.Max));	
	}
		
	var ca = document.cookie.split(';');
	var currency;
	for(var i=0; i < ca.length; i++)
	{
		var c = ca[i].replace(/\s/g,'');
		if(c.indexOf("country") == 0)
		{
			currency = unescape(c.substring(("country=").length, c.length));
		}	
	}
	
	if(currency == "BP")
	{
		this.TopTooltip.m_HtmlElementHandle.value = this.TopTooltip.m_HtmlElementHandle.value.replace('$','\u00A3');
	}	
};

Adiamor.ui.Slider.prototype.formatTooltipValue = function(val)
{
	return val;
};

Adiamor.ui.Slider.prototype.setBounds = function()
{
	var type = this.ElementClassName.substring(7);
	/*if(type=="polish" || type=="sym" || type=="depth" || type=="table" || type=="size" || type=="fluor")
	{
		this.Coords = Adiamor.html.getCoords(this.Element);
	//  this.MinXCoord = this.Coords.x + Math.ceil(this.GrabbyWidth / 2);
		this.MaxYCoord = this.Coords.y + this.GrabbyHeight+3;
		this.MinYCoord = this.MaxYCoord + this.getHeight()-6;
	}
	else
	{*/
		this.Coords = Adiamor.html.getCoords(this.Element);
	//  this.MinXCoord = this.Coords.x + Math.ceil(this.GrabbyWidth / 2);
		this.MinXCoord = this.Coords.x + this.GrabbyWidth;
		this.MaxXCoord = this.MinXCoord + this.getWidth();
	//}
};

/**
 * Begin the drag operation of the LeftGrabby
 */
Adiamor.ui.Slider.prototype.startDragLeft = function(evt)
{
	this.OnStartDrag.notify(this, this.LeftGrabbyDD);
    this.LeftGrabbyDD.startDrag();
    Adiamor.html.cancelEvent(evt);
};

/**
 * Begin the drag operation of the RightGrabby
 */
Adiamor.ui.Slider.prototype.startDragRight = function(evt)
{
	this.OnStartDrag.notify(this, this.RightGrabbyDD);
    this.RightGrabbyDD.startDrag(); 
    Adiamor.html.cancelEvent(evt);
};

/**
 * Stop the drag of the left grabby.
 * This is called from several places including when the user clicks on the slider,
 * when the user drags the slider, and when the user enters a tooltip value.
 */
Adiamor.ui.Slider.prototype.stopLeftDrag = function(evtArgs)
{
	var val = this.LeftGrabby.getX();
	// Move this to a private method to get the left grabby x coord
	var compare = this.Min;
	if (compare > this.Max) { compare = this.Max; }
	if(evtArgs.Tooltip !== true)
	{
		this.LeftValue = Math.max(this.getValueFunction(val/this.getWidth()),compare);
	}	
	this.stopDrag(evtArgs);
};

/**
 * Stop the drag of the right grabby.
 * This is called from several places including when the user clicks on the slider,
 * when the user drags the slider, and when the user enters a tooltip value.
 */
Adiamor.ui.Slider.prototype.stopRightDrag = function(evtArgs)
{
	var val = this.RightGrabby.getX();
	var width = this.getWidth();
	// Move this to a private method to get the right grabby x coord
	var compare = this.Max;
	if (compare < this.Min) { compare = this.Min; }
	if(evtArgs.Tooltip !== true)
	{
		this.RightValue = Math.min(this.getValueFunction((width + val)/width),compare);
	}	
	this.stopDrag(evtArgs);
};

/**
 * Begin the drag operation of the BottomGrabby
 */
Adiamor.ui.Slider.prototype.startDragBottom = function(evt)
{
	this.OnStartDrag.notify(this, this.BottomGrabbyDD);
    this.BottomGrabbyDD.startDrag();
    Adiamor.html.cancelEvent(evt);
};

/**
 * Begin the drag operation of the TopGrabby
 */
Adiamor.ui.Slider.prototype.startDragTop = function(evt)
{
	this.OnStartDrag.notify(this, this.TopGrabbyDD);
    this.TopGrabbyDD.startDrag(); 
    Adiamor.html.cancelEvent(evt);
};

/**
 * Stop the drag of the bottom grabby.
 * This is called from several places including when the user clicks on the slider,
 * when the user drags the slider, and when the user enters a tooltip value.
 */
Adiamor.ui.Slider.prototype.stopBottomDrag = function(evtArgs)
{
	var val = Math.abs(this.BottomGrabby.getY());
	// Move this to a private method to get the left grabby x coord
	var compare = this.Min;
	if (compare > this.Max) { compare = this.Max; }
	if(evtArgs.Tooltip !== true)
	{
		this.BottomValue = Math.max(this.getSmallValueFunction(val/this.getHeight()),compare);
	}	
	this.stopDrag(evtArgs);
};

/**
 * Stop the drag of the top grabby.
 * This is called from several places including when the user clicks on the slider,
 * when the user drags the slider, and when the user enters a tooltip value.
 */
Adiamor.ui.Slider.prototype.stopTopDrag = function(evtArgs)
{
	var val = Math.abs(this.TopGrabby.getY());
	var height = this.getHeight();
	// Move this to a private method to get the right grabby x coord
	var compare = this.Max;
	if (compare < this.Min) { compare = this.Min; }
	if(evtArgs.Tooltip !== true)
	{
		this.TopValue = Math.min(this.getSmallValueFunction(((height + val + (this.GrabbyHeight))/height)-1),compare);
	}	
	this.stopDrag(evtArgs);
};

Adiamor.ui.Slider.prototype.stopDrag = function(evtArgs)
{
	var type = this.ElementClassName.substring(7);
	var evt = evtArgs.Event;
	var Grabby = evtArgs.DragElement;
	var step, y, mod, div;
	var offset = 5;
	
	g_diamondData.setParam('diamond',null);
	
	/*if(type=="polish" || type=="sym" || type=="depth" || type=="table" || type=="size" || type=="fluor")
	{
		step = Math.floor((this.getHeight())/this.Ticks);
		y = Grabby.getY();

		// Snap the grabby into place.
		if (this.Discrete)
		{
			mod = (y % step);
			div = Math.floor(Math.abs(y) / step);

			// Snap the y value here
			if (Math.abs(y) > (div * step + step/2)) { y = (div+1)*step; }
			else if (Math.abs(y) <= div * step + step/2) { y = (div)*step; }

			var bottomoffset = 0;
			var topoffset = 0;
			
			//if (this.ElementClassName == "slider-fluor" && (Grabby.Position == "Bottom" || this.TopValue != "42"))
			//	offset += 4;			
			
			if (Math.abs(this.BottomGrabby.getY() / step) >= Math.abs(this.TopGrabby.getY() / step))
			{
				if (this.ElementClassName == "slider-fluor" && this.TopValue != "42")
				{
					offset += 3;
				}
				if (Grabby.Position == "Bottom") {
					// We are moving the bottom grabby
					if(y <= Math.abs(this.TopGrabby.getY()))
					{
						y += step;
						bottomoffset += (this.Min < this.Max?1:-1);
					}
					
					bottomoffset += (this.Min < this.Max?-1:1);
					this.BottomValue = Math.round(this.BottomValue) + bottomoffset;
					
					if(this.BottomValue > this.Min) { offset = 0; }
					
						
					//this.setMinValue(this.BottomValue);
				} else {
					// We are moving the top grabby
					if(Math.abs(this.BottomGrabby.getY()) <= y+offset)
					{
						y -= step;
						topoffset += (this.Min < this.Max?1:-1);
					}	
					topoffset += (this.Min < this.Max?-1:1);
					this.TopValue = Math.round(this.TopValue) + topoffset;
					
					if(this.TopValue-1 <= this.Max) { offset = 15; }
					//this.setMaxValue(this.TopValue);
				}
			}
			Grabby.setY(y+offset);
		}
		this.OnRangeChanged.notify({'slider':this});
		Adiamor.html.cancelEvent(evt);
	}
	else
	{*/
		
		step = Math.floor((this.getWidth())/this.Ticks);
		x = Grabby.getX();

		// Snap the grabby into place.
		if (this.Discrete)
		{
			mod = (x % step);
			div = Math.floor(x / step);

			// Snap the x value here
			
			if (x > (div * step + step/2)) { x = (div+1)*step; }
			else if (x <= div * step + step/2) { x = (div)*step; }

			var leftoffset = 0;
			var rightoffset = 0;
			offset = 0;
			if ((this.LeftGrabby.getX() + 6) > (this.getWidth() + this.RightGrabby.getX()))
			{
				if (x < 0)
				{
					// We are moving the right grabby
					x += step;
					rightoffset = (this.Min > this.Max?-1:1);
				}
				else
				{
					// We are moving the left grabby
					x -= step;
					leftoffset = (this.Min > this.Max?1:-1);
				}
			}

			if(typeof(this.LeftValue) == "undefined") { this.LeftValue = this.Min; }
			if(typeof(this.RightValue) == "undefined") { this.RightValue = this.Max; }
			this.LeftValue = Math.round(this.LeftValue) + leftoffset;
			this.RightValue = Math.round(this.RightValue) + rightoffset;

			Grabby.setX(x);
		}
		this.OnRangeChanged.notify({'slider':this});
		Adiamor.html.cancelEvent(evt);
    //}
};

/**
 * Returns the value represented by the left/bottom grabby.
 */
Adiamor.ui.Slider.prototype.getMinValue = function()
{
	var type = this.ElementClassName.substring(7);
	var minVal;
	/*if(type=="polish" || type=="sym" || type=="depth" || type=="table" || type=="size" || type=="fluor")
	{
		// Return back the internally stored minimum value
		if(this.BottomValue != null) { return this.BottomValue; }
		else
		{
			minVal = this.BottomGrabby.getY()/this.getHeight();
			if(minVal == 0 && this.Discrete) { minVal = -0.01; }
			minVal = this.getSmallValueFunction(minVal);
			return minVal;
		}	
	}
	else
	{*/
		// Return back the internally stored minimum value
		if(this.LeftValue != null) { return this.LeftValue; }
		else
		{
			minVal = this.LeftGrabby.getX()/this.getWidth();
			if(minVal == 0 && this.Discrete) { minVal = -0.01; }
			minVal = this.getValueFunction(minVal);
			return minVal;
		}
	//}
};

/**
 * Sets the position of the left grabby to the value specified
 * @param {number} minValue The value to set the left grabby at.
 */
Adiamor.ui.Slider.prototype.setMinValue = function(minValue)
{
	var type = this.ElementClassName.substring(7);
	/*if(type=="polish" || type=="sym" || type=="depth" || type=="table" || type=="size" || type=="fluor")
	{
		var offset = 0;
		//if(Adiamor.browser.IE6)
		//	offset=0;
		if(!this.Discrete && this.ElementClassName.indexOf("depth") != -1 && !(this.setSmallValueFunction(minValue) >= 1))
		{
			offset = 11;
		}
		else if(!this.Discrete && this.ElementClassName.indexOf("table") != -1 && !(this.setSmallValueFunction(minValue) >= 1))
		{
			offset = 20;
		}	
		else if(!this.Discrete && this.ElementClassName.indexOf("size") != -1 && !(this.setSmallValueFunction(minValue) >= 1))
		{
			offset = 9;
		}	
		else if(this.setSmallValueFunction(minValue) >= 1)
		{
			offset = -1;
		}	
		
		// Store the left value internally
		this.BottomValue = minValue;
		this.BottomGrabby.setY(this.getHeight() * this.setSmallValueFunction(minValue) + offset, this.BottomValue);
	}
	else
	{*/
		// Store the left value internally
		this.LeftValue = minValue;
		this.LeftGrabby.setX(this.getWidth() * this.setValueFunction(minValue), this.LeftValue);
	//}
};

/**
* Returns the value represented by the right grabby.
*/
Adiamor.ui.Slider.prototype.getMaxValue = function()
{
	var type = this.ElementClassName.substring(7);
	var maxVal;
	/*if(type=="polish" || type=="sym" || type=="depth" || type=="table" || type=="size" || type=="fluor")
	{
		// Return back the internally stored minimum value
		if(this.TopValue != null) { return this.TopValue; }
		else	
		{
			var height = this.getHeight();
			maxVal = ((height + this.TopGrabby.getY())/height);
			if(maxVal == 1 && this.Discrete) { maxVal = 1.01; }
			maxVal = this.getSmallValueFunction(maxVal);
			return maxVal;
		}	
	}
	else
	{*/
		// Return back the internally stored minimum value
		if(this.RightValue != null) { return this.RightValue; }
		else	
		{
			var width = this.getWidth();
			maxVal = ((width + this.RightGrabby.getX())/width);
			if(maxVal == 1 && this.Discrete) { maxVal = 1.01; }
			maxVal = this.getValueFunction(maxVal);
			return maxVal;
		}	
	//}
};

/**
* Sets the position of the right grabby to the value specified
* @param {number} maxValue The value to set the right grabby at.
*/
Adiamor.ui.Slider.prototype.setMaxValue = function(maxValue)
{
	var type = this.ElementClassName.substring(7);
	/*if(type=="polish" || type=="sym" || type=="depth" || type=="table" || type=="size" || type=="fluor")
	{
		this.TopValue = maxValue;
		var offset = this.GrabbyHeight;
		if(!this.Discrete && !(this.setSmallValueFunction(maxValue) <= 0) && this.ElementClassName.indexOf("table") != -1)
		{
			offset = 24;
		}	
		else if(!this.Discrete && !(this.setSmallValueFunction(maxValue) <= 0) && this.ElementClassName.indexOf("size") != -1)
		{
			offset = 3;
		}	
		else if(!this.Discrete && !(this.setSmallValueFunction(maxValue) <= 0) && this.ElementClassName.indexOf("depth") != -1)
		{
			offset = 5;
		}	
		else if(this.setSmallValueFunction(maxValue) <= 0)
		{
			offset += 7;
		}	
				
		var height = this.getHeight();
		this.TopGrabby.setY(height * this.setSmallValueFunction(maxValue) + offset, this.TopValue);
	}
	else
	{*/
		this.RightValue = maxValue;

		var width = this.getWidth();
		this.RightGrabby.setX(width * this.setValueFunction(maxValue) - width, this.RightValue);
	//}
};

/**
 * Handles a click event on the left overlay area
 */
Adiamor.ui.Slider.prototype.handleLeftOverlayClick = function(evtArgs)
{
	var coords = Adiamor.html.getEventCoords(evtArgs);

	this.LeftGrabby.setX((coords.x - this.MinXCoord));

	this.stopLeftDrag({"DragElement":this.LeftGrabby,"Event":evtArgs});
};

/**
 * Handles a click event on the right overlay area
 */
Adiamor.ui.Slider.prototype.handleRightOverlayClick = function(evtArgs)
{
	var coords = Adiamor.html.getEventCoords(evtArgs);

	this.RightGrabby.setX((coords.x - this.MaxXCoord));

	this.stopRightDrag({"DragElement":this.RightGrabby,"Event":evtArgs});
};

/**
 * Handles a click event on the top overlay area
 */
Adiamor.ui.Slider.prototype.handleTopOverlayClick = function(evtArgs)
{
	var coords = Adiamor.html.getEventCoords(evtArgs);

	this.TopGrabby.setY((coords.y - this.MaxYCoord));

	this.stopTopDrag({"DragElement":this.TopGrabby,"Event":evtArgs});
};

/**
 * Handles a click event on the bottom overlay area
 */
Adiamor.ui.Slider.prototype.handleBottomOverlayClick = function(evtArgs)
{
	var coords = Adiamor.html.getEventCoords(evtArgs);

	this.BottomGrabby.setY((coords.y - this.MaxYCoord));

	this.stopBottomDrag({"DragElement":this.BottomGrabby,"Event":evtArgs});
};

/**
 * Handles a click event on the 
 */
Adiamor.ui.Slider.prototype.handleSliderClick = function(evtArgs, elem)
{
	if (evtArgs.srcElement.getAttribute("type") == "text") { return true; }

	var coords = Adiamor.html.getEventCoords(evtArgs);

	var type = this.ElementClassName.substring(7);
	var click;
	/*if(type=="polish" || type=="sym" || type=="depth" || type=="table" || type=="size" || type=="fluor")
	{
		click = coords.y - this.MaxYCoord;
		var topY = Math.abs(click - Math.abs(this.TopGrabby.getY()));
		var bottomY = Math.abs(click - Math.abs(this.BottomGrabby.getY()));

		if(coords.y > this.MinYCoord)
		{}
		else if (bottomY < topY)
		{
			this.handleBottomOverlayClick(evtArgs);
		} else {
			this.handleTopOverlayClick(evtArgs);
		}
	}
	else
	{*/
		click = coords.x - this.MinXCoord;
		var rightX = this.RightGrabby.getX();
		var leftX = this.LeftGrabby.getX();
		var width = this.getWidth();

		if (click - leftX < (width - click - Math.abs(rightX)))
		{
			this.handleLeftOverlayClick(evtArgs);
		} else {
			this.handleRightOverlayClick(evtArgs);
		}
	//}
};

Adiamor.ui.Slider.prototype.handleMouseover = function(evtArgs, elem)
{
	if(this.LeftGrabby == null)
	{
		Adiamor.html.addClass(this.BottomGrabby.m_HtmlElementHandle, 'slider-grabbybottom'+this.ClassPostFix+'-o');
		Adiamor.html.addClass(this.TopGrabby.m_HtmlElementHandle, 'slider-grabbytop'+this.ClassPostFix+'-o');
		
		/*if(this.TooltipEnabled)
		{
			this.BottomTooltip.m_HtmlElementHandle.style.border="1px solid gray";
			this.TopTooltip.m_HtmlElementHandle.style.border="1px solid gray";
		}*/
	}
	else
	{
		Adiamor.html.addClass(this.LeftGrabby.m_HtmlElementHandle, 'slider-grabbyleft'+this.ClassPostFix+'-o');
		Adiamor.html.addClass(this.RightGrabby.m_HtmlElementHandle, 'slider-grabbyright'+this.ClassPostFix+'-o');
		
		/*if(this.TooltipEnabled)
		{
			this.LeftTooltip.m_HtmlElementHandle.style.border="1px solid gray";
			this.RightTooltip.m_HtmlElementHandle.style.border="1px solid gray";
		}*/
	}
};

Adiamor.ui.Slider.prototype.handleMouseout = function(evtArgs, elem)
{
	if(this.LeftGrabby == null)
	{
		Adiamor.html.removeClass(this.BottomGrabby.m_HtmlElementHandle, 'slider-grabbybottom'+this.ClassPostFix+'-o');
		Adiamor.html.removeClass(this.TopGrabby.m_HtmlElementHandle, 'slider-grabbytop'+this.ClassPostFix+'-o');
		
		/*if(this.TooltipEnabled)
		{
			this.BottomTooltip.m_HtmlElementHandle.style.border="1px solid white";
			this.TopTooltip.m_HtmlElementHandle.style.border="1px solid white";
		}*/
	}
	else
	{
		Adiamor.html.removeClass(this.LeftGrabby.m_HtmlElementHandle, 'slider-grabbyleft'+this.ClassPostFix+'-o');
		Adiamor.html.removeClass(this.RightGrabby.m_HtmlElementHandle, 'slider-grabbyright'+this.ClassPostFix+'-o');
		
		/*if(this.TooltipEnabled)
		{
			this.LeftTooltip.m_HtmlElementHandle.style.border="1px solid white";
			this.RightTooltip.m_HtmlElementHandle.style.border="1px solid white";
		}*/
	}	
};

Adiamor.ui.Slider.prototype.handleMouseoverP = function(evtArgs, elem)
{
	Adiamor.html.addClass(elem, 'ActiveSlider');
	
	if(this.LeftGrabby == null)
	{
		Adiamor.html.addClass(this.BottomGrabby.m_HtmlElementHandle, 'slider-grabbybottom'+this.ClassPostFix+'-o');
		Adiamor.html.addClass(this.TopGrabby.m_HtmlElementHandle, 'slider-grabbytop'+this.ClassPostFix+'-o');
	}
	else
	{
		Adiamor.html.addClass(this.LeftGrabby.m_HtmlElementHandle, 'slider-grabbyleft'+this.ClassPostFix+'-o');
		Adiamor.html.addClass(this.RightGrabby.m_HtmlElementHandle, 'slider-grabbyright'+this.ClassPostFix+'-o');
	}
};

Adiamor.ui.Slider.prototype.handleMouseoutP = function(evtArgs, elem)
{
	var eloop = null;
	
	if(evtArgs.toElement != null)
	{
		if(typeof(this.Element.parentElement) != "undefined")
		{
			eloop = evtArgs.toElement.parentElement;
		}
		else
		{
			eloop = evtArgs.toElement.parentNode;
		}		
	}
	
	var found = (evtArgs.toElement == elem);
		
	while (eloop != null && !found)
	{
		if(eloop == elem) {	found=true; }
		if(typeof(this.Element.parentElement) != "undefined")
		{
			eloop = eloop.parentElement;
		}
		else
		{
			eloop = eloop.parentNode;
		}
	}
	
	if(!found)
	{
		Adiamor.html.removeClass(elem, 'ActiveSlider');
		
		if(this.LeftGrabby == null)
		{
			Adiamor.html.removeClass(this.BottomGrabby.m_HtmlElementHandle, 'slider-grabbybottom'+this.ClassPostFix+'-o');
			Adiamor.html.removeClass(this.TopGrabby.m_HtmlElementHandle, 'slider-grabbytop'+this.ClassPostFix+'-o');
		}
		else
		{
			Adiamor.html.removeClass(this.LeftGrabby.m_HtmlElementHandle, 'slider-grabbyleft'+this.ClassPostFix+'-o');
			Adiamor.html.removeClass(this.RightGrabby.m_HtmlElementHandle, 'slider-grabbyright'+this.ClassPostFix+'-o');
		}
	}	
};

Adiamor.ui.Slider.prototype.getWidth = function()
{
	return (this.Width-2*this.GrabbyWidth);
};

Adiamor.ui.Slider.prototype.getHeight = function()
{
	return (this.Height-2*this.GrabbyHeight);
};

/**
 * This is the function that is used to encode the pixel coords
 * of the grabby to actual values.
 */
Adiamor.ui.Slider.prototype.getValueFunction = function(val)
{
	return ((this.Max - this.Min) * val + this.Min);
};

Adiamor.ui.Slider.prototype.setValueFunction = function(val)
{
	return (val - this.Min) / (this.Max - this.Min);
};

Adiamor.ui.Slider.prototype.getSmallValueFunction = function(val)
{
	return ((this.Min - this.Max) * val + this.Max);
};

Adiamor.ui.Slider.prototype.setSmallValueFunction = function(val)
{
	var offset = 0;
	if(this.Discrete) { offset = 1;	}
	return ((val - offset) - this.Max) / (this.Min - this.Max);
};

Adiamor.ui.Slider.expGetValueFunction = function(x)
{
//	return (this.Min + this.Slope * (Math.exp(x * Math.log((this.Max-this.Min)/this.Slope + 1)/this.getWidth()) - 1));
	var val = (this.Min + this.Slope * (Math.exp(x * Math.log((this.Max-this.Min)/this.Slope + 1)) - 1));
	return val;
};

Adiamor.ui.Slider.expSetValueFunction = function(y)
{
	var val = (Math.log((y - this.Min)/this.Slope + 1) / (Math.log((this.Max-this.Min)/this.Slope + 1))); //0+1/(1+Math.pow(Math.E, (-2*(y-1))))
	return val;
//	return (Math.log((y - this.Min)/this.Slope + 1) / (Math.log((this.Max-this.Min)/this.Slope + 1)/this.getWidth()));
};

/**
 * 
 */
function connect(method1, method2, object1, object2, filter)
{
	var srcMethod = object1[method1];
	if (filter instanceof Function)
	{
		object1[method1] = function(val)
		{
			srcMethod.apply(object1, arguments);
			val = filter.call(this, val);
			method2.call(object2, val);
		};	
	}
	else
	{
		object1[method1] = function(val)
		{
			srcMethod.apply(object1, arguments);
			method2.call(object2, val);
		};
	}
}

Adiamor.lang.defineNs("Adiamor.ui");

Adiamor.ui.Scrollbar = function() 
{
	this.uid = Adiamor.base.getUid(); 
	this.OnScroll = new Adiamor.base.SubjectHelper();
};
Adiamor.ui.Scrollbar.prototype.render = function()
{
	//Render the scrollbar
};
Adiamor.ui.Scrollbar.prototype.attachToParent = function(HtmlContainer, HtmlElement, HtmlSurface)
{
	this.HtmlContainer = HtmlContainer;
	this.HtmlElement = HtmlElement || Adiamor.html.getFirstChild(this.HtmlContainer);
	if (this.HtmlElement == null) { this.render(); }
	else { this.HtmlElement.style.overflow = "auto"; }
	this.HtmlSurface = HtmlSurface || Adiamor.html.getFirstChild(this.HtmlElement);
	this.HtmlSurface.style.width = 1;
	//this.HtmlSurface.style.overflow = "hidden";

	// Attach events
	Adiamor.html.attachEvent(this.HtmlElement, "scroll", this.scrollByUser, this);
};
Adiamor.ui.Scrollbar.prototype.scrollByUser = function()
{
	this.OnScroll.notify(this.getScrollPercent());
};

Adiamor.ui.Scrollbar.prototype.getScrollPercent = function() {};
Adiamor.ui.Scrollbar.prototype.setRange = function(size) {};
/*
 * Returns the horizontal thickness of the scrollbar
 */ 
Adiamor.ui.Scrollbar.prototype.getWidth = function()
{
	return 17;
};
/*
 * Returns the vertical thickness of the scrollbar
 */ 
Adiamor.ui.Scrollbar.prototype.getHeight = function()
{
	return 17;
};

//Adiamor.ui.Scrollbar.prototype.fire= function(evt,args)  {
//	return Adiamor.event.notify(evt+this.uid,args);
//}

//Adiamor.ui.Scrollbar.prototype.subscribe= function(evt,func,context)  {
//	if (typeof(context)=="undefined") context=this;
//	return Adiamor.event.subscribe(evt+this.uid,Adiamor.lang.close(context, func));
//}

Adiamor.ui.VerticalScrollbar = function() 
{
	Adiamor.ui.VerticalScrollbar.baseConstructor.call(this);
};

Adiamor.lang.extend(Adiamor.ui.VerticalScrollbar, Adiamor.ui.Scrollbar);

Adiamor.ui.VerticalScrollbar.prototype.setScrollPercent = function(percent)
{
	this.HtmlElement.scrollTop=(this.HtmlSurface.clientHeight-this.HtmlElement.clientHeight)*percent;
	return false;
};

Adiamor.ui.VerticalScrollbar.prototype.getScrollPercent = function()
{
	return (this.HtmlElement.scrollTop/(this.HtmlSurface.clientHeight-this.HtmlElement.clientHeight));
};

/*
 * @param size A percent value between 0 and 1.
 */ 
Adiamor.ui.VerticalScrollbar.prototype.setRange = function(size)
{
	//size = Math.min(size, 10000);
	//, parseInt(this.HtmlElement.style.height))
	this.HtmlSurface.style.height = size + 'px';
};
Adiamor.lang.defineNs('Adiamor.collections');

//	Helper function for check if a hash is empty or not.
/**
 * @private
 */
Adiamor.collections.isHashEmpty = function(hash) //collections
{
	var empty = true;
	for (var item in hash)
	{
		if (hash[item] != null && hash[item] != '')
		{
			empty = false;
			break;
		}
	}
	return empty;
};

Adiamor.collections.hashLength = function(hash)
{
	var count = 0;
	for (var item in hash)
	{
		if (hash.hasOwnProperty(item)) { count++; }
	}
	return count;
};

Adiamor.collections.serialize = function(hash)
{
	var s = "";
	for (var item in hash)
	{
		if (hash.hasOwnProperty(item))
		{ 
			var value = hash[item];
			var type = typeof(value);
			if (type == "string" || type == "number") { s += "'"+item+"':'"+value+"',"; }
		}	
	}
	s = s.substring(0, s.length-1);
	return "{"+s+"}";
};
Adiamor.collections.Map = function()
{
	this.head = null;
	this.tail = null;
	this.debug = [];
};

Adiamor.collections.Map.prototype.insert = function(low,high)
{
	low = Number(low);
	high = Number(high);
	if (high < low) { return; }
	this.debug.push("insert("+low+","+high+")");
	var newNode = new Adiamor.collections.MapNode(low,high);
	if (this.head==null){
		this.debug.push("empty cache, adding first node");
		this.head = newNode;
		this.tail = newNode;
	}
	else
	{
		// Handle adding at beginning or end as special
		// case due to the fact that ranges are quite
		// often prepended or appended to the list.
		var n = this.head;
		// find the node that will come after the new one.
		while (n != null && low>n.high+1)
		{
			n = n.next;
		}
		if (n==null) {
			this.debug.push("appending node to end");
			this.tail.next = newNode;
			newNode.prev = this.tail;
			this.tail = newNode;
		}
		else
		{
			this.debug.push("inserting new node before " + n.toString());
			if (n.prev != null)
			{
				newNode.prev = n.prev;
				n.prev.next = newNode;
			}
			newNode.next = n;
			n.prev = newNode;

			while(newNode.mergeNext())
			{
			}

			if (newNode.prev==null)
			{
				this.head = newNode;
			}
			if (newNode.next==null)
			{
				this.tail = newNode;
			}
		}
	}
};

Adiamor.collections.Map.prototype.remove = function(low, high)
{
	low = Number(low);
	high = Number(high);
	this.debug.push("insert("+low+","+high+")");
	if (this.head==null){
	}
	else
	{	
	    if (high < this.head.low || low > this.tail.high) { return; }

		// Handle adding at beginning or end as special
		// case due to the fact that ranges are quite
		// often prepended or appended to the list.
		var start = this.head;

		while (start != null && low > start.high)
		{
			start = start.next;
		}

		if (start==null)
		{
			this.debug.push("the range was not found");
		}
		else
		{
			var end = start;
			var temp = null;

			while (end != null && high > end.high)
    		{
    		    if ((end.next != null && high < end.next.low) || end.next == null) { break; }
				temp = end.next;
				if (end != start)
			    {
					this.removeNode(end);
				}
				end = temp;
			}

            if (start != end)
            {
                if (high >= end.high)
                {
                    //    that means the entire end node is to be removed
                    this.removeNode(end);
                }

                if (low <= start.low)
                {
                    //    that means the entire start node is to be removed
                    this.removeNode(start);
                }
            }
            //    start and end are the same ...
            //    only thing left here is if we are removing the exact node
            else if (start.low >= low && start.high <= high)
            {
                this.removeNode(start);
                return;
            }
            //    otherwise we need to create a node cause we are removing a range
            //    that is smaller than the single node.
            else if (low > start.low && high < start.high)
            {
                var origLow = start.low;
                var origHigh = start.high;
                this.removeNode(start);
                this.insert(origLow, low-1);
                this.insert(high+1, origHigh);
                return;
            }

            if (end != null && high < end.high)
            {
                //    that means that the end node is not the start and it will have to made smaller
                end.low = high+1;
            }

            if (start != null && low > start.low)
            {
                //    that means we have to shorten the start range since low is somewhere in it
                start.high = low-1;
            }
		}
	}		
};

Adiamor.collections.Map.prototype.gaps = function(low,high)
{ // Could this search be executed faster in XPath???
	if (high < 0 || low < 0 || high < low) { return []; }

	var g = [];
	var n = this.head;

	if (n==null || n.low>high || this.tail.high<low)
	{
		// our search range lies entirely outside our cache
		g.push(new Adiamor.collections.Range(low,high));
		return g;
	}

	//	This loops through all the nodes in our Map until
	//	a node high value is greater than the low end of our range

	//TODO: change this to a binary search???
	var minLow = 0;
	while (n != null && n.high < low) // shouldn't overlap???
	{
		minLow = n.high+1;
		n = n.next;
	}

	if (n!=null)
	{
		do
		{
			if (g.length == 0) // if this is the first gap.
			{
				if (low < n.low) {
//						g.push(new Adiamor.collections.Range(low,Math.min(n.low-1,high)));
					g.push(new Adiamor.collections.Range(Math.max(low,minLow),Math.min(n.low-1,high))); // Need to consider the case where the previous high overlaps the inserted range's low
				}
			}
			if (high > n.high)
			{
				if (n.next == null || n.next.low > high) // Need to consider the case where the inserted range's high overlaps the next range's low
				{
					g.push(new Adiamor.collections.Range(n.high+1, high));
				}
				else
				{
					g.push(new Adiamor.collections.Range(n.high+1, n.next.low-1));
				}
			}
			n = n.next;
		} while (n != null && n.high < high);
	}
	else
	{
		g.push(new Adiamor.collections.Range(this.tail.high+1,high));
	}
	return g;
};

Adiamor.collections.Map.prototype.ranges = function(low,high)
{ // Could this search be executed faster in XPath???
	var g = [];
	var n = this.head;

	if (n==null || n.low>high || this.tail.high<low)
	{
		// our search range lies entirely outside our cache
		return g;
	}

	//	This loops through all the nodes in our Map until
	//	a node high value is greater than the low end of our range

	//TODO: change this to a binary search???
	while (n != null && n.high < low) // shouldn't overlap???
	{
		minLow = n.high+1;
		n = n.next;
	}
	if (n!=null)
	{
		do
		{
			g.push(new Adiamor.collections.Range(n.low,n.high));
			n = n.next; 
		} while (n != null && n.high < high);
	}
	return g;
};

Adiamor.collections.Map.prototype.removeNode = function(node)
{
	if (node.prev != null)
	{
		node.prev.next = node.next;
	}
	else
	{
		this.head = node.next;
	}

	if (node.next != null)
	{
		node.next.prev = node.prev;
	}
	else
	{
		this.tail = node.prev;
	}

	node = null;
};

Adiamor.collections.Map.prototype.flush = function()
{
	var node = this.head;
	while(Boolean(node))
	{
		var next = node.next;
		delete(node);
		node = next;
	}
	this.head=null;
	this.tail=null;
};

Adiamor.collections.Map.prototype.toString = function()
{
	var n = this.head;
	var s = [];
	while (n != null)   
	{
		s.push(n.toString());
		n = n.next;
	}
	return s.join(",") + '';// + ' :: ' + a.join(",");
};
Adiamor.collections.MapNode = function(low,high)
{
	this.low = low;
	this.high = high;
	this.next = null;
	this.prev = null;
};

Adiamor.collections.MapNode.prototype.isIn = function(val)
{
	return ((val >= this.low) && (val <= this.high));
};

// Merges this node with it's next neighbour if necessary.
// ie. if this node is [0,10] and next is [11,20] or [4,20], 
// we will make a [0,20] node. Returns true if a merge was 
// performed or false if no merge is necessary.
Adiamor.collections.MapNode.prototype.mergeNext = function()
{
	var next = this.next;
	if (next!=null && next.low<=this.high+1)
	{
		this.high = Math.max(this.high,next.high);
		this.low  = Math.min(this.low, next.low );
		var nextNext = next.next;
		this.next = nextNext; // this.next.next may be null, that's fine.
		if (nextNext != null)
		{
			nextNext.prev = this;
		}
		next.clear();
		return true;
	}
	else {
		return false;
	}
};

Adiamor.collections.MapNode.prototype.clear = function()
{
	this.next = null;
	this.prev = null;
};


Adiamor.collections.MapNode.prototype.toString = function()
{
	return "[" + this.low + "," + this.high + "]";
};
Adiamor.collections.Range = function(low,high)
{
	this.low=low;
	this.high=high;
};

Adiamor.collections.Range.prototype.isIn = function(val)
{
  	return ((val>=this.low) && (val<=this.high));
};

// Pre-load the images for the checkboxes
var imgs = [];
var index;
for (var i=0; i<g_checkboxes.length; i++)
{
	index = imgs.length;
	imgs[index] = new Image();
	imgs[index].src = g_imagePath+g_checkboxes[i].name+"_d.gif";
}

index = imgs.length;
imgs[index] = new Image();
imgs[index].src = g_imagePath+"leftslider_big_over.gif";
index = imgs.length;
imgs[index] = new Image();
imgs[index].src = g_imagePath+"leftslider_small_over.gif";
index = imgs.length;
imgs[index] = new Image();
imgs[index].src = g_imagePath+"leftslider_mini_over.gif";

/**
 * The height of the secondary slider area when it is closed.
 */
var g_sliderExtensionHeightOrig = 50;
/**
 * The height of the secondary slider area when it is open.
 */
var g_sliderExtensionHeightFinal = 325;
/**
 * The lenght of time (in ms) for the transtion from page 1 to page 2 and back.
 */
var g_pageTransitionTime = 500;

/**
 * This is the url that is navigated to when the user clicks on a record in the grid list.
 * A querystring parameter named "id" is appended with the diamond ID as the value.
 */
var g_detailUrl = "";

/**
 * The panel showing all the data about a particular diamond from the grid
 */
var g_rowInfoPanel;
/**
 * The panel showing the information about comparing diamonds.
 */
var g_rowComparePanel;
/**
 * The contents of the panel showing the information about comparing diamonds.
 */
var g_rowCompareContents;

/**
 * Timeout ID for allowing the user to mouse over the row compare panel without it disappearing.
 */
var g_rowComparePanelTimeout = null;
/**
 * Timeout ID for allowing the user to mouse over the column chooser panel without it disappearing.
 */
var g_colChooserPanelTimeout = null;

/**
 *  The small panel that appears over a slider when the range is changed.
 */
var g_resultsPanel;

/**
 * The DIV containing the secondary sliders.
 */
var g_extendedSliders;

/**
 * A global variable to store the state of the diamond search that can be restored
 * when the user presses the back / forward buttons in the browser.
 */
var g_state = [];
/**
 * The current index of the state information in the g_state array.
 */
var g_currentState = 0;

/**
 * The panel that appears with the list of columns for the grid.
 */
var g_colChooserPanel;
/**
 * The contents of the panel that appears with the list of columns for the grid.
 */
var g_colChooserContents;
/**
 * The button to activate the column chooser panel.
 */
var g_colChooserButton;

/**
 * The first main panel containing the first page with the diamonds and two groups of sliders.
 */
var g_queryBuilderPanel;
/**
 * The second main panel containing the second page with the diamonds, mini sliders and data grid results.
 */
var g_queryResultsPanel;
/**
 * The DIV element used for the page fade transition.
 */
var g_queryMask;

/**
 * Indicates if results have been found.
 */
var g_resultsFound = false;

function sliderTutorial(item)
{
	item.Slider.LeftOverlay.m_HtmlElementHandle.style.width=((item.Slider.Width/2)-(item.Slider.Width/20))+'px';
	item.Slider.RightOverlay.m_HtmlElementHandle.style.width=((item.Slider.Width/2)-(item.Slider.Width/20))+'px';
	Adiamor.ui.Effects.tutorial({width:0}, [item.Slider.LeftOverlay.m_HtmlElementHandle], 300, null);
	Adiamor.ui.Effects.tutorial({width:0}, [item.Slider.RightOverlay.m_HtmlElementHandle], 300, null);
}



function restoreSliders(sliders, min, max)
{
	var found = false;
	var minVal, maxVal;
	for (var i=0; i<sliders.length; i++)
	{
		minVal = readCookie(min+i);
		if(minVal != null && !(isNaN(parseInt(minVal))))
		{
			sliders[i].Slider.setMinValue(minVal);
			found = true;
		}
		else if(sliders[i].Slider.ClassPostFix == "-small")
		{
			if(sliders[i].Slider.Discrete)
			{
				minVal = sliders[i].Slider.Min;
				minVal++;
				sliders[i].Slider.setMinValue(minVal);
			}
			else
			{
				minVal = sliders[i].Slider.Min;
				sliders[i].Slider.setMinValue(minVal);			
			}
		}
		maxVal = readCookie(max+i);
		if(maxVal != null && !(isNaN(parseInt(maxVal))))
		{
			sliders[i].Slider.setMaxValue(maxVal);
			found = true;
		}
		else if(sliders[i].Slider.ClassPostFix == "-small")
		{
			if(sliders[i].Slider.Discrete)
			{
				maxVal = sliders[i].Slider.Max;
				//maxVal++;
				sliders[i].Slider.setMaxValue(maxVal);
			}
			else
			{
				maxVal = sliders[i].Slider.Max;
				sliders[i].Slider.setMaxValue(maxVal);
			}
		}

		//if((minVal != null || maxVal != null) || sliders[i].Slider.ClassPostFix != "-small")
		//{
			updateDataViewSliderParams({"slider":sliders[i].Slider}, sliders[i].name);
		//}
	}
	return found;
}

function restoreCheckboxes()
{
	var found = false;
	var round_cb = null;
	
	for (var i=0; i<g_checkboxes.length; i++)
	{
		var g_cb = g_checkboxes[i];
		var n = g_cb.name;
		var cookie = readCookie("shape:"+n);

		var cb = g_cb.Checkbox;
		var img = g_cb.Image;
		var ncb = g_cb.CheckboxQr;
		var nimg = g_cb.ImageQr;
	
		// At this point cb is the visible checkbox and ncb is the invisible equivalent
		if (cookie == "checked")
		{
			cb.checked = true;
			ncb.checked = true;
			img.src = g_imagePath + n + '_d.gif';
			nimg.src = g_imagePath + n + '_d.gif';
			g_diamondData.setParam('shape_'+n,g_inverseMappings.Shape[n]);
			found = true;
		}
		else 
		{
			cb.checked = false;
			ncb.checked = false;
			img.src = g_imagePath+'t' + n + '_d.gif';
			nimg.src = g_imagePath+'t' + n + '_d.gif';
			g_diamondData.setParam('shape_'+n);
			if (n == "round")
			{
				round_cb = g_cb;
			}
		}
	}
	
	// If there are no diamonds selected just select the round diamond.
	if (!found)
	{
		round_cb.Checkbox.checked = true;
		round_cb.CheckboxQr.checked = true;
		round_cb.Image.src = g_imagePath + 'round_d.gif';
		round_cb.ImageQr.src = g_imagePath + 'round_d.gif';
		g_diamondData.setParam('shape_round',g_inverseMappings.Shape.round);
	}
}

/**
 * Saves any state information to a cookie on page unlad
 */
 
function saveState()
{
	// Grid sort state
	createCookie("sortcolumn",g_grid.SortColumn,1);
	createCookie("sortdirection",g_grid.SortDirection,1);
	
	//	Get the rows from metadata and calculate the first visible row
	var firstVisibleRow = 0;
	//	Set scrollTop to be the current amount of scrolling plus the height of the top frozen rows
	//	minus the height of the indicators

	firstVisibleRow += Math.floor(g_grid.View.frame.scrollTop/g_grid.View.RowHeight);

	//	Get the rows from metadata and calculate the last visible row
	var lastVisibleRow = 0;
	lastVisibleRow += Math.ceil(g_grid.View.frame.clientHeight/g_grid.View.RowHeight) + firstVisibleRow;
	
	createCookie("startRow",firstVisibleRow,1);
	createCookie("endRow",lastVisibleRow,1);

	// Grid visible columns
	Adiamor.lang.forEach(g_grid.Columns, function(item) 
		{
			// Get the checkbox control and see if it exists.
			var cb = $(item.Name.toLowerCase() + '_cb');
			if (cb != null)
			{
				if (cb.checked) {
					createCookie("column:"+item.Name, "visible", 1);
				} else {
					createCookie("column:"+item.Name, "invisible", 1);
				}
			}
		}
	);

	if(g_miniSliders.Slider == null)
		Adiamor.lang.forEach(g_miniSliders, setupMainSlider);
	
	var i;
	// Main slider state
	for (i=0; i<g_miniSliders.length; i++)
	{
		if(g_miniSliders[i].Slider.TooltipEnabled)
		{
			createCookie("mamin:"+i, g_miniSliders[i].Slider.LeftTooltip.m_HtmlElementHandle.value.replace(/[^0-9|\.]/gi,''), 1);
			createCookie("mamax:"+i, g_miniSliders[i].Slider.RightTooltip.m_HtmlElementHandle.value.replace(/[^0-9|\.]/gi,''), 1);
		}
		else
		{
			createCookie("mamin:"+i, g_miniSliders[i].Slider.getMinValue(), 1);
			createCookie("mamax:"+i, g_miniSliders[i].Slider.getMaxValue(), 1);
		}
	}

	if(g_smallSliders.Slider == null)
		Adiamor.lang.forEach(g_smallSliders, setupMainSlider);

	// Secondary slider state
	for (i=0; i<g_smallSliders.length; i++)
	{
		if(g_smallSliders[i].Slider.TooltipEnabled)
		{
			createCookie("smmin:"+i, g_smallSliders[i].Slider.LeftTooltip.m_HtmlElementHandle.value.replace(/[^0-9|\.]/gi,''), 1);
			createCookie("smmax:"+i, g_smallSliders[i].Slider.RightTooltip.m_HtmlElementHandle.value.replace(/[^0-9|\.]/gi,''), 1);
		}
		else
		{
			createCookie("smmin:"+i, parseInt(g_smallSliders[i].Slider.getMinValue(),10), 1);
			createCookie("smmax:"+i, parseInt(g_smallSliders[i].Slider.getMaxValue(),10), 1);
		}
	}

	// Diamond checkboxes
	for (i=0; i<g_checkboxes.length; i++)
	{
		if (g_checkboxes[i].Checkbox.checked) {
			createCookie("shape:"+g_checkboxes[i].name,"checked",1);
		} else {
			createCookie("shape:"+g_checkboxes[i].name,null,1);
		}
	}
}

/**
 * Restores the slider states from a state object.
 * @param {Object} obj A state object from which the state can be restored.
 */
function setState(obj)
{
	Adiamor.lang.forEach(g_miniSliders, function(item, index)
	{
		item.Slider.setMinValue(obj[item.name.replace('-mini','')].left);
		item.Slider.setMaxValue(obj[item.name.replace('-mini','')].right);
		updateDataViewSliderParams({"slider":item.Slider}, item.name);
	});
	Adiamor.lang.forEach(g_mainSliders, function(item, index)
	{
		item.Slider.setMinValue(obj[item.name].left);
		item.Slider.setMaxValue(obj[item.name].right);
		updateDataViewSliderParams({"slider":item.Slider}, item.name);
	});
	Adiamor.lang.forEach(g_smallSliders, function(item, index)
	{
		item.Slider.setMinValue(obj[item.name].left);
		item.Slider.setMaxValue(obj[item.name].right);
		updateDataViewSliderParams({"slider":item.Slider}, item.name);
	});
	Adiamor.lang.forEach(g_checkboxes, function(item, index)
		{
			var n = item.name;
		
			var cb = item.Checkbox;
			var img = item.Image;
			var ncb = item.CheckboxQr;
			var nimg = item.ImageQr;

			// At this point cb is the visible checkbox and ncb is the invisible equivalent
			if (obj[n].checked)
			{
				cb.checked = true;
				ncb.checked = true;
				img.src = g_imagePath + n + '_d.gif';
				nimg.src = g_imagePath + n + '_d.gif';
				// set the param in the datasource
				g_diamondData.setParam('shape_'+n,g_inverseMappings.Shape[n]);
			}
			else 
			{
				cb.checked = false;
				ncb.checked = false;
				img.src = g_imagePath+'t' + n + '_d.gif';
				nimg.src = g_imagePath+'t' + n + '_d.gif';
				// clear the param in the datasource
				g_diamondData.setParam('shape_'+n);
			}
		}
	);
}

/**
 * Displays the slider callout.
 */
function showSliderInfo(evtObj, element)
{
	
	//$('imMenuContainer').style.zIndex=0;
	this.Callout.Container.style.zIndex=1000;
	Adiamor.html.align(this.Callout.Container, this.info, Adiamor.at | Adiamor.al, 0, 0, -160 + this.calloutOffset, this.info.offsetWidth);
	/*$('OptionsContainer').style.display="none";
	$(this.name+'Callout').style.display="inline";*/
}

/**
 * Hides the slider callout.
 */
function hideSliderInfo(evtObj, element)
{
	//$('imMenuContainer').style.zIndex=9999;
	this.Callout.Container.style.left = -2000+'px';
	/*$('OptionsContainer').style.display="inline";
	$(this.name+'Callout').style.display="none";*/
}

/**
 * Sets up a slider callout position where the item argument is the slider object from the g_mainSliders, g_miniSliders or g_smallSliders array.
 */
function setupSliderCallout(item)
{
	var n = item.name;
	if ($('slider-'+n+'-callout'))
	{
		item.Callout = new Adiamor.ui.Panel();
		item.Callout.attachToParent($('slider-'+n+'-callout'));
		item.Callout.setBackgroundImage(g_imagePath+n+'_callout.png');
		item.Callout.setWidth(241);
		item.Callout.setHeight(280);

		item.info = $('slider-'+n+'-info');

		Adiamor.html.attachEvent(item.info, 'mouseover', Adiamor.lang.close(item, showSliderInfo));
		Adiamor.html.attachEvent(item.info, 'mouseout', Adiamor.lang.close(item, hideSliderInfo));
	}
}

/**
 * Sets up required properties for a general slider.
 */
function setupBasicSlider(item)
{
	var n = item.name;
	if (item.Slider == null)
	{
		item.Slider = new Adiamor.ui.Slider(item.sliderParams);
		item.Name = n;
		item.Slider.ElementClassName = "slider-"+n;
	    item.Slider.attachToParent($("slider-container-"+n));
	    // Just a little hook here to keep track of the currently active slider.
	    // Used to prevent strange things from happening when the user drags the mouse off the browser window.
	    item.Slider.OnStartDrag.subscribe(Adiamor.lang.close({}, function(slider, grabby){g_activeSlider = grabby;}));
	}
}

/**
 * Event handler for when the secondary sliders on the first page change.
 */
function smallSliderChanged(evtArgs)
{
	updateDataViewSliderParams(evtArgs, this.Name);

	// Re-render the grid
	g_grid.render();
}

/**
 * Setup a secondary slider, position the associated help callout, attach callout events where the item argument is the slider object from the g_smallSliders array.
 */
function setupSmallSlider(item)
{
	setupBasicSlider(item);
	//setupSliderCallout(item);
	item.Slider.OnRangeChanged.subscribe(Adiamor.lang.close(item, smallSliderChanged));
}

/**
 * Hides the fade transition mask
 */
function hideMask()
{
	g_queryMask.style.display = 'none';
}

/**
 * Creates a state object by recording the max and min values of all the sliders.
 * @returns {Object} The state object is returned.
 */
function createStateObject()
{
	var obj = {};
	// Main and mini sliders are the same ones - store the value from the currently active ones
	// Check if the query builder is positioned off screen - if so then use the mini sliders.
	var sliders = g_mainSliders;
	if (parseInt(g_queryBuilderPanel.style.left,10) < 0) { sliders = g_miniSliders; }

	Adiamor.lang.forEach(sliders, function(item, index)
	{
		// The mini slider names will be price-mini etc so just strip off the -mini part and get the min/max values.
		if(item.Slider.TooltipEnabled)
		{
			obj[item.name.replace('-mini','')] = {"left":item.Slider.LeftTooltip.m_HtmlElementHandle.value.replace(/[^0-9|\.]/gi,''),"right":item.Slider.RightTooltip.m_HtmlElementHandle.value.replace(/[^0-9|\.]/gi,'')};
		}	
		else
		{
			obj[item.name.replace('-mini','')] = {"left":item.Slider.getMinValue(),"right":item.Slider.getMaxValue()};
		}	
	});

	// Store the state of the small sliders.
	
	Adiamor.lang.forEach(g_smallSliders, function(item, index)
	{
		obj[item.name] = {"right":item.Slider.getMaxValue(),"left":item.Slider.getMinValue()};
	});

	// Store the state of the checkboxes.
	Adiamor.lang.forEach(g_checkboxes, function(item, index)
	{
		obj[item.name] = {"checked":item.Checkbox.checked};
	});
	return obj;
}

/**
 * Shows the query results panel using a fade transition.
 * @param {Boolean} saveState Boolean that specifies if the state should be saved.
 * @param {Int} fragment The identifier for the state to be saved to.
 */
function showQueryResults(saveState, fragment)
{
	// First make sure the builder panel is not visible
	hideElement(g_queryBuilderPanel);

	// Make the results panel appear now off the screen
	g_queryResultsPanel.style.left = '-2000px';
	showElement(g_queryResultsPanel);

	// Align the mask to the width and height of the results panel - it will show up 
	// in the same top/left as the builder panel.
	// HACK for Mozilla not getting the right offsetWidth on the query results panel
	g_queryMask.style.width = Math.max(g_queryResultsPanel.offsetWidth, $("myGridList").offsetWidth + 30) + 'px';
	g_queryMask.style.height = g_queryResultsPanel.offsetHeight + 'px';

	// Position the results panel top at negative of the query panel height (since they are positioned 
	// relatively this is required to set the results panel to the same top as the query panel
	positionElement(g_queryResultsPanel, 0, 0);

	// This should only be done the first time the query results are displayed
	if (g_smallSliders[0].Slider == null) { Adiamor.lang.forEach(g_smallSliders, setupSmallSlider); }
	
	// Restore the secondary sliders from the cookie.
	var found = restoreSliders(g_smallSliders, "smmin:", "smmax:") || found;
	
	if (Adiamor.browser.MOZ || Adiamor.browser.IE)
	{
		if (saveState == null || saveState == true)
		{
			// First store the state and fix the back button.
			Adiamor.browser.History.instance.add('queryresults.html#'+(g_state.length));
			g_state.push(createStateObject());
		}
		else if (saveState == false)
		{
			// If saveState is false, that means this has been initiated by a restore state (ie back or forward button)
			// so now that the panel is not visible we can re-set the state
			setState(g_state[fragment]);
			// Also need to render the grid.
			g_grid.render();
		}
	}

	Adiamor.ui.Effects.fade(g_queryMask, {startValue:100,endValue:0}, g_pageTransitionTime, Adiamor.dom.setOpacity, Adiamor.dom, hideMask);

	// Render the first page in the Grid
	g_grid.render();
	
	var sliders = g_mainSliders;
	for(var i=0; i<g_mainSliders.length; i++)
	{
		sliders[i] = g_mainSliders[i];
		sliders[i].Slider = g_mainSliders[i].Slider;
	}
	
	if(document.getElementById("round-qr_cb").checked || document.getElementById("princess-qr_cb").checked ||
		document.getElementById("emerald-qr_cb").checked || document.getElementById("asscher-qr_cb").checked)
	{
		sliders[2].Ticks = 5;
		sliders[2].Slider.Ticks = 5;
		sliders[2].Slider.Max = 5;
		sliders[2].sliderParams.Max = 5;
		if(sliders[2].Slider.getMaxValue() == 4) { sliders[2].Slider.setMaxValue(5); }
			
		if(checkNonAffinity())
		{
			$('label-size').style.display="block";
			
			if($('ntb-sliderAdiamor__uid__11') != null) { $('ntb-sliderAdiamor__uid__11').className="slider-bg-repeat slider-element slider-cut-mini"; }
			if($('ntb-sliderAdiamor__uid__6') != null) { $('ntb-sliderAdiamor__uid__6').className="slider-bg-repeat slider-element slider-cut"; }
			if($('cutmarkings') != null) { $('cutmarkings').src="http://www.adiamor.com/images/Adiamor_T/cutmarkings.gif"; }
		}
		else
		{
			$('label-size').style.display="none";
			
			if($('ntb-sliderAdiamor__uid__11') != null) { $('ntb-sliderAdiamor__uid__11').className="slider-bg-repeat slider-element slider-cut-mini-both"; }
			if($('ntb-sliderAdiamor__uid__6') != null) { $('ntb-sliderAdiamor__uid__6').className="slider-bg-repeat slider-element slider-cut-both"; }
			if($('cutmarkings') != null) { $('cutmarkings').src="http://www.adiamor.com/images/Adiamor_T/cutmarkings.gif"; }
		}
		
		if(parseInt(g_diamondData.params.cut_high,10) == 4) { g_diamondData.setParam('cut_high', 5); }
	}
	else
	{
		sliders[2].Ticks = 4;
		sliders[2].Slider.Ticks = 4;
		sliders[2].Slider.Max = 4;	
		sliders[2].sliderParams.Max = 4;
		if(sliders[2].Slider.getMaxValue() == 5) { sliders[2].Slider.setMaxValue(4); }
		if(sliders[2].Slider.getMinValue() == 4) { sliders[2].Slider.setMinValue(3); }
		
		$('label-size').style.display="block";
		
		if($('ntb-sliderAdiamor__uid__11') != null) { $('ntb-sliderAdiamor__uid__11').className="slider-bg-repeat slider-element slider-cut-mini-noround"; }
		if($('ntb-sliderAdiamor__uid__6') != null) { $('ntb-sliderAdiamor__uid__6').className="slider-bg-repeat slider-element slider-cut-noround"; }
		if($('cutmarkings') != null) { $('cutmarkings').src="http://www.adiamor.com/images/Adiamor_T/cutmarkings2.gif"; }

		if(parseInt(g_diamondData.params.cut_high,10) == 5)
		{
			if(parseInt(g_diamondData.params.cut_low,10) == 4 || parseInt(g_diamondData.params.cut_low,10) == 5)
			{
				g_diamondData.setParam('cut_low', 3);
			}	
			g_diamondData.setParam('cut_high', 4);
		}
	}

	// In the case that we are not saving the state - ie we are not responding to the back button
	// then we just do the standard updating of the sliders from the previous panel to the current one
	if (saveState != false) { updateSliders(0); }
}

/**
 * Update the small results panel on the first page. This is fired on the RowCountChanged event
 * of the datasource.
 */
function updateResultsPanel()
{
	g_resultsFound = true;
	$('results-pending').style.display = 'none';
	var numResults = Adiamor.lang.formatNumber(g_diamondData.getRemoteRowCount(),0);
	if (numResults == 0)
	{
		var msg = $('gridlist-overlay');
		showElement(msg);
		Adiamor.html.align(msg, g_grid.View.element, Adiamor.aw | Adiamor.ah | Adiamor.at | Adiamor.al);
	}
	
	$('results-recordcount').innerHTML = numResults;
	$('results-found').innerHTML = numResults + " Results Found";
	$('results-found').style.display = 'block';
}

/**
 * Displays the activity indicator to indicate that the results are being retrieved from the server.
 */
function showResultsPending()
{
	if (!g_resultsFound)
	{
		// Show the activity indicator.
		$('results-pending').style.display="block";
		// Hide the number of results found div
		$('results-found').style.display = 'none';
		// Set a timeout just in case there are problems with the server.
		window.setTimeout(updateResultsPanel, 3000);
	}
}

/**
 * Shows the mini results panel using a slide transition when the slider limits are changed.
 */
function showResultsPanel(slider)
{
	g_resultsPanel.Container.style.display='block';
	// if the results panel is visible quickly make it shrink ...
	if (parseInt(g_resultsPanel.getSurfaceTop(),10) == 0)
	{
		Adiamor.ui.Effects.disappearFromTop(g_resultsPanel, {}, 50, Adiamor.lang.close({}, showResultsPanel, [slider]));
	}
	// show it at the new location.
	else
	{
		showResultsPending();

		g_resultsPanel.setSurfaceTop(29);
		g_resultsPanel.show();

		Adiamor.html.align(g_resultsPanel.Container, slider.Container, Adiamor.at | Adiamor.al, 0, 0, -g_resultsPanel.Container.offsetHeight, 0);
		Adiamor.ui.Effects.appearFromBottom(g_resultsPanel, {}, 300);
	}
}

/**
 * Updates the main sliders with the new value of the mini slider.
 */
function miniSliderChanged(evtArgs)
{
	// Update the DataView params for this slider
	updateSliders(1);
	updateDataViewSliderParams(evtArgs, this.Name);

	// Re-render the grid
	g_grid.render();
}

/**
 * Gets the number of records from the server using a request for a single record from the JsonDataView.
 */
function getDataViewRecordCount()
{
	// We just want to return one row of data ... this will also include the rowCount
	g_diamondData.setParam("start", 0);
	g_diamondData.setParam("page_size", 1);

	// Clear the dataview of all the data
	g_diamondData.flush();

	// Retrieve the data from the server.
	g_diamondData.get();
}

/**
 * Event handler for when the main sliders on the first page change.
 */
function mainSliderChanged(evtArgs)
{
	g_resultsFound = false;
	// Show the mini results panel.
	showResultsPanel(this.Slider);

	// Update the DataView params for this slider
	updateDataViewSliderParams(evtArgs, this.Name);

	// Request a single record from the DataView to get the new record count
	getDataViewRecordCount();
}

/**
 * Setup a mini slider, position the associated help callout, attach callout events where the item argument is the slider object from the g_miniSliders array.
 */
function setupMiniSlider(item, index)
{
	setupBasicSlider(item);
	setupSliderCallout(item);
	item.Slider.OnRangeChanged.subscribe(Adiamor.lang.close(item, miniSliderChanged));
}

/**
 * Restores any state information to a cookie on page unlad
 */
 
function restoreState()
{
	var found = false;
	
	// Restore the main sliders from the cookie.
	if (g_miniSliders[0].Slider == null) { Adiamor.lang.forEach(g_miniSliders, setupMiniSlider); }
	found = restoreSliders(g_miniSliders, "mamin:", "mamax:") || found;
	found = restoreSliders(g_mainSliders, "mamin:", "mamax:") || found;

	restoreCheckboxes();

	// Setup the columns that are visible in the datagrid from the cookie.
	Adiamor.lang.forEach(g_grid.Columns, function(item) 
		{
			var checked = readCookie("column:"+item.Name);
			// Get the checkbox control and see if it exists.
			var cb = $(item.Name.toLowerCase() + '_cb');
			if (cb != null)
			{
				if (checked == "visible") {
					item.cssStyle.display = '';
					cb.checked = true;
				} else {
					item.cssStyle.display = 'none';
					cb.checked = false;
				}
			}
		}
	);

	// Setup the grid sort
	var sortCol = readCookie("sortcolumn") || 14;
	var sortDir = readCookie("sortdirection") || "ASC";
	g_grid.setSort(sortCol, sortDir);
	
	// Decide which view to show, either the detailed search or search results.
	//if(found == true)
	//{
		showQueryResults(null, null, true);
	/*}
	else
	{
		// First time on the page then setup the history management
		Adiamor.browser.History.instance.add('querybuilder.html#'+(g_state.length));
		g_state.push(createStateObject());

		showElement(g_queryBuilderPanel);
	}*/
	showColumns();
	var position = (readCookie("startRow")*g_grid.View.RowHeight);//(g_grid.Scrollbar.HtmlSurface.clientHeight-g_grid.Scrollbar.HtmlElement.clientHeight);
	
	setTimeout("scrollMove("+position+")",1400);
	
	if(!found) { Adiamor.lang.forEach(g_miniSliders, sliderTutorial); }
	
}

/**
 * Hides the secondary sliders.
 */
function hideSliders()
{
	// First hide the results panel if it is visible.
	g_resultsPanel.Container.style.display='none';
	Adiamor.ui.Effects.shrink({height:g_sliderExtensionHeightOrig}, [g_extendedSliders, Adiamor.html.getFirstChild(g_extendedSliders)], 50);
	$('slider-extension-show').style.display = 'block';
	$('slider-extension-hide').style.display = 'none';
}

/**
 * Shows the secondary sliders.
 */
function showSliders()
{
	Adiamor.ui.Effects.shrink({height:g_sliderExtensionHeightFinal}, [g_extendedSliders, Adiamor.html.getFirstChild(g_extendedSliders)], 100);
	$('slider-extension-show').style.display = 'none';
	$('slider-extension-hide').style.display = 'block';
}

function fadeSlidersIn()
{
	Adiamor.ui.Effects.fade($('query-results-filter'), {startValue:0,endValue:100}, 500, Adiamor.dom.setOpacity, Adiamor.dom, null);
	Adiamor.html.detachEvent($('query-collapse'), 'click', expandSliders);
	Adiamor.html.attachEvent($('query-collapse'), 'click', collapseSliders);
}

function fadeSlidersOut()
{
	Adiamor.ui.Effects.shrink({height:0}, [$('query-results-filter')], 50);
	Adiamor.html.detachEvent($('query-collapse'), 'click', collapseSliders);
	Adiamor.html.attachEvent($('query-collapse'), 'click', expandSliders);
}

function collapseSliders(evtArgs, elem, saveState, fragment)
{
	Adiamor.ui.Effects.fade($('query-results-filter'), {startValue:100,endValue:0}, 500, Adiamor.dom.setOpacity, Adiamor.dom, fadeSlidersOut);
}

function expandSliders(evtArgs, elem, saveState, fragment)
{
	Adiamor.ui.Effects.shrink({height:245}, [$('query-results-filter')], 50, fadeSlidersIn);
}

//*********************************************************
//** State serialization and deserialization
//*********************************************************

/**
 * Shows the query builder panel using a fade transition.
 * @param {Boolean} saveState Boolean that specifies if the state should be saved.
 * @param {Int} fragment The identifier for the state to be saved to.
 */
function showQueryBuilder(saveState, fragment)
{
	if (Adiamor.browser.MOZ || Adiamor.browser.IE)
	{
		if (saveState == null || saveState == true)
		{
			// First store the state and fix the back button.
			// This results from a click so it clears the forward history.
			Adiamor.browser.History.instance.add('querybuilder.html#'+(g_state.length));
			g_state.push(createStateObject());
		}
		else if (saveState == false)
		{
			// If saveState is false, that means this has been initiated by a restore state (ie back or forward button)
			// so now that the panel is not visible we can re-set the state
			setState(g_state[fragment]);
			// Also need to update the results panel.
			getDataViewRecordCount();
		}
	}

	// Second make sure the results panel is not visible
	hideElement(g_queryResultsPanel);

	// Make the builder panel appear now off the screen
	g_queryBuilderPanel.style.left = '-2000px';
	showElement(g_queryBuilderPanel);

	// Align the mask to the width and height of the results panel - it will show up 
	// in the same top/left as the builder panel.
	// HACK for Mozilla not getting the right offsetWidth on the query results panel
	g_queryMask.style.width = (g_queryBuilderPanel.offsetWidth + 100) + 'px';
	g_queryMask.style.height = g_queryBuilderPanel.offsetHeight + 'px';

	// Position the results panel top at negative of the query panel height (since they are positioned 
	// relatively this is required to set the results panel to the same top as the query panel
	positionElement(g_queryBuilderPanel, 0, 0);

	// Align the mask on the builder.
	Adiamor.html.align(g_queryMask, g_queryBuilderPanel, Adiamor.al | Adiamor.at | Adiamor.ah, 0, 30);

	// Make the builder panel appear now below the mask
	showElement(g_queryBuilderPanel);

	Adiamor.ui.Effects.fade(g_queryMask, {startValue:100,endValue:0}, g_pageTransitionTime, Adiamor.dom.setOpacity, Adiamor.dom, hideMask);

	// In the case that we are not saving the state - ie we are not responding to the back button
	// then we just do the standard updating of the sliders from the previous panel to the current one
	if (saveState != false) { updateSliders(1); }
}

/**
 * Hides the query builder panel.
 * @param {Object} evtArgs Standard event arguments.
 * @param {HTMLElement} evtArgs Standard event element.
 * @param {Bool} saveState Bool value indicating whether the state should be saved or not. 
 * If it is not explicitly set to false it is assumed true.
 * @param {String} fragment The fragment identifier to be used with AJAX history.
 */
function hideQueryBuilder(evtArgs, evtElem, saveState, fragment)
{
	g_queryMask.style.display = 'block';
	Adiamor.html.align(g_queryMask, g_queryBuilderPanel, Adiamor.al | Adiamor.at | Adiamor.aw | Adiamor.ah, 0, 30);
	// Then fade the mask in to make the querybuilder disappear and call showQueryResults
	Adiamor.ui.Effects.fade(g_queryMask, {startValue:0,endValue:100}, g_pageTransitionTime, Adiamor.dom.setOpacity, Adiamor.dom, Adiamor.lang.close(this, showQueryResults, [saveState, fragment]));
}

/**
 * Hides the column chooser panel.
 */
function hideColChooserPanel()
{
	hideElement(g_colChooserPanel.Container);
	hideElement(g_colChooserContents);
}

/**
 * Hides the query results panel and shows query builder panel using a fade transition.
 * @param {Object} evtArgs Standard event arguments.
 * @param {HTMLElement} evtArgs Standard event element.
 * @param {Bool} saveState Bool value indicating whether the state should be saved or not. 
 * If it is not explicitly set to false it is assumed true.
 * @param {String} fragment The fragment identifier to be used with AJAX history.
 */
function hideQueryResults(evtArgs, elem, saveState, fragment)
{
	hideColChooserPanel();
	g_queryMask.style.display = 'block';
	Adiamor.html.align(g_queryMask, g_queryResultsPanel, Adiamor.aw | Adiamor.ah, 0, 30);
	// Then fade the mask in to make the querybuilder disappear and call showQueryBuilder
	Adiamor.ui.Effects.fade(g_queryMask, {startValue:0,endValue:100}, g_pageTransitionTime, Adiamor.dom.setOpacity, Adiamor.dom, Adiamor.lang.close(this, showQueryBuilder, [saveState, fragment]));
}

/**
 * Restores the state with given URL fragment as the key for the state
 */
function restoreBackButtonState(url, fragment)
{
	if (g_state[fragment] != null)
	{
		if (parseInt(g_queryBuilderPanel.style.left,10) < 0)
		{
			if (url == "querybuilder.html")
			{
				// That means we need to do a transition to the query results panel
				hideQueryResults(null, null, false, fragment);
			}
			else
			{
				// Otherwise we just restore the state ...
				setState(g_state[fragment]);
			}
		}
		else
		{
			if (url == "queryresults.html")
			{
				// That means we need to do a transition to the query builder panel
				hideQueryBuilder(null, null, false, fragment);
			}
			else
			{
				setState(g_state[fragment]);
			}
		}
	}
}

//*********************************************************
//** Transition effects from page 1 to page 2
//*********************************************************

/**
 * Displays/hides an optional slider. TODO: add a fade effect
 * @param {Object} evtArgs Standard event arguments.
 * @param {HTMLElement} evtArgs Standard event element.
 * @param {Bool} saveState Bool value indicating whether the state should be saved or not. 
 * If it is not explicitly set to false it is assumed true.
 * @param {String} fragment The fragment identifier to be used with AJAX history.
 */

function displayOptionalSlider(evtArgs, elem, saveState, fragment)
{
	var mask = $("slider-mask-"+this.id.substring(6));
	var label = $("label-"+this.id.substring(6));
	
	if(mask.style.display=="none" || mask.style.display=="")
	{	
		$('slider-mask-polish').style.display="none";
		$('slider-mask-symmetry').style.display="none";
		$('slider-mask-depth').style.display="none";
		$('slider-mask-table').style.display="none";
		$('slider-mask-size').style.display="none";
		$('slider-mask-fluor').style.display="none";
		
		$('label-polish').src="http://www.adiamor.com/images/Adiamor_T/polishlabel.gif";
		$('label-symmetry').src="http://www.adiamor.com/images/Adiamor_T/symmetrylabel.gif";
		$('label-depth').src="http://www.adiamor.com/images/Adiamor_T/depthlabel.gif";
		$('label-table').src="http://www.adiamor.com/images/Adiamor_T/tablelabel.gif";
		$('label-fluor').src="http://www.adiamor.com/images/Adiamor_T/fluorlabel.gif";
		$('label-size').src="http://www.adiamor.com/images/Adiamor_T/lwlabel.gif";
		
		if(this.id.substring(6) == "size")
		{
			label.src="../images/Adiamor_T/lwlabel_on.gif";
		}
		else
		{
			label.src="../images/Adiamor_T/"+this.id.substring(6)+"label_on.gif";
		}
	
		mask.style.display="block";
	}
	else
	{
		mask.style.display="none";		
		
		if(this.id.substring(6) == "size")
		{
			label.src="../images/Adiamor_T/lwlabel.gif";
		}
		else
		{
			label.src="../images/Adiamor_T/"+this.id.substring(6)+"label.gif";
		}
	}
}

//***********************************************
//******** DIAMOND CHOOSER **********************
//***********************************************

/**
 * Selects a diamond that is clicked on.
 */
function clickDiamond(evtObj)
{
	var id = evtObj.srcElement.id;
	var n = this.name;

	var cb = this.Checkbox;
	var img = this.Image;
	var ncb = this.CheckboxQr;
	var nimg = this.ImageQr;
	
	g_smallSliders[2].Slider.setMinValue(45);
	g_smallSliders[2].Slider.setMaxValue(86);
	g_smallSliders[3].Slider.setMinValue(49);
	g_smallSliders[3].Slider.setMaxValue(89);
	g_smallSliders[4].Slider.setMinValue(0.50);
	g_smallSliders[4].Slider.setMaxValue(2.75);
	g_diamondData.setParam('depth_low', 45);
	g_diamondData.setParam('depth_high', 86);
	g_diamondData.setParam('table_low', 49);
	g_diamondData.setParam('table_high', 89);
	g_diamondData.setParam('size_low', 0.75);
	g_diamondData.setParam('size_high', 2.75);
	
	if (id.indexOf("-qr") > 0)
	{
		cb = this.CheckboxQr;
		img = this.ImageQr;
		ncb = this.Checkbox;
		nimg = this.Image;
	}
	// At this point cb is the visible checkbox and ncb is the invisible equivalent
	if (cb.checked)
	{
		// They clicked on the diamond picture we need to manually set the checkbox state
		if (id.indexOf("_cb") < 0) { cb.checked = false; }
		// Set the invisible checkbox no matter what
		ncb.checked = false;
		img.src = g_imagePath+'t' + n + '_d.gif';
		nimg.src = g_imagePath+'t' + n + '_d.gif';
		
		if(checkNumShapes() > 0)
		{
			g_diamondData.setParam('shape_'+n);
		}
	}
	else 
	{
		if(checkNumShapes() == 0)
		{
			g_diamondData.setParam('shape_asscher');
			g_diamondData.setParam('shape_cushion');
			g_diamondData.setParam('shape_emerald');
			g_diamondData.setParam('shape_heart');
			g_diamondData.setParam('shape_marquise');
			g_diamondData.setParam('shape_oval');
			g_diamondData.setParam('shape_pear');
			g_diamondData.setParam('shape_princess');
			g_diamondData.setParam('shape_radiant');
			g_diamondData.setParam('shape_round');
		}
		
		// They clicked on the diamond picture we need to manually set the checkbox state
		if (id.indexOf("_cb") < 0) { cb.checked = true; }
		// Set the invisible checkbox no matter what
		ncb.checked = true;
		img.src = g_imagePath + n + '_d.gif';
		nimg.src = g_imagePath + n + '_d.gif';
		g_diamondData.setParam('shape_'+n,g_inverseMappings.Shape[n]);
	}
	// set this param in the datatable to indicate that the reques is due to a diamond click.
	g_diamondData.setParam('diamond','1');
	
	/*if (g_miniSliders[0].Slider == null)
		Adiamor.lang.forEach(g_miniSliders, setupMiniSlider);*/
		
	var sliders, i;	
	if (id.indexOf("-qr") > 0)
	{
		sliders = g_miniSliders;
		for(i=0; i<g_miniSliders.length; i++)
		{
			sliders[i] = g_miniSliders[i];
			sliders[i].Slider = g_miniSliders[i].Slider;
		}	
	}	
	else
	{
		sliders = g_mainSliders;
		for(i=0; i<g_mainSliders.length; i++)
		{
			sliders[i] = g_mainSliders[i];
			sliders[i].Slider = g_mainSliders[i].Slider;
		}
	}
	
	if(firstClick == false && n != "round")
	{
		firstClick = true;
		
		document.getElementById("round-qr_cb").checked = false;
		document.getElementById("round_cb").checked = false;
		document.getElementById("round-qr_img").src = g_imagePath+'tround_d.gif';
		document.getElementById("round_img").src = g_imagePath+'tround_d.gif';
		g_diamondData.setParam('shape_round');
		
		$('label-size').style.display="block";
		
		if(checkNonAffinity())
		{
			sliders[2].Ticks = 4;
			sliders[2].Slider.Ticks = 4;
			sliders[2].Slider.Max = 4;	
			sliders[2].sliderParams.Max = 4;
			if(sliders[2].Slider.getMaxValue() == 5 || sliders[2].Slider.getMaxValue() == "5") { sliders[2].Slider.setMaxValue(4); }
			if(sliders[2].Slider.getMinValue() == 4 || sliders[2].Slider.getMinValue() == "4") { sliders[2].Slider.setMinValue(3); }
			
			if($('ntb-sliderAdiamor__uid__11') != null)
			{
				$('ntb-sliderAdiamor__uid__11').className="slider-bg-repeat slider-element slider-cut-mini-noround";
			}	
			if($('ntb-sliderAdiamor__uid__6') != null)
			{
				$('ntb-sliderAdiamor__uid__6').className="slider-bg-repeat slider-element slider-cut-noround";
			}	
			if($('cutmarkings') != null)
			{
				$('cutmarkings').src="http://www.adiamor.com/images/Adiamor_T/cutmarkings2.gif";
			}
			
			if(parseInt(g_diamondData.params.cut_high,10) == 5)
			{
				if(parseInt(g_diamondData.params.cut_low,10) == 4 || parseInt(g_diamondData.params.cut_low,10) == 5)
				{
					g_diamondData.setParam('cut_low', 3);
				}	
				g_diamondData.setParam('cut_high', 4);
			}
		}
	}
	else
	{
		firstClick = true;
		
		if(n == "round")
		{
			if (ncb.checked)
			{
				sliders[2].Ticks = 5;
				sliders[2].Slider.Ticks = 5;
				sliders[2].Slider.Max = 5;
				sliders[2].sliderParams.Max = 5;
				if(sliders[2].Slider.getMaxValue() == 4 || sliders[2].Slider.getMaxValue() == "4") { sliders[2].Slider.setMaxValue(5); }
				
				if(checkNonAffinity())
				{
					$('label-size').style.display="block";
			
					if($('ntb-sliderAdiamor__uid__11') != null)
					{
						$('ntb-sliderAdiamor__uid__11').className="slider-bg-repeat slider-element slider-cut-mini";
					}	
					if($('ntb-sliderAdiamor__uid__6') != null)
					{
						$('ntb-sliderAdiamor__uid__6').className="slider-bg-repeat slider-element slider-cut";
					}	
					if($('cutmarkings') != null)
					{
						$('cutmarkings').src="http://www.adiamor.com/images/Adiamor_T/cutmarkings.gif";
					}	
				}
				else
				{
					$('label-size').style.display="none";
			
					if($('ntb-sliderAdiamor__uid__11') != null)
					{
						$('ntb-sliderAdiamor__uid__11').className="slider-bg-repeat slider-element slider-cut-mini-both";
					}	
					if($('ntb-sliderAdiamor__uid__6') != null)
					{
						$('ntb-sliderAdiamor__uid__6').className="slider-bg-repeat slider-element slider-cut-both";
					}	
					if($('cutmarkings') != null)
					{
						$('cutmarkings').src="http://www.adiamor.com/images/Adiamor_T/cutmarkings.gif";
					}	
				}
				
				if(parseInt(g_diamondData.params.cut_high,10) == 4) { g_diamondData.setParam('cut_high', 5); }
			}
			else 
			{
				if(checkNonAffinity())
				{
					sliders[2].Ticks = 4;
					sliders[2].Slider.Ticks = 4;
					sliders[2].Slider.Max = 4;	
					sliders[2].sliderParams.Max = 4;
					if(sliders[2].Slider.getMaxValue() == 5 || sliders[2].Slider.getMaxValue() == "5") { sliders[2].Slider.setMaxValue(4); }
					if(sliders[2].Slider.getMinValue() == 4 || sliders[2].Slider.getMinValue() == "4") { sliders[2].Slider.setMinValue(3); }
						
					if($('ntb-sliderAdiamor__uid__11') != null)
					{
						$('ntb-sliderAdiamor__uid__11').className="slider-bg-repeat slider-element slider-cut-mini-noround";
					}
					if($('ntb-sliderAdiamor__uid__6') != null)
					{
						$('ntb-sliderAdiamor__uid__6').className="slider-bg-repeat slider-element slider-cut-noround";
					}
					if($('cutmarkings') != null)
					{
						$('cutmarkings').src="http://www.adiamor.com/images/Adiamor_T/cutmarkings2.gif";
					}
					
					$('label-size').style.display="block";
					
					if(parseInt(g_diamondData.params.cut_high,10) == 5)
					{
						if(parseInt(g_diamondData.params.cut_low,10) == 4 || parseInt(g_diamondData.params.cut_low,10) == 5)
						{
							g_diamondData.setParam('cut_low', 3);
						}	
						g_diamondData.setParam('cut_high', 4);
					}
				}
			}
		}
		else
		{
			if(document.getElementById("round-qr_cb").checked || document.getElementById("princess-qr_cb").checked ||
				document.getElementById("emerald-qr_cb").checked || document.getElementById("asscher-qr_cb").checked)
			{
				sliders[2].Ticks = 5;
				sliders[2].Slider.Ticks = 5;
				sliders[2].Slider.Max = 5;
				sliders[2].sliderParams.Max = 5;
				if(sliders[2].Slider.getMaxValue() == 4 || sliders[2].Slider.getMaxValue() == "4") { sliders[2].Slider.setMaxValue(5); }
				
				if(checkNonAffinity())
				{
					$('label-size').style.display="block";
			
					if($('ntb-sliderAdiamor__uid__11') != null)
					{
						$('ntb-sliderAdiamor__uid__11').className="slider-bg-repeat slider-element slider-cut-mini";
					}	
					if($('ntb-sliderAdiamor__uid__6') != null)
					{
						$('ntb-sliderAdiamor__uid__6').className="slider-bg-repeat slider-element slider-cut";
					}	
					if($('cutmarkings') != null)
					{
						$('cutmarkings').src="http://www.adiamor.com/images/Adiamor_T/cutmarkings.gif";
					}	
				}
				else
				{
					$('label-size').style.display="none";
			
					if($('ntb-sliderAdiamor__uid__11') != null)
					{
						$('ntb-sliderAdiamor__uid__11').className="slider-bg-repeat slider-element slider-cut-mini-both";
					}	
					if($('ntb-sliderAdiamor__uid__6') != null)
					{
						$('ntb-sliderAdiamor__uid__6').className="slider-bg-repeat slider-element slider-cut-both";
					}	
					if($('cutmarkings') != null)
					{
						$('cutmarkings').src="http://www.adiamor.com/images/Adiamor_T/cutmarkings.gif";
					}	
				}
				
				if(parseInt(g_diamondData.params.cut_high,10) == 4) { g_diamondData.setParam('cut_high', 5); }
			}
			else
			{
				sliders[2].Ticks = 4;
				sliders[2].Slider.Ticks = 4;
				sliders[2].Slider.Max = 4;	
				sliders[2].sliderParams.Max = 4;
				if(sliders[2].Slider.getMaxValue() == 5 || sliders[2].Slider.getMaxValue() == "5") { sliders[2].Slider.setMaxValue(4); }
				if(sliders[2].Slider.getMinValue() == 4 || sliders[2].Slider.getMinValue() == "4") { sliders[2].Slider.setMinValue(3); }
					
				if($('ntb-sliderAdiamor__uid__11') != null)
				{
					$('ntb-sliderAdiamor__uid__11').className="slider-bg-repeat slider-element slider-cut-mini-noround";
				}
				if($('ntb-sliderAdiamor__uid__6') != null)
				{
					$('ntb-sliderAdiamor__uid__6').className="slider-bg-repeat slider-element slider-cut-noround";
				}
				if($('cutmarkings') != null)
				{
					$('cutmarkings').src="http://www.adiamor.com/images/Adiamor_T/cutmarkings2.gif";
				}
				
				$('label-size').style.display="block";
				
				if(parseInt(g_diamondData.params.cut_high,10) == 5)
				{
					if(parseInt(g_diamondData.params.cut_low,10) == 4 || parseInt(g_diamondData.params.cut_low,10) == 5)
					{
						g_diamondData.setParam('cut_low', 3);
					}	
					g_diamondData.setParam('cut_high', 4);
				}
			}
		}
	}
	
	updateSliders(1);
	updateSliders(0);
	
	g_diamondData.flush();
}

/**
 * Event handler for clicks on diamond choosers on the query builder page. 
 * Displays the pending results panel and retrieves the data from the server with the new search parameters.
 */
function clickDiamondQb(evtObj)
{
	g_resultsFound = false;

	// Show the mini results panel.
	showResultsPending();

	// Call the clickDiamond method in the context of the checkbox
	clickDiamond.call(this, evtObj);

	// Get an updated rowCount for the new filter.
	getDataViewRecordCount();
}

/**
 * Event handler for clicks on diamond choosers on the query results page.
 * Displays the pending results panel and retrieves the data from the server with the new search parameters.
 */
function clickDiamondQr(evtObj)
{
	clickDiamond.call(this, evtObj);

	// Re-render the grid
	g_grid.render();
}

/**
 * Sets up the specified checkbox where the item argument is the checkbox object from the g_checkboxes array.
 */
function setupCheckbox(item)
{
	var n = item.name;
	item.Panel = $('checkbox-'+n);
	item.PanelQr = $('checkbox-'+n+'-qr');
	item.Image = $(n+'_img');
	item.ImageQr = $(n+'-qr_img');
	item.Checkbox = $(n+'_cb');
	item.CheckboxQr = $(n+'-qr_cb');

	if (item.Checkbox.checked)
	{
		item.Image.src = g_imagePath + n + '_d.gif';
		item.ImageQr.src = g_imagePath + n + '_d.gif';
		g_diamondData.setParam('shape_'+n, g_inverseMappings.Shape[n]);
	}
	Adiamor.html.attachEvent(item.Panel, 'mousedown', Adiamor.lang.close(item, clickDiamondQb));
	Adiamor.html.attachEvent(item.PanelQr, 'mousedown', Adiamor.lang.close(item, clickDiamondQr));
}

/**
 * Setup a primary slider, position the associated help callout, attach callout events where the item argument is the slider object from the g_mainSliders array.
 */
function setupMainSlider(item)
{
	setupBasicSlider(item);
	setupSliderCallout(item);
	item.Slider.OnRangeChanged.subscribe(Adiamor.lang.close(item, mainSliderChanged));
}

/**
 * Sets the min and max values of all the sliders based on information returned from the server.
 * The payload is the full (JSON object instantiated) data returned from the server.
 * The "limits" property should contain a hash like this {"price":{"min":200,"max":40000}, ... }
 */
function setSliderLimits(getCompleteEventArgs)
{
	var data = getCompleteEventArgs.payload.limits;
	if (data == null || tooltip != null)
	{
		return;
	}

	var n, s, newMin, newMax, i;
	for (i=0; i<g_mainSliders.length; i++)
	{
		mainSlider = g_mainSliders[i].Slider;
		miniSlider = g_miniSliders[i].Slider;

		n = g_mainSliders[i].name;
		if (data[n] != null)
		{
			// New value is the current value or the new min/max
			newMin = Math.max(mainSlider.getMinValue(), data[n].min);
			newMax = Math.min(mainSlider.getMaxValue(), data[n].max);

			// Setup the sliders new end points
			mainSlider.Max = data[n].max;
			mainSlider.Min = data[n].min;

			// The mini slider might not yet be initialized
			if (miniSlider != null)
			{
				miniSlider.Max = data[n].max;
				miniSlider.Min = data[n].min;
			}

			// Set the slider min and max values
			mainSlider.setMinValue(newMin);
			mainSlider.setMaxValue(newMax);

			if (miniSlider != null)
			{
				miniSlider.setMinValue(newMin);
				miniSlider.setMaxValue(newMax);
			}
		}
	}

	for (i=0; i<g_smallSliders.length; i++)
	{
		s = g_smallSliders[i].Slider;
		n = g_smallSliders[i].name;
		if (data[n] != null)
		{
			// New value is the current value or the new min/max
			newMin = Math.max(s.getMinValue(), data[n].min);
			newMax = Math.min(s.getMaxValue(), data[n].max);

			// Set the sliders new end points
			s.Max = data[n].max;
			s.Min = data[n].min;

			// Set the slider min and max values
			s.setMinValue(newMin);
			s.setMaxValue(newMax);
		}
	}
}

/**
 * Shows the panel with info about the currently selected diamond.
 */
function showInfoPanel(row)
{
	var dRow = parseInt(row.getAttribute('row'),10);

	// TODO: Change this to loop through the grid and show any columns that are not visible...

	var cols = [{"label":"Item Number:","column":"ID"},
				{"label":"Shape","column":"Shape"},
				{"label":"Girdle","column":"Girdle"},
				{"label":"Culet","column":"Culet"},
				{"label":"Depth","column":"Depth"},
				{"label":"Table","column":"Tbl"},
				{"label":"Polish","column":"Pol"},
				{"label":"Symmetry","column":"Sym"},
				{"label":"Fluorescence","column":"Fluor"},
				{"label":"Measurements","column":"Meas"},
				{"label":"L/W Ratio","column":"Size"}];

	var s = [];
	s.push('<br><div>');
	
	for (var i=0; i<cols.length; i++)
	{
		var cb = $(cols[i].column.toLowerCase() + '_cb');
		var show = true;
		if (cb != null)
		{
			if (cb.checked)
			{
				show = false;		
			}
		}
		var val = g_diamondData.getMappedValue(dRow, g_grid.ColumnsMap[cols[i].column]);
		if(cols[i].column == "Pol" || cols[i].column == "Sym")
		{
			
			if(val == "EX")
			{
				val = "Excellent";
			}
			else if(val == "ID")
			{
				val = "Ideal";
			}
			else if(val == "VG")
			{
				val = "Very Good";
			}
			else if(val == "G")
			{
				val = "Good";
			}
			else if(val == "F")
			{
				val = "Fair";
			}
		}
		else if(cols[i].column == "Fluor")
		{
			if(val == "F")
			{
				val = "Faint";
			}
			else if(val == "MB")
			{
				val = "Medium";
			}
			else if(val == "N")
			{
				val = "None";
			}
			else if(val == "SB")
			{
				val = "Strong";
			}
			else if(val == "VS")
			{
				val = "Very Strong";
			}
		}
		if (show && val != null && val != "")
		{
			if(i%2)
			{
				if(i==0)
				{
					s.push('<div style="margin-left: 21px; margin-right: 8px; padding-bottom:2px; padding-top:2px; font-size: 11px; width: 158px"><strong>'+cols[i].label+'</strong>&nbsp;&nbsp;D-'+val+'</div>');
				}	
				else if(i == 4 || i == 5)
				{
					s.push('<div style="margin-left: 21px; margin-right: 8px; padding-bottom:2px; padding-top:2px; font-size: 11px; border-top: 1px solid #B2B2B2; width: 158px"><strong>'+cols[i].label+':</strong>&nbsp;&nbsp;'+val+'%</div>');
				}	
				else if(i == 9)
				{
					s.push('<div style="margin-left: 21px; margin-right: 8px; padding-bottom:2px; padding-top:2px; font-size: 11px; border-top: 1px solid #B2B2B2; width: 158px"><strong>'+cols[i].label+':</strong>&nbsp;&nbsp;'+val+'&nbsp;mm</div>');
				}	
				else
				{
					s.push('<div style="margin-left: 21px; margin-right: 8px; padding-bottom:2px; padding-top:2px; font-size: 11px; border-top: 1px solid #B2B2B2; width: 158px"><strong>'+cols[i].label+':</strong>&nbsp;&nbsp;'+val+'</div>');
				}	
			}
			else
			{
				if(i==0)
				{
					s.push('<div style="margin-left: 21px; margin-right: 8px; padding-bottom:2px; padding-top:2px; font-size: 11px; width: 158px"><strong>'+cols[i].label+'</strong>&nbsp;&nbsp;D-'+val+'</div>');
				}	
				else if(i == 4 || i == 5)
				{
					s.push('<div style="margin-left: 21px; margin-right: 8px; padding-bottom:2px; padding-top:2px; font-size: 11px; border-top: 1px solid #B2B2B2; width: 158px"><strong>'+cols[i].label+':</strong>&nbsp;&nbsp;'+val+'%</div>');
				}	
				else if(i == 9)
				{
					s.push('<div style="margin-left: 21px; margin-right: 8px; padding-bottom:2px; padding-top:2px; font-size: 11px; border-top: 1px solid #B2B2B2; width: 158px"><strong>'+cols[i].label+':</strong>&nbsp;&nbsp;'+val+'&nbsp;mm</div>');
				}	
				else
				{
					s.push('<div style="margin-left: 21px; margin-right: 8px; padding-bottom:2px; padding-top:2px; font-size: 11px; border-top: 1px solid #B2B2B2; width: 158px;"><strong>'+cols[i].label+':</strong>&nbsp;&nbsp;'+val+'</div>');
				}	
			}
		}
	}
	s.push('</div>');

	Adiamor.lang.forEach(g_grid.Columns, function(item) 
		{
		}
	);
	hideColChooserPanel();

	$("panel-rowdetail-contents").innerHTML = s.join('');
 
	var topOffset = -g_rowInfoPanel.Container.offsetHeight/2 +10;
	if (Adiamor.browser.MOZ)
	{
		topOffset -= $("ListDataFrame").scrollTop;
	}
	
	var container_offset=0;
	if(dRow < parseInt($("ListDataFrame").scrollTop/22,10)+6)
	{
		container_offset = ((6-(dRow-parseInt($("ListDataFrame").scrollTop/22,10)))*22)-5;
	}	
	else if(dRow > parseInt($("ListDataFrame").scrollTop/22,10)+9)
	{
		container_offset = ((9+parseInt($("ListDataFrame").scrollTop/22,10)-dRow)*22);
	}
	
	Adiamor.html.align(g_rowInfoPanel.Container, row, Adiamor.at | Adiamor.al, 0, 0, topOffset+container_offset, g_grid.Header.Container.clientWidth + 18);
	Adiamor.html.align(g_rowInfoPanelArrow.Container, row, Adiamor.at | Adiamor.al, 0, 0, 0, g_grid.Header.Container.clientWidth + 20);
}

/**
 * Actually hides the com compare diamonds panel.
 */
function hideComparePanel()
{
	hideElement(g_rowComparePanel.Container);
	hideElement(g_rowCompareContents);
}

/**
 * Hides the row info panel after a delay
 */
function hideInfoPanel(evtObj, elem, clear)
{
	clearPanel = true;
	window.setTimeout("hideInfoPanelNow(null, null, true)", 1000)
}

/**
 * Hides the row info panel
 * This could be called from a few different places like an event or explicitly
 */
function hideInfoPanelNow(evtObj, elem, clear)
{
	if (clearPanel)
	{
		g_rowInfoPanel.Container.style.left = -1000+'px';

		if (clear)
		{
			window.clearTimeout(g_rowComparePanelTimeout);
			g_rowComparePanelTimeout = null;
			hideComparePanel();
		}
		else
		{
			g_rowComparePanelTimeout = window.setTimeout(hideComparePanel, 200);
		}
	}
	else
		window.setTimeout("hideInfoPanelNow(null, null, true)", 500)
}

/**
 * Handles mouse over events on the data grid. It will either display an info panel about
 * the diamond currently hovered over or the compare diamonds popup.
 */
function rowMouseOverHandler(evtArgs)
{
	hideInfoPanelNow(null, null, true);

	/*if (evtArgs.cell.getAttribute('column') == '15')
	{
		// show the compare panel
		showComparePanel(evtArgs.row);
	}
	else
	{*/
		// show the info panel.
		showInfoPanel(evtArgs.row);
	//}
}

function preventHide(evtArgs)
{
	clearPanel = false;
}

/**
 * Hides the panel with the compare diamonds button.
 */
function hideComparePanelHandler(evtObj, elem)
{
	// Check if the toElement of the mouseout event is a child of the compare panel or not. 
	var comparePanel = findElement(evtObj.toElement, 'panel-rowcompare');
	if (comparePanel == null)
	{
		hideComparePanel();
	}	
}

function querySt(ji)
{
	hu = window.location.search.substring(1);
	gy = hu.split("&");
	for(i=0;i<gy.length;i++)
	{
		ft = gy[i].split("=");
		if(ft[0] == ji)
		{
			return ft[1];
		}
	}
}

/**
 * Used to prevent the user from dragging the slider off the page and getting it stuck in drag mode.
 */
function abortDrag(evtArgs)
{
	if (evtArgs.fromElement == null && g_activeSlider != null)
	{
		g_activeSlider.onMouseUp();
	}
}

/**
 * Display the column chooser panel.
 */
function showColChooserPanel()
{
	showElement(g_colChooserPanel.Container);
	showElement(g_colChooserContents);
	Adiamor.html.align(g_colChooserPanel.Container, g_colChooserButton, Adiamor.at | Adiamor.al, 0,0,g_colChooserButton.offsetHeight);
	Adiamor.html.align(g_colChooserContents, g_colChooserButton, Adiamor.at | Adiamor.al, 0,0,g_colChooserButton.offsetHeight);
}

/**
 * Toggles the visibility of the column chooser panel.
 */
function toggleColChooserPanel()
{
	if (isElementVisible(g_colChooserContents))
	{
		hideColChooserPanel();
	}
	else
	{
		showColChooserPanel();
	}
}

/**
 * Initializes the application. To be called once the DOM is fully loaded.
 */
function init()
{
	if(typeof(sIFR) == "function")
	{
	}
	
	if(Adiamor.browser.IE && !Adiamor.browser.IE6 && !Adiamor.browser.IE7 && !Adiamor.browser.IE8)
	{
		window.location="http://www.adiamor.com/diamondsearch.aspx";
	}	
	else if(Adiamor.browser.OPERA)
	{
		window.location="http://www.adiamor.com/diamondsearch.aspx";
	}	
	/*else if(Adiamor.browser.CHROME)
	{
		if(window.location.href.indexOf("col=") >= 0)
		{
			window.location="http://www.adiamor.com/diamondsearch.aspx?col=Affinity";
		}	
		else
		{
			window.location="http://www.adiamor.com/diamondsearch.aspx";
		}	
	}*/

	Adiamor.html.attachEvent(window, "unload", saveState);
	
	var rightTooltipOffset = 40;
	if (!Adiamor.browser.IE) { rightTooltipOffset = 40; }

	g_mainSliders = [	{name:'price',calloutOffset:120,sliderParams:{"Height":60,"OverlayHeight":47,"TooltipEnabled":true,"Min":250,"Max":500000,"getValueFunction":Adiamor.ui.Slider.expGetValueFunction,"setValueFunction":Adiamor.ui.Slider.expSetValueFunction,"formatTooltipValue":formatMoney0,"LeftTooltipOffsetLeft":-30,"RightTooltipOffsetLeft":-27+rightTooltipOffset,"LeftTooltipOffsetTop":-11,"RightTooltipOffsetTop":-11,"Slope":120}},
	                 	{name:'carat',calloutOffset:56,sliderParams:{"Height":60,"OverlayHeight":47,"TooltipEnabled":true,"Min":0.30,"Max":15,"getValueFunction":Adiamor.ui.Slider.expGetValueFunction,"setValueFunction":Adiamor.ui.Slider.expSetValueFunction,"formatTooltipValue":formatCarat,"LeftTooltipOffsetLeft":-20,"RightTooltipOffsetLeft":-27+rightTooltipOffset,"LeftTooltipOffsetTop":-11,"RightTooltipOffsetTop":-11,"Slope":0.05}},
						{name:'cut',calloutOffset:4,sliderParams:{"Min":0,"Max":5,"Discrete":true,"Ticks":5}},
						{name:'color',calloutOffset:-38,sliderParams:{"Min":29,"Max":22,"Discrete":true,"Ticks":7}},
						{name:'clarity',calloutOffset:-76,sliderParams:{"Min":37,"Max":30,"Discrete":true,"Ticks":7}}];

	if(Adiamor.browser.SAFARI)
	{
		g_smallSliders = [{name:'polish',calloutOffset:20,sliderParams:{"Height":36,"Width":226,"OverlayHeight":35,"GrabbyWidth":10,"GrabbyHeight":17,"Min":63,"Max":60,"Discrete":true,"Ticks":3,"ClassPostFix":"-small"}},
				{name:'sym',calloutOffset:20,sliderParams:{"Height":36,"Width":226,"OverlayHeight":35,"GrabbyWidth":10,"GrabbyHeight":17,"Min":63,"Max":60,"Discrete":true,"Ticks":3,"ClassPostFix":"-small"}},
				{name:'depth',calloutOffset:20,sliderParams:{"Height":15,"Width":226,"OverlayHeight":35,"GrabbyWidth":10,"GrabbyHeight":17,"Min":45,"Max":86,"TooltipEnabled":true,"formatTooltipValue":formatNumber1,"LeftTooltipOffsetLeft":-35,"LeftTooltipOffsetTop":3,"RightTooltipOffsetLeft":-25+rightTooltipOffset,"RightTooltipOffsetTop":3,"ClassPostFix":"-small"}},
				{name:'table',calloutOffset:20,sliderParams:{"Height":15,"Width":226,"OverlayHeight":35,"GrabbyWidth":10,"GrabbyHeight":17,"Min":49,"Max":89,"TooltipEnabled":true,"formatTooltipValue":formatDouble,"LeftTooltipOffsetLeft":-35,"LeftTooltipOffsetTop":3,"RightTooltipOffsetLeft":-25+rightTooltipOffset,"RightTooltipOffsetTop":3,"ClassPostFix":"-small"}},
				{name:'size',calloutOffset:20,sliderParams:{"Height":15,"Width":226,"OverlayHeight":35,"GrabbyWidth":10,"GrabbyHeight":17,"Min":0.50,"Max":2.75,"TooltipEnabled":true,"formatTooltipValue":formatNumber2,"LeftTooltipOffsetLeft":-35,"LeftTooltipOffsetTop":3,"RightTooltipOffsetLeft":-25+rightTooltipOffset,"RightTooltipOffsetTop":3,"ClassPostFix":"-small"}},
				{name:'fluor',calloutOffset:20,sliderParams:{"Height":36,"Width":226,"OverlayHeight":35,"GrabbyWidth":10,"GrabbyHeight":17,"Min":46,"Max":41,"Discrete":true,"Ticks":5,"ClassPostFix":"-small"}}];
		
		g_miniSliders = [ {name:'price-mini',calloutOffset:20,sliderParams:{"Height":18,"Width":427,"OverlayHeight":35,"GrabbyWidth":10,"GrabbyHeight":17,"Min":250,"Max":500000,"TooltipEnabled":true,"getValueFunction":Adiamor.ui.Slider.expGetValueFunction,"setValueFunction":Adiamor.ui.Slider.expSetValueFunction,"formatTooltipValue":formatMoney0,"LeftTooltipOffsetLeft":-35,"LeftTooltipOffsetTop":1,"RightTooltipOffsetLeft":-25+rightTooltipOffset,"RightTooltipOffsetTop":1,"Slope":100,"ClassPostFix":"-mini"}},
				{name:'carat-mini',calloutOffset:20,sliderParams:{"Height":18,"Width":427,"OverlayHeight":35,"GrabbyWidth":10,"GrabbyHeight":17,"Min":0.30,"Max":15.01,"TooltipEnabled":true,"getValueFunction":Adiamor.ui.Slider.expGetValueFunction,"setValueFunction":Adiamor.ui.Slider.expSetValueFunction,"formatTooltipValue":formatCarat,"LeftTooltipOffsetLeft":-35,"LeftTooltipOffsetTop":1,"RightTooltipOffsetLeft":-25+rightTooltipOffset,"RightTooltipOffsetTop":1,"Slope":0.1,"ClassPostFix":"-mini"}},
				{name:'cut-mini',calloutOffset:20,sliderParams:{"Height":31,"Width":427,"OverlayHeight":35,"GrabbyWidth":10,"Discrete":true,"Ticks":5,"GrabbyHeight":17,"Min":0,"Max":5,"ClassPostFix":"-mini"}},
				{name:'color-mini',calloutOffset:20,sliderParams:{"Height":31,"Width":427,"OverlayHeight":35,"GrabbyWidth":10,"Discrete":true,"Ticks":7,"GrabbyHeight":17,"Min":29,"Max":22,"ClassPostFix":"-mini"}},
				{name:'clarity-mini',calloutOffset:20,sliderParams:{"Height":31,"Width":427,"OverlayHeight":35,"GrabbyWidth":10,"Discrete":true,"Ticks":7,"GrabbyHeight":17,"Min":37,"Max":30,"ClassPostFix":"-mini"}}];
	}
	else if(!Adiamor.browser.IE6)
	{
		g_smallSliders = [{name:'polish',calloutOffset:20,sliderParams:{"Height":36,"Width":226,"OverlayHeight":35,"GrabbyWidth":10,"GrabbyHeight":17,"Min":63,"Max":60,"Discrete":true,"Ticks":3,"ClassPostFix":"-small"}},
				{name:'sym',calloutOffset:20,sliderParams:{"Height":36,"Width":226,"OverlayHeight":35,"GrabbyWidth":10,"GrabbyHeight":17,"Min":63,"Max":60,"Discrete":true,"Ticks":3,"ClassPostFix":"-small"}},
				{name:'depth',calloutOffset:20,sliderParams:{"Height":15,"Width":226,"OverlayHeight":35,"GrabbyWidth":10,"GrabbyHeight":17,"Min":45,"Max":86,"TooltipEnabled":true,"formatTooltipValue":formatNumber1,"LeftTooltipOffsetLeft":-35,"LeftTooltipOffsetTop":3,"RightTooltipOffsetLeft":-25+rightTooltipOffset,"RightTooltipOffsetTop":3,"ClassPostFix":"-small"}},
				{name:'table',calloutOffset:20,sliderParams:{"Height":15,"Width":226,"OverlayHeight":35,"GrabbyWidth":10,"GrabbyHeight":17,"Min":49,"Max":89,"TooltipEnabled":true,"formatTooltipValue":formatDouble,"LeftTooltipOffsetLeft":-35,"LeftTooltipOffsetTop":3,"RightTooltipOffsetLeft":-25+rightTooltipOffset,"RightTooltipOffsetTop":3,"ClassPostFix":"-small"}},
				{name:'size',calloutOffset:20,sliderParams:{"Height":15,"Width":226,"OverlayHeight":35,"GrabbyWidth":10,"GrabbyHeight":17,"Min":0.50,"Max":2.75,"TooltipEnabled":true,"formatTooltipValue":formatNumber2,"LeftTooltipOffsetLeft":-35,"LeftTooltipOffsetTop":3,"RightTooltipOffsetLeft":-25+rightTooltipOffset,"RightTooltipOffsetTop":3,"ClassPostFix":"-small"}},
				{name:'fluor',calloutOffset:20,sliderParams:{"Height":36,"Width":226,"OverlayHeight":35,"GrabbyWidth":10,"GrabbyHeight":17,"Min":46,"Max":41,"Discrete":true,"Ticks":5,"ClassPostFix":"-small"}}];
		
		g_miniSliders = [ {name:'price-mini',calloutOffset:20,sliderParams:{"Height":18,"Width":427,"OverlayHeight":35,"GrabbyWidth":10,"GrabbyHeight":17,"Min":250,"Max":500000,"TooltipEnabled":true,"getValueFunction":Adiamor.ui.Slider.expGetValueFunction,"setValueFunction":Adiamor.ui.Slider.expSetValueFunction,"formatTooltipValue":formatMoney0,"LeftTooltipOffsetLeft":-35,"LeftTooltipOffsetTop":1,"RightTooltipOffsetLeft":-25+rightTooltipOffset,"RightTooltipOffsetTop":1,"Slope":100,"ClassPostFix":"-mini"}},
				{name:'carat-mini',calloutOffset:20,sliderParams:{"Height":18,"Width":427,"OverlayHeight":35,"GrabbyWidth":10,"GrabbyHeight":17,"Min":0.30,"Max":15.01,"TooltipEnabled":true,"getValueFunction":Adiamor.ui.Slider.expGetValueFunction,"setValueFunction":Adiamor.ui.Slider.expSetValueFunction,"formatTooltipValue":formatCarat,"LeftTooltipOffsetLeft":-35,"LeftTooltipOffsetTop":1,"RightTooltipOffsetLeft":-25+rightTooltipOffset,"RightTooltipOffsetTop":1,"Slope":0.1,"ClassPostFix":"-mini"}},
				{name:'cut-mini',calloutOffset:20,sliderParams:{"Height":31,"Width":427,"OverlayHeight":35,"GrabbyWidth":10,"Discrete":true,"Ticks":5,"GrabbyHeight":17,"Min":0,"Max":5,"ClassPostFix":"-mini"}},
				{name:'color-mini',calloutOffset:20,sliderParams:{"Height":31,"Width":427,"OverlayHeight":35,"GrabbyWidth":10,"Discrete":true,"Ticks":7,"GrabbyHeight":17,"Min":29,"Max":22,"ClassPostFix":"-mini"}},
				{name:'clarity-mini',calloutOffset:20,sliderParams:{"Height":31,"Width":427,"OverlayHeight":35,"GrabbyWidth":10,"Discrete":true,"Ticks":7,"GrabbyHeight":17,"Min":37,"Max":30,"ClassPostFix":"-mini"}}];
	}
	else
	{
		g_smallSliders = [{name:'polish',calloutOffset:20,sliderParams:{"Height":36,"Width":226,"OverlayHeight":35,"GrabbyWidth":10,"GrabbyHeight":17,"Min":63,"Max":60,"Discrete":true,"Ticks":3,"ClassPostFix":"-small"}},
				{name:'sym',calloutOffset:20,sliderParams:{"Height":36,"Width":226,"OverlayHeight":35,"GrabbyWidth":10,"GrabbyHeight":17,"Min":63,"Max":60,"Discrete":true,"Ticks":3,"ClassPostFix":"-small"}},
				{name:'depth',calloutOffset:20,sliderParams:{"Height":15,"Width":226,"OverlayHeight":35,"GrabbyWidth":10,"GrabbyHeight":17,"Min":45,"Max":86,"TooltipEnabled":true,"formatTooltipValue":formatNumber1,"LeftTooltipOffsetLeft":-35,"LeftTooltipOffsetTop":3,"RightTooltipOffsetLeft":-25+rightTooltipOffset,"RightTooltipOffsetTop":3,"ClassPostFix":"-small"}},
				{name:'table',calloutOffset:20,sliderParams:{"Height":15,"Width":226,"OverlayHeight":35,"GrabbyWidth":10,"GrabbyHeight":17,"Min":49,"Max":89,"TooltipEnabled":true,"formatTooltipValue":formatDouble,"LeftTooltipOffsetLeft":-35,"LeftTooltipOffsetTop":3,"RightTooltipOffsetLeft":-25+rightTooltipOffset,"RightTooltipOffsetTop":3,"ClassPostFix":"-small"}},
				{name:'size',calloutOffset:20,sliderParams:{"Height":15,"Width":226,"OverlayHeight":35,"GrabbyWidth":10,"GrabbyHeight":17,"Min":0.50,"Max":2.75,"TooltipEnabled":true,"formatTooltipValue":formatNumber2,"LeftTooltipOffsetLeft":-35,"LeftTooltipOffsetTop":3,"RightTooltipOffsetLeft":-25+rightTooltipOffset,"RightTooltipOffsetTop":3,"ClassPostFix":"-small"}},
				{name:'fluor',calloutOffset:20,sliderParams:{"Height":36,"Width":226,"OverlayHeight":35,"GrabbyWidth":10,"GrabbyHeight":17,"Min":46,"Max":41,"Discrete":true,"Ticks":5,"ClassPostFix":"-small"}}];
		
		g_miniSliders = [ {name:'price-mini',calloutOffset:20,sliderParams:{"Height":18,"Width":427,"OverlayHeight":16,"GrabbyWidth":10,"GrabbyHeight":17,"Min":250,"Max":500000,"TooltipEnabled":true,"getValueFunction":Adiamor.ui.Slider.expGetValueFunction,"setValueFunction":Adiamor.ui.Slider.expSetValueFunction,"formatTooltipValue":formatMoney0,"LeftTooltipOffsetLeft":-35,"LeftTooltipOffsetTop":1,"RightTooltipOffsetLeft":-25+rightTooltipOffset,"RightTooltipOffsetTop":1,"Slope":100,"ClassPostFix":"-mini"}},
				{name:'carat-mini',calloutOffset:20,sliderParams:{"Height":18,"Width":427,"OverlayHeight":16,"GrabbyWidth":10,"GrabbyHeight":17,"Min":0.30,"Max":15.01,"TooltipEnabled":true,"getValueFunction":Adiamor.ui.Slider.expGetValueFunction,"setValueFunction":Adiamor.ui.Slider.expSetValueFunction,"formatTooltipValue":formatCarat,"LeftTooltipOffsetLeft":-35,"LeftTooltipOffsetTop":1,"RightTooltipOffsetLeft":-25+rightTooltipOffset,"RightTooltipOffsetTop":1,"Slope":0.1,"ClassPostFix":"-mini"}},
				{name:'cut-mini',calloutOffset:20,sliderParams:{"Height":31,"Width":427,"OverlayHeight":16,"GrabbyWidth":10,"Discrete":true,"Ticks":5,"GrabbyHeight":17,"Min":0,"Max":5,"ClassPostFix":"-mini"}},
				{name:'color-mini',calloutOffset:20,sliderParams:{"Height":31,"Width":427,"OverlayHeight":16,"GrabbyWidth":10,"Discrete":true,"Ticks":7,"GrabbyHeight":17,"Min":29,"Max":22,"ClassPostFix":"-mini"}},
				{name:'clarity-mini',calloutOffset:20,sliderParams:{"Height":31,"Width":427,"OverlayHeight":16,"GrabbyWidth":10,"Discrete":true,"Ticks":7,"GrabbyHeight":17,"Min":37,"Max":30,"ClassPostFix":"-mini"}}];
	}

	Adiamor.html.attachEvent(document, 'mouseover', abortDrag);

	g_extendedSliders = $('slider-extension-container');

	if (Adiamor.browser.IE7)
	{
		g_extendedSliders.style.height = g_sliderExtensionHeightFinal+'px';
		Adiamor.html.getFirstChild(g_extendedSliders).style.height = g_sliderExtensionHeightFinal+'px';

		$('slider-extension-show').style.display = 'none';
		$('slider-extension-hide').style.display = 'block';
	}

	g_queryMask = $('query-mask');
	g_queryBuilderPanel = $('query-builder');
	g_queryResultsPanel = $('query-results');

	Adiamor.dom.setOpacity(g_queryMask, 0);
	Adiamor.html.align(g_queryMask, g_queryBuilderPanel, Adiamor.al | Adiamor.at);
	g_queryMask.style.display = 'none';

	g_resultsPanel = new Adiamor.ui.Panel();
	g_resultsPanel.attachToParent($("slider-results-container"));
//	Adiamor.html.addUnload(Adiamor.lang.close(g_resultsPanel, g_resultsPanel.dispose));

	g_grid = new Adiamor.ui.GridList();
	g_grid.RowCount = 500;
	g_grid.RowHeight = 20;
//	Adiamor.html.addUnload(Adiamor.lang.close(g_grid, g_grid.dispose));


	var scrollbar = new Adiamor.ui.VerticalScrollbar();
	scrollbar.attachToParent($("VerticalScrollbarContainer"));
	scrollbar.setRange(10000);
//	Adiamor.html.addUnload(Adiamor.lang.close(scrollbar, scrollbar.dispose));

	g_grid.setScrollbar(scrollbar);

	g_diamondData = new Adiamor.data.PagedJsonDataView();
	g_diamondData.initialize({'GetHandler':g_getHandlerUrl});
	g_diamondData.OnRowCountChanged.subscribe(updateResultsPanel, g_resultsPanel);
	g_diamondData.OnDataReady.subscribe(setSliderLimits);
//	Adiamor.html.addUnload(Adiamor.lang.close(g_diamondData, g_diamondData.dispose));

	g_grid.setDataSource(g_diamondData);

	g_grid.OnMouseOver.subscribe(rowMouseOverHandler);
	g_grid.OnMouseOut.subscribe(hideInfoPanel);
	g_grid.attachToParent(null, $("myGridList"));
	
	Adiamor.lang.forEach(g_mainSliders, setupMainSlider);
	Adiamor.lang.forEach(g_checkboxes, setupCheckbox);
	if (Adiamor.browser.IE7) { hideSliders(); }

	g_rowInfoPanel = new Adiamor.ui.Panel();
	g_rowInfoPanel.attachToParent($('panel-rowdetail'));
	g_rowInfoPanel.setBackgroundImage(g_imagePath+'row_info_callout.png');
	g_rowInfoPanel.setWidth(198);
	g_rowInfoPanel.setHeight(290);
	g_rowInfoPanel.OnMouseOver.subscribe(preventHide);
	g_rowInfoPanel.OnMouseOut.subscribe(hideInfoPanel);

	g_rowInfoPanelArrow = new Adiamor.ui.Panel();
	g_rowInfoPanelArrow.attachToParent($('panel-rowdetail-arrow'));
	g_rowInfoPanelArrow.setBackgroundImage(g_imagePath+'row_info_callout-arrow.png');
	g_rowInfoPanelArrow.setWidth(13);
	g_rowInfoPanelArrow.setHeight(20);

//	Adiamor.html.addUnload(Adiamor.lang.close(g_rowInfoPanel, g_rowInfoPanel.dispose));

	g_rowComparePanel = new Adiamor.ui.Panel();
	g_rowComparePanel.attachToParent($('panel-rowcompare'));
	g_rowComparePanel.setBackgroundImage(g_imagePath+'row-compare-callout.png');
	g_rowComparePanel.setWidth(154);
	g_rowComparePanel.setHeight(169);
//	Adiamor.html.addUnload(Adiamor.lang.close(g_rowComparePanel, g_rowComparePanel.dispose));

	g_rowCompareContents = $('panel-rowcompare-contents');
	Adiamor.html.attachEvent(g_rowCompareContents, 'mouseover', function() { window.clearTimeout(g_rowComparePanelTimeout); });
	Adiamor.html.attachEvent(g_rowCompareContents, 'mouseout', hideComparePanelHandler);

	g_colChooserPanel = new Adiamor.ui.Panel();
	g_colChooserPanel.attachToParent($('panel-columnchooser'));
	g_colChooserPanel.setBackgroundImage(g_imagePath+'chooserback_new.png');
//	Adiamor.html.addUnload(Adiamor.lang.close(g_colChooserPanel, g_colChooserPanel.dispose));

	// Setup the column chooser panel
	g_colChooserContents = $('panel-columnchooser-contents');

	g_colChooserButton = $('columnchooser-button');
	Adiamor.html.attachEvent(g_colChooserButton, 'mousedown', toggleColChooserPanel);

	// Attach events for buttons to show / hide the extra sliders.
	Adiamor.html.attachEvent($('slider-extension-show'), 'click', showSliders);
	Adiamor.html.attachEvent($('slider-extension-hide'), 'click', hideSliders);

	// Attach events for buttons to hide the query and show the results
	Adiamor.html.attachEvent($('show-results-button'), 'click', hideQueryBuilder);
	Adiamor.html.attachEvent($('show-results-button-small'), 'click', hideQueryBuilder);

	// Attach events for buttons to hide the results and show the query
	Adiamor.html.attachEvent($('show-query-button1'), 'click', hideQueryResults);
	Adiamor.html.attachEvent($('show-query-button2'), 'click', hideQueryResults);
	
	Adiamor.html.attachEvent($('query-collapse'), 'click', collapseSliders);	
	
	// Attach events for labels to hide/show the optional search criteria sliders
	Adiamor.html.attachEvent($('label-polish'), 'click', displayOptionalSlider);
	Adiamor.html.attachEvent($('label-symmetry'), 'click', displayOptionalSlider);
	Adiamor.html.attachEvent($('label-depth'), 'click', displayOptionalSlider);
	Adiamor.html.attachEvent($('label-table'), 'click', displayOptionalSlider);
	Adiamor.html.attachEvent($('label-size'), 'click', displayOptionalSlider);
	Adiamor.html.attachEvent($('label-fluor'), 'click', displayOptionalSlider);

	// Setup support for backbutton between the two pages.
	Adiamor.browser.History.instance = new Adiamor.browser.History();
	Adiamor.browser.History.instance.OnChange.subscribe(restoreBackButtonState);

	restoreState();
	
	if(window.location.href.indexOf("col=Canada") >= 0 || window.location.href.indexOf("canadian-diamonds") >= 0 || window.location.href.indexOf("Canadian-Diamonds") >= 0)
	{
		CanadaInit();
	}	

	window.onresize = function(event) {
		var pURL = unescape(window.location.pathname);
		if(Adiamor.browser.IE)
		{
			if(getDocHeight() == Adiamor.browser.DocumentHeight)
			{}
			else
			{
				/*Adiamor.browser.DocumentHeight = getDocHeight();
				Adiamor.base.uid = 1;
				init();*/
				//window.location.replace( pURL );
			}
		}
		else
		{
			/*Adiamor.base.uid = 1;
			init();*/
			window.location.replace( pURL );
		}
	}
}

function CanadaInit()
{
	g_getHandlerUrl = 'CanadaSearch.aspx';
	
	var headertext = $('HeaderText');
	headertext.innerHTML = "THIS TEXT IS BLUE NILE'S.  NEEDS COPY TEXT.  In the last twenty years, Canada has become the world's third largest diamond supplier, producing ";
	headertext.innerHTML += "approximately 15% of the world's diamonds. Along with the other diamond producing countries, Canada follows the Kimberley Process and has taken ";
	headertext.innerHTML += "a strong leadership role in the diamond industry ensuring their diamonds are produced with strict adherence to ethical and environmental ";
	headertext.innerHTML += "guidelines and fair labor practices.<br/><br/>";
	
	headertext.innerHTML += "Canadian diamonds purchased from Blue Nile will be accompanied by a Canadian diamond certificate that states the cut of the diamond, the ";
	headertext.innerHTML += "rough weight, and the polished weight, as well as the Canadian diamond certification number.";
	
	headertext.style.margin="8px 20px";
	
	$('diamondSearchTitle').src="../images/textpics/canadaSearchTitle.gif";
	$('query-builder').style.display="none";
	$('query-results-filter').style.display="none";
	$('CanInput').style.display="inline";
	
	ShapeChange('round');
}

/**
 * Initializes the application. To be called once the DOM is fully loaded.
 */
function affinityinit()
{
	var rightTooltipOffset = 40;
	if (!Adiamor.browser.IE) { rightTooltipOffset = 40; }

	g_mainSliders = [	{name:'price',calloutOffset:120,sliderParams:{"Height":60,"OverlayHeight":47,"TooltipEnabled":true,"Min":250,"Max":500000,"getValueFunction":Adiamor.ui.Slider.expGetValueFunction,"setValueFunction":Adiamor.ui.Slider.expSetValueFunction,"formatTooltipValue":formatMoney0,"LeftTooltipOffsetLeft":-30,"RightTooltipOffsetLeft":-27+rightTooltipOffset,"LeftTooltipOffsetTop":-11,"RightTooltipOffsetTop":-11,"Slope":120}},
	                 	{name:'carat',calloutOffset:56,sliderParams:{"Height":60,"OverlayHeight":47,"TooltipEnabled":true,"Min":0.30,"Max":15,"getValueFunction":Adiamor.ui.Slider.expGetValueFunction,"setValueFunction":Adiamor.ui.Slider.expSetValueFunction,"formatTooltipValue":formatCarat,"LeftTooltipOffsetLeft":-20,"RightTooltipOffsetLeft":-27+rightTooltipOffset,"LeftTooltipOffsetTop":-11,"RightTooltipOffsetTop":-11,"Slope":0.05}},
						{name:'cut',calloutOffset:4,sliderParams:{"Min":0,"Max":5,"Discrete":true,"Ticks":5}},
						{name:'color',calloutOffset:-38,sliderParams:{"Min":29,"Max":22,"Discrete":true,"Ticks":7}},
						{name:'clarity',calloutOffset:-76,sliderParams:{"Min":37,"Max":30,"Discrete":true,"Ticks":7}}];

	if(!Adiamor.browser.IE6)
	{
		g_smallSliders = [{name:'polish',calloutOffset:120,sliderParams:{"Height":177,"Width":121,"GrabbyWidth":74,"GrabbyHeight":9,"Min":63,"Max":60,"Discrete":true,"Ticks":3,"ClassPostFix":"-small"}},
					{name:'sym',calloutOffset:120,sliderParams:{"Height":177,"Width":121,"GrabbyWidth":74,"GrabbyHeight":9,"Min":63,"Max":60,"Discrete":true,"Ticks":3,"ClassPostFix":"-small"}},
					{name:'depth',calloutOffset:45,sliderParams:{"Height":177,"Width":121,"GrabbyWidth":74,"GrabbyHeight":9,"Min":45,"Max":86,"TooltipEnabled":true,"formatTooltipValue":formatNumber1,"BottomTooltipOffsetTop":10,"BottomTooltipOffsetLeft":40,"TopTooltipOffsetTop":-20,"TopTooltipOffsetLeft":40,"ClassPostFix":"-small"}},
					{name:'table',calloutOffset:85,sliderParams:{"Height":177,"Width":121,"GrabbyWidth":74,"GrabbyHeight":9,"Min":49,"Max":89,"TooltipEnabled":true,"formatTooltipValue":formatDouble,"BottomTooltipOffsetTop":10,"BottomTooltipOffsetLeft":40,"TopTooltipOffsetTop":-20,"TopTooltipOffsetLeft":40,"ClassPostFix":"-small"}},
					{name:'size',calloutOffset:75,sliderParams:{"Height":177,"Width":121,"GrabbyWidth":74,"GrabbyHeight":9,"Min":0.50,"Max":2.75,"TooltipEnabled":true,"formatTooltipValue":formatNumber2,"BottomTooltipOffsetTop":10,"BottomTooltipOffsetLeft":40,"TopTooltipOffsetTop":-20,"TopTooltipOffsetLeft":40,"ClassPostFix":"-small"}},
					{name:'fluor',calloutOffset:5,sliderParams:{"Height":177,"Width":121,"GrabbyWidth":74,"GrabbyHeight":9,"Min":46,"Max":41,"Discrete":true,"Ticks":5,"ClassPostFix":"-small"}}];
		g_miniSliders = [ {name:'price-mini',calloutOffset:20,sliderParams:{"Height":18,"Width":427,"OverlayHeight":35,"GrabbyWidth":10,"GrabbyHeight":18,"Min":250,"Max":500000,"TooltipEnabled":true,"getValueFunction":Adiamor.ui.Slider.expGetValueFunction,"setValueFunction":Adiamor.ui.Slider.expSetValueFunction,"formatTooltipValue":formatMoney0,"LeftTooltipOffsetLeft":-35,"LeftTooltipOffsetTop":1,"RightTooltipOffsetLeft":-25+rightTooltipOffset,"RightTooltipOffsetTop":1,"Slope":100,"ClassPostFix":"-mini"}},
						{name:'carat-mini',calloutOffset:20,sliderParams:{"Height":18,"Width":427,"OverlayHeight":35,"GrabbyWidth":10,"GrabbyHeight":18,"Min":0.30,"Max":15,"TooltipEnabled":true,"getValueFunction":Adiamor.ui.Slider.expGetValueFunction,"setValueFunction":Adiamor.ui.Slider.expSetValueFunction,"formatTooltipValue":formatCarat,"LeftTooltipOffsetLeft":-35,"LeftTooltipOffsetTop":1,"RightTooltipOffsetLeft":-25+rightTooltipOffset,"RightTooltipOffsetTop":1,"Slope":0.1,"ClassPostFix":"-mini"}},
						{name:'cut-mini',calloutOffset:20,sliderParams:{"Height":31,"Width":427,"OverlayHeight":35,"GrabbyWidth":10,"Discrete":true,"Ticks":5,"GrabbyHeight":18,"Min":0,"Max":5,"ClassPostFix":"-mini"}},
						{name:'color-mini',calloutOffset:20,sliderParams:{"Height":31,"Width":427,"OverlayHeight":35,"GrabbyWidth":10,"Discrete":true,"Ticks":7,"GrabbyHeight":18,"Min":29,"Max":22,"ClassPostFix":"-mini"}},
						{name:'clarity-mini',calloutOffset:20,sliderParams:{"Height":31,"Width":427,"OverlayHeight":35,"GrabbyWidth":10,"Discrete":true,"Ticks":7,"GrabbyHeight":18,"Min":37,"Max":30,"ClassPostFix":"-mini"}}];
	}
	else
	{
		g_smallSliders = [{name:'polish',calloutOffset:120,sliderParams:{"Height":177,"Width":121,"GrabbyWidth":74,"GrabbyHeight":9,"Min":63,"Max":60,"Discrete":true,"Ticks":3,"ClassPostFix":"-small"}},
					{name:'sym',calloutOffset:120,sliderParams:{"Height":177,"Width":121,"GrabbyWidth":74,"GrabbyHeight":9,"Min":63,"Max":60,"Discrete":true,"Ticks":3,"ClassPostFix":"-small"}},
					{name:'depth',calloutOffset:45,sliderParams:{"Height":177,"Width":121,"GrabbyWidth":74,"GrabbyHeight":9,"Min":45,"Max":86,"TooltipEnabled":true,"formatTooltipValue":formatNumber1,"BottomTooltipOffsetTop":15,"BottomTooltipOffsetLeft":40,"TopTooltipOffsetTop":-20,"TopTooltipOffsetLeft":40,"ClassPostFix":"-small"}},
					{name:'table',calloutOffset:85,sliderParams:{"Height":177,"Width":121,"GrabbyWidth":74,"GrabbyHeight":9,"Min":49,"Max":89,"TooltipEnabled":true,"formatTooltipValue":formatDouble,"BottomTooltipOffsetTop":15,"BottomTooltipOffsetLeft":40,"TopTooltipOffsetTop":-20,"TopTooltipOffsetLeft":40,"ClassPostFix":"-small"}},
					{name:'size',calloutOffset:75,sliderParams:{"Height":177,"Width":121,"GrabbyWidth":74,"GrabbyHeight":9,"Min":0.50,"Max":2.75,"TooltipEnabled":true,"formatTooltipValue":formatNumber2,"BottomTooltipOffsetTop":15,"BottomTooltipOffsetLeft":40,"TopTooltipOffsetTop":-20,"TopTooltipOffsetLeft":40,"ClassPostFix":"-small"}},
					{name:'fluor',calloutOffset:5,sliderParams:{"Height":177,"Width":121,"GrabbyWidth":74,"GrabbyHeight":9,"Min":46,"Max":41,"Discrete":true,"Ticks":5,"ClassPostFix":"-small"}}];
		
		g_miniSliders = [ {name:'price-mini',calloutOffset:20,sliderParams:{"Height":18,"Width":427,"OverlayHeight":16,"GrabbyWidth":10,"GrabbyHeight":18,"Min":250,"Max":500000,"TooltipEnabled":true,"getValueFunction":Adiamor.ui.Slider.expGetValueFunction,"setValueFunction":Adiamor.ui.Slider.expSetValueFunction,"formatTooltipValue":formatMoney0,"LeftTooltipOffsetLeft":-35,"LeftTooltipOffsetTop":1,"RightTooltipOffsetLeft":-25+rightTooltipOffset,"RightTooltipOffsetTop":1,"Slope":100,"ClassPostFix":"-mini"}},
						{name:'carat-mini',calloutOffset:20,sliderParams:{"Height":18,"Width":427,"OverlayHeight":16,"GrabbyWidth":10,"GrabbyHeight":18,"Min":0.30,"Max":15,"TooltipEnabled":true,"getValueFunction":Adiamor.ui.Slider.expGetValueFunction,"setValueFunction":Adiamor.ui.Slider.expSetValueFunction,"formatTooltipValue":formatCarat,"LeftTooltipOffsetLeft":-35,"LeftTooltipOffsetTop":1,"RightTooltipOffsetLeft":-25+rightTooltipOffset,"RightTooltipOffsetTop":1,"Slope":0.1,"ClassPostFix":"-mini"}},
						{name:'cut-mini',calloutOffset:20,sliderParams:{"Height":31,"Width":427,"OverlayHeight":16,"GrabbyWidth":10,"Discrete":true,"Ticks":5,"GrabbyHeight":18,"Min":0,"Max":5,"ClassPostFix":"-mini"}},
						{name:'color-mini',calloutOffset:20,sliderParams:{"Height":31,"Width":427,"OverlayHeight":16,"GrabbyWidth":10,"Discrete":true,"Ticks":7,"GrabbyHeight":18,"Min":29,"Max":22,"ClassPostFix":"-mini"}},
						{name:'clarity-mini',calloutOffset:20,sliderParams:{"Height":31,"Width":427,"OverlayHeight":16,"GrabbyWidth":10,"Discrete":true,"Ticks":7,"GrabbyHeight":18,"Min":37,"Max":30,"ClassPostFix":"-mini"}}];
	}

	Adiamor.html.attachEvent(document, 'mouseover', abortDrag);

	g_extendedSliders = $('slider-extension-container');

	if (Adiamor.browser.IE7)
	{
		g_extendedSliders.style.height = g_sliderExtensionHeightFinal+'px';
		Adiamor.html.getFirstChild(g_extendedSliders).style.height = g_sliderExtensionHeightFinal+'px';

		$('slider-extension-show').style.display = 'none';
		$('slider-extension-hide').style.display = 'block';
	}

	g_queryMask = $('query-mask');
	g_queryBuilderPanel = $('query-builder');
	g_queryResultsPanel = $('query-results');

	Adiamor.dom.setOpacity(g_queryMask, 0);
	Adiamor.html.align(g_queryMask, g_queryBuilderPanel, Adiamor.al | Adiamor.at);
	g_queryMask.style.display = 'none';

	g_resultsPanel = new Adiamor.ui.Panel();
	g_resultsPanel.attachToParent($("slider-results-container"));

	g_grid = new Adiamor.ui.GridList();
	g_grid.RowCount = 500;
	g_grid.RowHeight = 20;


	var scrollbar = new Adiamor.ui.VerticalScrollbar();
	scrollbar.attachToParent($("VerticalScrollbarContainer"));
	scrollbar.setRange(10000);

	g_grid.setScrollbar(scrollbar);

	g_diamondData = new Adiamor.data.PagedJsonDataView();
	g_diamondData.initialize({'GetHandler':g_getHandlerUrl});
	g_diamondData.OnRowCountChanged.subscribe(updateResultsPanel, g_resultsPanel);
	g_diamondData.OnDataReady.subscribe(setSliderLimits);

	g_grid.setDataSource(g_diamondData);

	g_grid.OnMouseOver.subscribe(rowMouseOverHandler);
	g_grid.OnMouseOut.subscribe(hideInfoPanel);
	g_grid.attachToParent(null, $("myGridList"));

	Adiamor.lang.forEach(g_mainSliders, setupMainSlider);
	Adiamor.lang.forEach(g_checkboxes, setupCheckbox);
	if (Adiamor.browser.IE7) { hideSliders(); }

	g_rowInfoPanel = new Adiamor.ui.Panel();
	g_rowInfoPanel.attachToParent($('panel-rowdetail'));
	g_rowInfoPanel.setBackgroundImage(g_imagePath+'row_info_callout.png');
	g_rowInfoPanel.setWidth(198);
	g_rowInfoPanel.setHeight(290);

	g_rowInfoPanelArrow = new Adiamor.ui.Panel();
	g_rowInfoPanelArrow.attachToParent($('panel-rowdetail-arrow'));
	g_rowInfoPanelArrow.setBackgroundImage(g_imagePath+'row_info_callout-arrow.png');
	g_rowInfoPanelArrow.setWidth(13);
	g_rowInfoPanelArrow.setHeight(20);

	g_rowComparePanel = new Adiamor.ui.Panel();
	g_rowComparePanel.attachToParent($('panel-rowcompare'));
	g_rowComparePanel.setBackgroundImage(g_imagePath+'row-compare-callout.png');
	g_rowComparePanel.setWidth(154);
	g_rowComparePanel.setHeight(169);

	g_rowCompareContents = $('panel-rowcompare-contents');
	Adiamor.html.attachEvent(g_rowCompareContents, 'mouseover', function() { window.clearTimeout(g_rowComparePanelTimeout); });
	Adiamor.html.attachEvent(g_rowCompareContents, 'mouseout', hideComparePanelHandler);

	g_colChooserPanel = new Adiamor.ui.Panel();
	g_colChooserPanel.attachToParent($('panel-columnchooser'));
	g_colChooserPanel.setBackgroundImage(g_imagePath+'chooserback_new.png');

	// Setup the column chooser panel
	g_colChooserContents = $('panel-columnchooser-contents');

	g_colChooserButton = $('columnchooser-button');
	Adiamor.html.attachEvent(g_colChooserButton, 'mousedown', toggleColChooserPanel);

	// Attach events for buttons to show / hide the extra sliders.
	Adiamor.html.attachEvent($('slider-extension-show'), 'click', showSliders);
	Adiamor.html.attachEvent($('slider-extension-hide'), 'click', hideSliders);

	// Attach events for buttons to hide the query and show the results
	Adiamor.html.attachEvent($('show-results-button'), 'click', hideQueryBuilder);
	Adiamor.html.attachEvent($('show-results-button-small'), 'click', hideQueryBuilder);

	// Attach events for buttons to hide the results and show the query
	Adiamor.html.attachEvent($('show-query-button1'), 'click', hideQueryResults);
	Adiamor.html.attachEvent($('show-query-button2'), 'click', hideQueryResults);
	
	Adiamor.html.attachEvent($('query-collapse'), 'click', collapseSliders);

	// Setup support for backbutton between the two pages.
	Adiamor.browser.History.instance = new Adiamor.browser.History();
	Adiamor.browser.History.instance.OnChange.subscribe(restoreBackButtonState);

	restoreState();
}

function scrollMove(position)
{
	g_grid.Scrollbar.HtmlElement.scrollTop=position;
}

/**
 * Collects the IDs of all the diamonds that are selected in the data grid and 
 * directs the browser to the compare diamonds page.
 */
function compareDiamonds()
{
	var selectedDiamonds = g_grid.SelectedRows;
	var idList = "";
	var cookieValue = readCookie("compare");
	idList = cookieValue;
	if(cookieValue != null)
	{
		cookieValue = cookieValue.split("-");
	}
	if(idList == "0" || idList == null) { idList = ""; }
		
	var count = 0;
	for (var item2 in selectedDiamonds)
	{
		if (selectedDiamonds.hasOwnProperty(item2)) {
			count++;
		}	
	}
	
	if(count > 1)
	{
		for (var item in selectedDiamonds)
		{
			if (selectedDiamonds.hasOwnProperty(item)) {
				var rowIndex = item;
				var Id = g_diamondData.getMappedValue(rowIndex, g_grid.ColumnsMap.ID);
				if(idList.indexOf(Id) == -1) { idList = idList + "D|" + Id + "-"; }
			}	
		}
		
		var items = idList.split("-");
		idList = "";
		
		for(var i=0; i<items.length; i++)
		{
			if(items[i].indexOf("D") == -1 && items[i].indexOf("R") == -1 && items[i].indexOf("E") == -1 && items[i].indexOf("P") == -1 && items[i].indexOf("B") == -1 && items[i].indexOf("T") == -1)
			{
				items[i] = "D|"+items[i];
			}	
			if(items[i] != "")
			{
				if(i != items.length-1) { idList += items[i] + "-"; }
			}
		}
		
		createCookie("compare", idList, 90);
		window.location="http://www.adiamor.com/Diamonds/Search";
	}
	else { alert("Please select at least two items to compare."); }
}

/**
 * Shows the panel with the compare button.
 */
function showComparePanel(row)
{
	var dRow = parseInt(row.getAttribute('row'),10);

	var topOffset = -g_rowComparePanel.Container.offsetHeight/2-83;
	if (Adiamor.browser.MOZ)
	{
		topOffset -= $("ListDataFrame").scrollTop;
	}

	showElement(g_rowComparePanel.Container);
	showElement(g_rowCompareContents);

	Adiamor.html.align(g_rowComparePanel.Container, row, Adiamor.at | Adiamor.al, 0, 0, topOffset, -g_rowComparePanel.Container.offsetWidth + 10);
	Adiamor.html.align(g_rowCompareContents, row, Adiamor.at | Adiamor.al, 0, 0, topOffset, -g_rowComparePanel.Container.offsetWidth + 10);
}

//***********************************************
//******** COLUMN CHOOSER ***********************
//***********************************************

/**
 * Displays the columns the user chooses from the chooser.
 */
function showColumns()
{
	var vc = 0;
	Adiamor.lang.forEach(g_grid.Columns, function(item) 
		{
			var cb = $(item.Name.toLowerCase() + '_cb');
			if (cb != null)
			{
				if (cb.checked) {
					vc++;
				}
			}
			else if(item.Display)
			{
				vc++;	
			}
		}
	);
	
	Adiamor.lang.forEach(g_grid.Columns, function(item) 
		{
			// Get the checkbox control and see if it exists.
			var cb = $(item.Name.toLowerCase() + '_cb');
			if (cb != null)
			{
				if (cb.checked) {
					item.cssStyle.display = '';
				} else {
					item.cssStyle.display = 'none';
				}
			}
			
			if(item.Display || cb != null)
			{
				var width = GetColumnWidth(item,vc);
				if(width != null)
				{
					item.cssStyle.width=width+'px';
					item.Width=width;
				}
			}
		}
	);
	hideColChooserPanel();
	
	g_grid.render();
}

/*
 * Gets the width of the column based on number of columns visible
 */
function GetColumnWidth(item,vc)
{
	var width = item.OriginalWidth;
	switch(item.Name)
	{
		case "Shape":
			if(vc < 10)
			{
				width = 80;
				g_types["image"].Formatter=Adiamor.ui.Viewport.renderImage;
			}
			else if(vc == 10)
			{
				width = 74;
				g_types["image"].Formatter=Adiamor.ui.Viewport.renderImage;
			}
			else if(vc == 11)
			{
				width = 63;
				g_types["image"].Formatter=Adiamor.ui.Viewport.renderImageOnly;
			}
			else if(vc == 12)
			{
				width = 52;
				g_types["image"].Formatter=Adiamor.ui.Viewport.renderImageOnly;
			}
			else if(vc == 13)
			{
				width = 51;
				g_types["image"].Formatter=Adiamor.ui.Viewport.renderImageOnly;
			}
			else if(vc == 14)
			{
				width = 45;
				g_types["image"].Formatter=Adiamor.ui.Viewport.renderImageOnly;
			}
			else if(vc == 15)
			{
				width = 39;
				g_types["image"].Formatter=Adiamor.ui.Viewport.renderImageOnly;
			}
			break;
		case "Carat":
			if(vc < 10)
			{
				width = 75;
			}
			else if(vc == 10)
			{
				width = 65;
			}
			else if(vc == 11)
			{
				width = 55;
			}
			else if(vc == 12 || vc == 13)
			{
				width = 50;
			}
			else if(vc == 14)
			{
				width = 45;
			}
			else if(vc == 15)
			{
				width = 40;
			}
			break;
		case "Color":
			if(vc < 10)
			{
				width = 74;
			}
			else if(vc == 10)
			{
				width = 64;
			}
			else if(vc == 11)
			{
				width = 54;
			}
			else if(vc == 12)
			{
				width = 49;
			}
			else if(vc == 13)
			{
				width = 44;
			}
			else if(vc == 14)
			{
				width = 39;
			}
			else if(vc == 15)
			{
				width = 35;
			}
			break;
		case "Clar":
			if(vc < 10)
			{
				$('h'+item.Name).innerHTML = "Clarity";
				width = 80;
			}
			else if(vc == 10)
			{
				$('h'+item.Name).innerHTML = "Clarity";
				width = 70;
			}
			else if(vc == 11 || vc == 12)
			{
				$('h'+item.Name).innerHTML = "Clarity";
				width = 60;
			}
			else if(vc == 13)
			{
				$('h'+item.Name).innerHTML = "Clar.";
				width = 45;
			}
			else if(vc == 14)
			{
				$('h'+item.Name).innerHTML = "Clar.";
				width = 40;
			}
			else if(vc == 15)
			{
				$('h'+item.Name).innerHTML = "Clar.";
				width = 35;
			}
			break;
		case "Cut":
			if(vc < 10)
			{
				width = 79;
			}
			else if(vc == 10 || vc == 11 || vc == 12)
			{
				width = 74;
			}
			else if(vc == 13)
			{
				width = 44;
			}
			else if(vc == 14)
			{
				width = 39;
			}
			else if(vc == 15)
			{
				width = 35;
			}
			break;
		case "Cert":
			if(vc < 10)
			{
				$('h'+item.Name).innerHTML = "Certificate";
				width = 75;
			}
			else if(vc == 10 || vc == 11)
			{
				$('h'+item.Name).innerHTML = "Certificate";
				width = 75;
			}
			else if(vc == 12 || vc == 13)
			{
				$('h'+item.Name).innerHTML = "Cert.";
				width = 55;
			}
			else if(vc == 14)
			{
				$('h'+item.Name).innerHTML = "Cert.";
				width = 45;
			}
			else if(vc == 15)
			{
				$('h'+item.Name).innerHTML = "Cert.";
				width = 38;
			}
			break;
		case "SPrice":
			if(vc < 10)
			{
				$('h'+item.Name).innerHTML = "Price";
				width = 75;
			}
			else if(vc == 10)
			{
				$('h'+item.Name).innerHTML = "Price";
				width = 65;
			}
			else if(vc > 10)
			{
				$('h'+item.Name).innerHTML = "Price";
				width = 55;
			}
			break;
		case "Selected":
			if(vc < 12)
			{
				width = 78;
			}
			else if(vc >= 12)
			{
				width = 68;
			}
			break;
		case "Info":
			if(vc < 14)
			{
				$('h'+item.Name).innerHTML = "Details";
				width = 62;
			}
			else if(vc == 14)
			{
				$('h'+item.Name).innerHTML = "Details";
				width = 47;
			}
			break;
		case "Pol":
			if(vc < 15)
			{
				width = 40;
			}
			else if(vc == 15)
			{
				width = 35;
			}
			break;
		case "Sym":
			if(vc < 15)
			{
				width = 40;
			}
			else if(vc == 15)
			{
				width = 35;
			}
			break;
		case "Depth":
			if(vc < 15)
			{
				width = 40;
			}
			else if(vc == 15)
			{
				width = 35;
			}
			break;
		case "Tbl":
			if(vc < 15)
			{
				width = 40;
			}
			else if(vc == 15)
			{
				width = 35;
			}
			break;
		default:
			break;
	}
	return width;
} 


/**
 * Handles the mouseout event of the column chooser button. This sets a timeout such that the
 * mouse may get over top of the column chooser panel such that the panel does not disappear.
 */
function handleColChooserButtonMouseOut(evtObj, evtElem, clear)
{
	if (clear)
	{
		window.clearTimeout(g_colChooserPanelTimeout);
		g_colChooserPanelTimeout = null;
		hideColChooserPanel();
	}
	else
	{
		g_colChooserPanelTimeout = window.setTimeout(hideColChooserPanel, 20);
	}
}

/**
 * Handles mouseout events from the column chooser panel. This checks to see if the the toElement
 * of the mouseout event also has the same ancestor or not - if so then it is an internal mouseout.
 */
function hideColChooserPanelHandler(evtObj)
{
	// Check if the toElement of the mouseout event is a child of the col choser panel or not. 
	var colChooserPanel = findElement(evtObj.toElement, 'panel-columnchooser');
	if (colChooserPanel == null)
	{
		hideColChooserPanel();
	}
}

/**
 * Function used for starting the application. This function just checks for a DOM element with ID="init" and when that DOM 
 * node is ready the application can be started. 
 */
function load()
{
	if(document.getElementById('init') != null) {
		Adiamor.browser.DocumentHeight = getDocHeight();
		init();
	}
	else if(document.getElementById('affinityinit') != null) { affinityinit(); }
	else { window.setTimeout(load, 25); }
	var cDiv = $('currency');
	if(cDiv != null) { cDiv.style.display="none"; }
}

load();
