// Vovici Client Side Survey API
// Copyright 1997-2010 Vovici Corporation. All rights reserved.
// Version: 5.4.0

// Implement swapNode for older browsers
try {
	if (!Node.prototype.swapNode) {
		Node.prototype.swapNode = function(node) {
			var nextSibling = this.nextSibling;
			if (nextSibling == node) nextSibling = nextSibling.nextSibling;
			if (nextSibling == null) nextSibling = this;
			var parentNode = this.parentNode;
			node.parentNode.replaceChild(this, node);
			parentNode.insertBefore(node, nextSibling);
		}
	}
} catch (e) { }

/// <summary>
/// Creates a new instance of the Client Side Survey API.
/// </summary>
function VcSurvey(arg) {
	this.Culture = 'en-US';
	// Number Formatting Defaults
	this.NumberDecimalSeparator = '.';
	this.NumberGroupSeparator = ',';
	this.NumberGroupSizes = 3;
	// Date Picker Defaults
	this.PrevText = 'Back';
	this.NextText = 'Next';
	this.MonthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
	this.MonthNamesShort = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
	this.DayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
	this.DayNamesShort = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
	this.DayNamesMin = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'];
	this.DateFormat = 'mm/dd/yyyy';
	this.DateSeparator = '/'
	this.FirstDay = 0;
	this.IsRTL = false;	
	this.firstValidationMessage = null;
	this.validationMessages = new Object();
	//since this is instantiated outside of live surveys, we don't always want to stomp on the enter key
	if (!arg) this.AddEvent(window, "load", this.DisableEnterKey);
}

/// <summary>
/// Returns the form element containing the survey.
/// </summary>
VcSurvey.prototype.SurveyForm = function() {
	var form = document.getElementById("PdcSurvey");
	if (!form) form = document.forms["PdcSurvey"];
	if (!form) form = document.forms[0];
	return form;
};

/// <summary>
/// Gets a value from the query string and returns it or blank if not found.
/// </summary>
// <param name="parameterName">A valid url parameter</param>
VcSurvey.prototype.GetUrlParameter = function(parameterName) {
	// Get the query string minus the ?
	var queryString = location.search.substring(1);

	// Convert plus to space
	queryString = queryString.replace(/\+/g, " ");
	// Split the args by & and the look at each named pair.
	var params = queryString.split('&');
	for (var x = 0; x < params.length; x++) {
		var pair = params[x].split('=');
		if ((pair.length == 2) && (pair[0] == parameterName)) {
			return decodeURIComponent(pair[1]);
		}
	}

	return '';
};

/// <summary>
/// Gets a value from the query string and sets it to the
/// specified fill in the blank, essay or hidden question.
/// </summary>
// <param name="heading">A valid dbHeading</param>
// <param name="parameterName">A valid url parameter</param>
VcSurvey.prototype.SetUrlParameter = function(heading, parameterName) {
	this.SetTextValue(heading, this.GetUrlParameter(parameterName));
};

/// <summary>
/// Auto Advances the survey to the next page,
/// or submits if on the last page.
/// </summary>
VcSurvey.prototype.AutoAdvance = function() {
	if (document.PdcSurvey.next) {
		document.PdcSurvey.next.click();
	} else if (document.PdcSurvey.submit) {
		document.PdcSurvey.submit.click();
	} else {
		document.PdcSurvey.submit();
	}
};

/// <param>
/// Sets html to an element.
/// </param>
/// <param name="id">Element ID</param>
/// <param name="html">HTML to assign</param>
VcSurvey.prototype.SetElementHtml = function(id, html) {
	var element = document.getElementById(id);
	if (element) element.innerHTML = html;
};

/// <summary>
/// Returns the value for a fill in the blank or essay question as a string.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
VcSurvey.prototype.GetTextValue = function(heading) {
	var value = '';
	var inputField = document.getElementById(heading);
	if (inputField) value = inputField.value;
	return value.toString();
};

/// <summary>
/// Sets the value for a fill in the blank, essay or hidden question.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
/// <param name="newValue">Value to assign to field</param>
VcSurvey.prototype.SetTextValue = function(heading, newValue) {
	var inputField = document.getElementById(heading);
	if (inputField) inputField.value = newValue;
};

/// <summary>
/// Returns the value for a fill in the blank as number.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
VcSurvey.prototype.GetNumericValue = function(heading) {
	var textValue = this.GetTextValue(heading);
	var numValue = this.ToEnglishNumber(textValue);
	return Number(numValue);
};

/// <summary>
/// Returns the selected value of a Choose One
/// (Radio Button List or Select List) or 0 for Not Answered.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
VcSurvey.prototype.GetChooseOneValue = function(heading) {
	var elements = document.getElementsByName(heading);
	for (var x = 0; x < elements.length; x++) {
		element = elements[x];
		if (element.tagName == "SELECT") {
			return Number(element.options[element.selectedIndex].value);
		} else if (element.type == "radio" && element.checked) {
			return Number(element.value);
		}
	}
	return 0;
};

/// <summary>
/// Sets the value for a Choose One
/// (Radio Button List or Select List)
/// </summary>
/// <param name="heading">A valid dbHeading</param>
/// <param name="newValue">Value to assign to field</param>
VcSurvey.prototype.SetChooseOneValue = function(heading, newValue) {
	var elements = document.getElementsByName(heading);
	for (var x = 0; x < elements.length; x++) {
		element = elements[x];
		if (element.tagName == "SELECT") {
			var selectedIndex = 0;
			var optionCount = element.options.length - 1;
			for (var i = 1; i < optionCount; i++) {
				if (element.options[i].value == newValue) {
					selectedIndex = i;
					break;
				}
			}
			element.selectedIndex = selectedIndex;
			return;
		} else if (element.type == "radio") {
			element.checked = (element.value == newValue);
			$(element).change();
		}
	}
};

/// <summary>
/// Returns the selected value of a Choose Many choice
/// 0 = unchecked, 1 = checked.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
VcSurvey.prototype.GetChooseManyValue = function(heading) {
	var element = document.getElementById(heading);
	if (element && element.checked) return 1;
	return 0;
};

/// <summary>
/// Sets the value for a Choose Many choice.
/// </summary>
/// <param name="newValue">Value to assign to field 0 = unchecked, 1 = checked</param>
VcSurvey.prototype.SetChooseManyValue = function(heading, newValue) {
	var element = document.getElementById(heading);
	if (element) element.checked = (newValue == 1);
	$(element).change();
};

/// <summary>
/// Given a list of choose many choices, sets them to not checked.
/// </summary>
/// <param>List of dbHeadings e.g. 'Q1_1', 'Q1_2', 'Q1_3'</param>
VcSurvey.prototype.ClearCheckboxes = function() {
	for (var i = 0; i < arguments.length; i++) {
		var element = document.getElementById(arguments[i]);
		if (element) element.checked = false;
	}
};

/// <summary>
/// Indicates if the specified essay question, fill in the blank topic
/// or choose one list/dropdown has been answered. Or if the specified choose one
/// radio or choose many checkbox have been selected.
/// Does not indicate whether its a valid answer.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
VcSurvey.prototype.IsAnswered = function(heading) {
	var inputField = document.getElementById(heading);
	// Test that id matches the heading. IE7 - getElementById will return first item witch matching name
	if (inputField && inputField.id == heading) {
		switch (inputField.tagName) {
			// Fill In
			case "INPUT":
				switch(inputField.type) {
					case "text":
					case "password":
					case "hidden":
						var ghostText = inputField.getAttribute("ghostText");
						if (ghostText && ghostText == inputField.value) return false;
						return (inputField.value != '');
					case "radio":
					case "checkbox":
						return inputField.checked;
				}
				break;
			// Essay
			case "TEXTAREA":
				return (inputField.value != '');
			// Choose One List/Dropdown
			case "SELECT":
				var value = inputField.options[inputField.selectedIndex].value;
				return (value != '0' && value != '');
		}
	} else {
		// Date Dropdown Boxes
		if (document.getElementById(heading + "_DD")) {
			var monthElement = document.getElementById(heading + "_MM");
			var month = Number(monthElement.options[monthElement.selectedIndex].value);
			var day = Number(document.getElementById(heading + "_DD").value);
			var year = Number(document.getElementById(heading + "_YYYY").value);
			if (month != 0 || day != 0 || year != 0) return true;
		// Radio Group
		} else {
			var elements = document.getElementsByName(heading);
			if (elements) {
				for (var x = 0; x < elements.length; x++) {
					if (elements[x].type == "radio" && elements[x].checked) {
						return true;
					}
				}
			}
		}		
	}
	return false;
};

/// <summary>
/// Given a list of field headings, returns the number
/// of them that have been answered.
/// </summary>
/// <param>List of dbHeadings e.g. 'Q1_1', 'Q1_2', 'Q1_3' or Array</param>
VcSurvey.prototype.AnsweredCount = function() {
	var answerCount = 0;
	var args = this.getArguments(arguments);
	for (var x = 0; x < args.length; x++) {
		if (this.IsAnswered(args[x])) answerCount++;
	}
	return answerCount;
};

/// <summary>
/// Given a list of field headings, returns true
/// if any of them have been answered.
/// </summary>
/// <param>List of dbHeadings e.g. 'Q1_1', 'Q1_2', 'Q1_3' or Array</param>
VcSurvey.prototype.AnyAnswered = function() {
	var args = this.getArguments(arguments);
	for (var x = 0; x < args.length; x++) {
		if (this.IsAnswered(args[x])) return true;
	}
	return false;
};

/// <summary>
/// Given a list of field headings, returns true
/// if any of them have not been answered.
/// </summary>
/// <param>List of dbHeadings e.g. 'Q1_1', 'Q1_2', 'Q1_3' or Array</param>
VcSurvey.prototype.AnyNotAnswered = function() {
	var args = this.getArguments(arguments);
	for (var x = 0; x < args.length; x++) {
		if (!this.IsAnswered(args[x])) return true;
	}
	return false;
};

/// <summary>
/// Private - Returns an Array of items given an argument object or array object.
/// </summary>
/// <param name="args">Array Object or Arguments</param>
VcSurvey.prototype.getArguments = function(args) {
	if (args[0].constructor.toString().indexOf("function Array()") != -1) {
		return args[0];
	} else {
		return Array.prototype.slice.call(args);
	}
}

/// <summary>
/// Given a fill in the blank heading, returns true if the length
/// of the respondents answer is less than the specified length.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
/// <param name="length">Minimum Length</param>
VcSurvey.prototype.IsMinLength = function(heading, length) {
	return (this.GetTextValue(heading).length < length);
};

/// <summary>
/// Given a fill in the blank heading, returns true if the length
/// of the respondents answer is greater than the specified length.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
/// <param name="length">Maximum Length</param>
VcSurvey.prototype.IsMaxLength = function(heading, length) {
	return (this.GetTextValue(heading).length > length);
};

/// <summary>
/// Given a fill in the blank heading, returns true if the value
/// of the respondents answer is within than the specified range.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
/// <param name="minValue">Minimum Value</param>
/// <param name="maxValue">Maximum Value</param>
VcSurvey.prototype.IsInRange = function(heading, minValue, maxValue) {
	var numValue = this.GetNumericValue(heading);
	if (minValue != null && numValue < minValue) return false;
	if (maxValue != null && numValue > maxValue) return false;
	return true;
};

/// <summary>
/// Given a list of field headings, returns true
/// if they all have unique values.
/// </summary>
/// <param name="headings">An array object of dbHeadings e.g. new Array('Q1_1', 'Q1_2', 'Q1_3')</param>
VcSurvey.prototype.IsRankedOrder = function(headings) {
	var choiceValues = new Array();
	for (var x = 0; x < headings.length; x++) {
		var value = this.GetChooseOneValue(headings[x]);
		// Exclude Not Answered and Coded Values
		if (value > 0) {
			// If value already selected
			if (choiceValues[value] == 1) {
				return false;
			} else {
				choiceValues[value] = 1;
			}
		}
	}
	return true;
};

/// <summary>
/// Given a list of field headings and a number of topics to rank,
/// returns true if that number of topics have been ranked.
/// </summary>
/// <param name="headings">An array object of dbHeadings e.g. new Array('Q1_1', 'Q1_2', 'Q1_3')</param>
/// <param name="numrank">Number of topics that need to be ranked</param>
VcSurvey.prototype.IsRankedTopX = function(headings, numrank) {
	var count = 0;
	var choiceValues = new Array();
	for (var x = 0; x < headings.length; x++) {
		var value = this.GetChooseOneValue(headings[x]);
		// Exclude Not Answered and Coded Values
		if (value > 0) count++;
	}
	return (count == numrank);
};

/// <summary>
/// Given a list of field headings and a number of topics to rank,
/// returns true if at least the number of topics have been ranked.
/// </summary>
/// <param name="headings">An array object of dbHeadings e.g. new Array('Q1_1', 'Q1_2', 'Q1_3')</param>
/// <param name="numrank">Number of topics that need to be ranked</param>
VcSurvey.prototype.IsRankedAtleastX = function(headings, numrank) {
	var choiceValues = new Array();

	// Set numrank values as zero
	for (var i = 0; i < headings.length; i++) {
		choiceValues[i] = 0;
	}

	for (var x = 0; x < headings.length; x++) {
		var value = this.GetChooseOneValue(headings[x]);
		// Exclude Not Answered and Coded Values
		if (value > 0) choiceValues[value - 1] = value; // Store ranked value
	}

	// Test all numrank values - if all are set then they were ranked. If some value is zero - it wasn't ranked.
	for (var i = 0; i < numrank; i++) {
		if (choiceValues[i] == 0) return false;
	}

	// Test all values after numrank - if a user continues ranking beyond the “at least” limit, the ranks must be in order
	// So if I have to rank AT LEAST 3 and I continue to rank beyond that, I cannot rank 1,2,3,7. I have to go 1,2,3, 4, 5, 6, 7.
	
	// Idea of processing: last was ranked (value == 1), then we check what's next:
	// - if next item is unranked (choiceValues[i] == 0) change checking on unranked (value == 0);
	// - if checking on unranked (value == 0) and next item is ranked (choiceValues[i] > 0) - this is wrong (like 1,2,3,7).
	var value = 1;
	for (var i = numrank; i < headings.length; i++) {
		if (value == 1 && choiceValues[i] == 0) value = 0;
		if (value == 0 && choiceValues[i] > 0) return false;
	}

	return true;
};

/// <summary>
/// Indicates if the specified fill in topic contains a whole number.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
VcSurvey.prototype.IsInteger = function(heading) {
	var inputField = document.getElementById(heading);
	if (inputField) return this.IsTextInteger(inputField.value);
	return false;
};

/// <summary>
/// Indicates if the specified text is a whole number.
/// </summary>
/// <param name="text">Text being tested</param>
VcSurvey.prototype.IsTextInteger = function(text) {
	// If number contains both a group seperator and a decimal seperator
	// We can determine if they entered the number for the wrong region.
	var groupSep = text.indexOf(this.NumberGroupSeparator);
	// If seperator is ascii 160 space, and was not found, also search for ascii 32 space
	if (groupSep == -1 && this.NumberGroupSeparator == "\u00A0") {
		groupSep = text.indexOf("\ ");
	}
	var decimalSep = text.indexOf(this.NumberDecimalSeparator);
	if (groupSep != -1 && decimalSep != -1 && (groupSep > decimalSep)) return false;
	// Test Concurrent Separators
	var reGroup = new RegExp("\\" + this.NumberGroupSeparator + "{2,}");
	var reDecimal = new RegExp("\\" + this.NumberDecimalSeparator + "{2,}");
	if(reGroup.exec(text) != null || reDecimal.exec(text) != null) return false;
	var number = this.ToEnglishNumber(text);
	if (number.match(/^-?\d+$/)) return true;
	return false;
};


/// <summary>
/// Indicates if the specified fill in topic contains a real number.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
VcSurvey.prototype.IsFloat = function(heading) {
	var inputField = document.getElementById(heading);
	if (inputField) return this.IsTextFloat(inputField.value);
	return false;
};

/// <summary>
/// Indicates if the specified text is a real number.
/// </summary>
/// <param name="text">Text being tested</param>
VcSurvey.prototype.IsTextFloat = function(text) {
	// If number contains both a group seperator and a decimal seperator
	// We can determine if they entered the number for the wrong region.
	var groupSep = text.indexOf(this.NumberGroupSeparator);
	// If seperator is ascii 160 space, and was not found, also search for ascii 32 space
	if (groupSep == -1 && this.NumberGroupSeparator == "\u00A0") {
		groupSep = text.indexOf("\ ");
	}
	var decimalSep = text.indexOf(this.NumberDecimalSeparator);
	if (groupSep != -1 && decimalSep != -1 && (groupSep > decimalSep)) return false;
	// Test Concurrent Separators
	var reGroup = new RegExp("\\" + this.NumberGroupSeparator + "{2,}");
	var reDecimal = new RegExp("\\" + this.NumberDecimalSeparator + "{2,}");
	if(reGroup.exec(text) != null || reDecimal.exec(text) != null) return false;
	var number = this.ToEnglishNumber(text);
	if (number.match(/^-?\d*(\.\d+)?$/)) return true;
	return false;
};

/// <summary>
/// Indicates if the specified fill in topic contains a valid e-mail address.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
VcSurvey.prototype.IsEmail = function(heading) {
	var inputField = document.getElementById(heading);
	if (inputField) {
		var email = inputField.value;
		if (email.match(/^[\w_\-\.\']+[\%\+]?[\w_\-\']*\@[0-9a-zA-Z\-]+\.[0-9a-zA-Z\-\.]+$/)) return true;
	}
	return false;
};

/// <summary>
/// Indicates if the specified fill in topic contains a valid date.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
VcSurvey.prototype.IsDate = function(heading) {
	// Get Month/Day/Year Values
	var month, day, strYear;
	var dateElement = document.getElementById(heading);
	// Calendar Picker
	if (dateElement) {
		var dateValue = dateElement.value;
		var dateFormat = this.DateFormat;
		// Croatian, Hungarian, Latvian end with trailing period
		if(dateValue.lastIndexOf('.') == dateValue.length - 1) {
			dateValue = dateValue.substr(0, dateValue.length - 1);
		}
		if(dateFormat.lastIndexOf('.') == dateFormat.length - 1) {
			dateFormat = dateFormat.substr(0, dateFormat.length - 1);
		}
		var reGroup = new RegExp("\\" + this.DateSeparator);
		// Uzbekistan uses different separators
		if (this.Culture == "uz-Latn-UZ") {
			reGroup = new RegExp("\\/| ");
		}
		var dateParts = dateFormat.split(reGroup);
		var valueParts = dateValue.split(reGroup);
		if (valueParts.length < 3) return false;
		for (var i = 0; i < 3; i++) {
			if (dateParts[i] == "mm") month = Number(valueParts[i]);
			if (dateParts[i] == "dd") day = Number(valueParts[i]);
			if (dateParts[i] == "yyyy") strYear = valueParts[i];
		}
	// Multiple Controls
	} else {
		var monthElement = document.getElementById(heading + "_MM");
		month = Number(monthElement.options[monthElement.selectedIndex].value);
		day = Number(document.getElementById(heading + "_DD").value);
		strYear = document.getElementById(heading + "_YYYY").value;
	}
	var year = Number(strYear);
	// Not a number
	if (isNaN(month) || isNaN(day) || isNaN(year)) return false;
	// Month out of range
	if (month < 1 || month > 12) return false;
	// Day out of range
	if (day < 1 || day > 31) return false;
	// 30 Day Months
	if ((month == 4 || month == 6 || month == 9 || month == 11) && day == 31) return false;
	// Leap Year Check
	if (month == 2) {
		var isleap = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
		if (day > 29 || (day == 29 && !isleap)) return false;
	}
	// Years must be a positive 4 digit integer.
	if (year <= 0 || strYear.length != 4 || !this.IsTextInteger(strYear)) return false;
	return true;
};

/// <summary>
/// Private - Given an array of field headings, returns their total as a number.
/// </summary>
/// <param name="heading">Array of dbHeadings</param>
VcSurvey.prototype.calculateTotal = function(headings) {
	var total = 0;
	var decimalPlaces = 0;

	for (var i = 0; i < headings.length; i++) {
		var heading = headings[i];
		var inputField = document.getElementById(heading);
		if (inputField) {
			var number = this.ToEnglishNumber(inputField.value);
			// Add leading 0 if missing
			if (number.indexOf(".") == 0) number = "0" + number;
			// Get decimal precision
			var decimalIndex = number.indexOf(".");
			if (decimalIndex != -1) {
				var decimalPlacesCount = number.length - (decimalIndex + 1);
				if (decimalPlacesCount > decimalPlaces) decimalPlaces = decimalPlacesCount;
			}
			if (number.match(/^-?\d+(\.\d+)?$/)) {
				total += parseFloat(number);
			}
		}
	}

	if (decimalPlaces > 0) total = total.toFixed(decimalPlaces);

	return total;
};

/// <summary>
/// Given a list of field headings, returns their total as a number.
/// </summary>
/// <param>List of dbHeadings e.g. 'Q1_1', 'Q1_2', 'Q1_3'</param>
VcSurvey.prototype.NumericTotal = function() {
	return this.calculateTotal(arguments);
};

/// <summary>
/// Given a list of field headings, returns their total as a string
/// formatted for the surveys culture.
/// </summary>
/// <param>List of dbHeadings e.g. 'Q1_1', 'Q1_2', 'Q1_3'</param>
VcSurvey.prototype.StringTotal = function() {
	var total = this.calculateTotal(arguments);
	return this.ToRegionNumber(total);
};


/// <summary>
/// Displays the running total for a list of topics.
/// </summary>
/// <param>
/// First arguement is dbheading of the question where to display the total.
/// Second arguement is list of fields to add.
/// e.g. 'Q1', 'Q1_1', 'Q1_2', 'Q2_3', 'Q2_4'
/// </param>
/// <param>List of dbHeadings e.g. 'Q1_1', 'Q1_2', 'Q1_3'</param>
VcSurvey.prototype.ShowRunningTotal = function() {
	var heading = arguments.pop() + "TOTAL";
	var element = document.getElementById(heading);
	if (element) element.innerHTML = this.StringTotal(arguments);
};

/// <summary>
/// Converts a number to a string with regional formatting.
/// </summary>
/// <param name="number">Number</param>
VcSurvey.prototype.ToRegionNumber = function(number) {
	var negative = (number < 0);

	// Convert to string
	number = number.toString();

	// Insert group seperators
	var parts = number.split('.');
	var base = Math.abs(parts[0]).toString();
	var groups = [];
	while(base.length > this.NumberGroupSizes) {
		var temp = base.substr(base.length - this.NumberGroupSizes);
		groups.unshift(temp);
		base = base.substr(0, base.length - this.NumberGroupSizes);
	}
	if(base.length > 0) { groups.unshift(base); }
	base = groups.join(this.NumberGroupSeparator);

	// Add decimal places if any with decimal symbol
	if (parts.length > 1) {
		number = base + this.NumberDecimalSeparator + parts[1];
	} else {
		number = base;
	}

	// Add minus sign if negative value
	if (negative) number = "-" + number;

	return number;
};

/// <summary>
/// Converts a region based number to US English Format.
/// </summary>
/// <param name="number">Number string for survey region</param>
VcSurvey.prototype.ToEnglishNumber = function(number) {
	while (number.indexOf(this.NumberGroupSeparator) != -1) {
		number = number.replace(this.NumberGroupSeparator, "");
	}
	// If seperator is ascii 160 space, also strip out ascii 32 space
	if (this.NumberGroupSeparator == "\u00A0") {
		while (number.indexOf("\ ") != -1) {
			number = number.replace("\ ", "");
		}
	}
	number = number.replace(this.NumberDecimalSeparator, ".");
	return number;
};

/// <summary>
/// Apply Odd/Even row style to a Matrix Question.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
VcSurvey.prototype.DisplayOddEvenRows = function(heading) {
	var table = document.getElementById("T" + heading);
	if (table) {	
		var tbody = table.getElementsByTagName("TBODY");
		if (tbody) {
			var viscount = 0;
			var rows = $(tbody[0]).children("TR");
			for(var i = 0; i < rows.length; i++) {
				var row = rows[i];
				if (row.style.display != "none") {
					viscount++;
					row.className = (viscount % 2 == 1) ? "odd-row" : "even-row";
				}
			}
		}
	}
};

/// <summary>
/// Hides columns (choices) in a table question based on a previous choose many's answers.
/// </summary>
/// <param>
/// First arguement is value to test 1 for selected, 0 for not selected
/// Remaining arguements are the dependent value (Usually a placeholder e.g. %Q1_1%) and the column id.
/// e.g. 1, '1|Q2_A_C1', '0|Q2_A_C2', '0|Q2_A_C3', '1|Q2T4', '0|Q2_A_C4'
/// </param>
VcSurvey.prototype.DisplayDynamicColumns = function() {
var value = arguments[0];
	// Define array for collecting visible td & th
	var visibleColumns = new Array();
	// Counter
	var c = 0;
	for (var i = 1; i < arguments.length; i++) {
		var pair = arguments[i].split('|');
		if (pair[0] != value) {
			this.HideTableColumn(pair[1]);
		} else {
			// Store ids of visible columns
			visibleColumns[c++] = pair[1];
		}
	}
	
	//Calculate width for each column, 100% - 20% - is here because we set up width 
	//for every choice column and the left colgroup already has width of 20%  
	var w = (100 - 20) / (visibleColumns.length);	
	// Specify the width of each column
	for (var i = 0; i < visibleColumns.length; i++) {
		$("td#" + visibleColumns[i]).css('width', w.toString() + '%');
		$("th#" + visibleColumns[i]).css('width', w.toString() + '%');
	}

};

/// <summary>
/// Hides a column (of choices) in a table question for the given column id.
/// </summary>
/// <param name="columnId">Id of table column to hide</param>
VcSurvey.prototype.HideTableColumn = function(columnId) {
	var cells = document.getElementsByName(columnId);
	for(j = 0; j < cells.length; j++) {
		cells[j].style.display = "none";
	}
	// Fix column group span for FireFox
	var index = columnId.lastIndexOf('_');
	var value = Number(columnId.substr(index + 2));
	var colId = columnId.substr(0, index) + ((value > 0) ? "_COLNORM" : "_COLCODED");
	var colGroup = document.getElementById(colId);
	if (colGroup) {
		var newSpan = Number(colGroup.span) - 1;
		if (newSpan == 0) {
			colGroup.style.display = "none";
		} else {
			colGroup.span = Number(colGroup.span) - 1;
		}
	}
}

/// <summary>
/// Gets whether the specified table question topic row is visible.
/// </summary>
/// <param name="elementId">Id of table row element</param>
VcSurvey.prototype.IsTopicVisible = function(elementId) {
	var element = document.getElementById(elementId);
	return (element && element.style.display=="");
};

/// <summary>
/// Hides choices in a table question dropdown based on a previous choose many's answers
/// </summary>
/// <param>
/// First arguement is value to test 1 for selected, 0 for not selected
/// Second arguement is the dropdown prefix
/// Third arguement is number of topics
/// Remaining arguements are the dependent values (Usually a placeholder e.g. %Q1_1%).
/// e.g. 1, 'Q3_A', 5, '1', '0', '0', '1', '0'
/// </param>
VcSurvey.prototype.DisplayDynamicList = function() {
	var value = arguments[0];
	var tableSide = arguments[1];
	var topicCount = arguments[2];
	for (var i = 1; i <= topicCount; i++) {
		var dbHeading = tableSide + "_" + i;
		for (var j = 3; j < arguments.length; j++) {
			if (arguments[j] != value) {
				var choice = j - 2;
				this.RemoveListChoice(dbHeading, choice);
			}
		}
	}
};

/// <summary>
/// Removes all choices with the specified value from a dropdown or list box.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
/// <param name="choiceValue">Value of choice to remove</param>
VcSurvey.prototype.RemoveListChoice = function(heading, choiceValue) {
	var choiceList = document.getElementById(heading);
	var optionCount = choiceList.options.length - 1;

	for (var i = optionCount; i > 0; i--) {
		if (choiceList.options[i].value == choiceValue) choiceList.options[i] = null;
	}
};

/// <summary>
/// Randomizes the Choices in a Choose One List Box or Dropdown Question.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
VcSurvey.prototype.RandomizeListChoices = function(heading) {
	var selectedValue = this.GetChooseOneValue(heading);	
	var choiceList = document.getElementById(heading);
	var optionCount = choiceList.options.length - 1;
	var randomizedChoices = new Array();

	for (var i = 1; i <= optionCount; i++) {
		var option = choiceList.options[i];
		var fixed = option.getAttribute("fixed");
		if (!(fixed && fixed == "fixed")) {
			choiceList.options[i] = new Option(i, i);
			randomizedChoices.push(option);
		} 
	}

	randomizedChoices = this.randomizeArray(randomizedChoices);

	for (var i = 1; i <= optionCount; i++) {
		var option = choiceList.options[i];
		var fixed = option.getAttribute("fixed");
		if (!(fixed && fixed == "fixed")) {
			if (randomizedChoices.length == 0) break;
			choiceList.options[i] = randomizedChoices.pop();
		}
	}

	this.SetChooseOneValue(heading, selectedValue);
};

/// <summary>
/// Randomizes the Choices in a Choose One Radio Buttons or Choose Many Check Boxes.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
/// <param name="numChoices">Total number of choices in the question</param>
VcSurvey.prototype.RandomizeListButtons = function(heading, numChoices) {
	var randomizedChoices = new Array();

	for (var i = 1; i <= numChoices; i++) {
		var spanChoice = document.getElementById(heading + "C" + i);
		if (spanChoice) {
			var fixed = spanChoice.getAttribute("fixed");
			if (!(fixed && fixed == "fixed")) {
				// Store clone of item in the array to avoid rewriting ID on next step
				randomizedChoices.push($(spanChoice).clone());
				// Setup span ID to other one to avoid swapping during replacing
				$(spanChoice).attr("id", heading + "C" + i + "-" + i);
			}
		}
	}

	randomizedChoices = this.randomizeArray(randomizedChoices);
	var randIndex = 0;

	for (var i = 1; i <= numChoices; i++) {
		// Find span with changed ID
		var spanChoice = document.getElementById(heading + "C" + i + "-" + i);
		if (spanChoice) {
			var fixed = spanChoice.getAttribute("fixed");
			if (!(fixed && fixed == "fixed")) {
				// Replace span with changed ID to original one from random array. Use randIndex to put items in correct order
				$(spanChoice).replaceWith(randomizedChoices[randIndex]);
				randIndex++;
				if (randIndex >= randomizedChoices.length) break;
			}
		}
	}
};

/// <summary>
/// Randomizes the rows in a Matrix Question.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
VcSurvey.prototype.RandomizeTableRows = function(heading, numChoices) {
	var table = document.getElementById("T" + heading);
	var tbodyElements = table.getElementsByTagName("tbody");
	var tbody = tbodyElements.item(0);
	var trElements = $(tbody).children("tr");
	var randomizedRows = new Array();

	for (var i = 0; i < trElements.length; i++) {
		var tr = trElements.get(i);
		var fixed = tr.getAttribute("fixed");
		if (!(fixed && fixed == "fixed")) {
			randomizedRows.push($(tr).clone());
			// Setup span ID to other one to avoid swapping during replacing
			$(tr).attr("id", $(tr).attr("id") + "-" + i);
		}
	}

	randomizedRows = this.randomizeArray(randomizedRows);
	var randIndex = 0;

	for (var i = 0; i < trElements.length; i++) {
		var tr = trElements.get(i);
		var fixed = tr.getAttribute("fixed");
		if (!(fixed && fixed == "fixed")) {
			// Replace span with changed ID to original one from random array. Use randIndex to put items in correct order
			$(tr).replaceWith(randomizedRows[randIndex]);
			randIndex++;
			if (randIndex >= randomizedRows.length) break;
		}
	}
};

/// <summary>
/// Randomizes the choices in a Drag and Drop Rank Order Question.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
VcSurvey.prototype.RandomizeDragDropItems = function(heading, numChoices) {
	var ddroUl = document.getElementById("DDRO_" + heading);
	var liElements = ddroUl.getElementsByTagName("li");
	var randomizedItems = new Array();

	for (var i = 0; i < liElements.length; i++) {
		var li = liElements.item(i);
		var fixed = li.getAttribute("fixed");
		if (!(fixed && fixed == "fixed")) {
			randomizedItems.push(li);
		}
	}

	randomizedItems = this.randomizeArray(randomizedItems);

	for (var i = 0; i < liElements.length; i++) {
		if (randomizedItems.length == 0) break;
		var li = liElements.item(i);
		var fixed = li.getAttribute("fixed");
		if (!(fixed && fixed == "fixed")) {
			if (li.swapNode) {
				li.swapNode(randomizedItems.pop());
			} else {
				li.innerHTML = randomizedItems.pop().innerHTML;
			}
		}
	}
};

/// <summary>
/// Randomizes the choices in a Scrolling Matrix Question.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
VcSurvey.prototype.RandomizeScrollingMatrixItems = function(heading, numChoices) {
	var imUl = document.getElementById("W" + heading).getElementsByTagName('ul')[0];
	var liElements = imUl.getElementsByTagName("li");
	var randomizedItems = new Array();

	for (var i = 0; i < liElements.length; i++) {
		var li = liElements.item(i);
		var fixed = li.getAttribute("fixed");
		if (!(fixed && fixed == "fixed")) {
			randomizedItems.push(li);
		}
	}

	randomizedItems = this.randomizeArray(randomizedItems);

	for (var i = 0; i < liElements.length; i++) {
		if (randomizedItems.length == 0) break;
		var li = liElements.item(i);
		var fixed = li.getAttribute("fixed");
		if (!(fixed && fixed == "fixed")) {
			if (li.swapNode) {
				li.swapNode(randomizedItems.pop());
			} else {
				li.innerHTML = randomizedItems.pop().innerHTML;
			}
		}
	}
};

/// <summary>
/// Randomizes the choices in a Scale Slider Question.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
VcSurvey.prototype.RandomizeScaleSliders = function(heading) {
	var oContainer = document.getElementById("SL_" + heading);
	var topics = oContainer.children;
	var randomizedItems = new Array();

	for (var i = 0; i < topics.length; i++) {
		var topic = topics.item(i);
		var fixed = topic.getAttribute("fixed");
		if (!(fixed && fixed == "fixed")) {
			randomizedItems.push(topic);
		}
	}

	randomizedItems = this.randomizeArray(randomizedItems);

	for (var i = 0; i < topics.length; i++) {
		if (randomizedItems.length == 0) break;
		var topic = topics.item(i);
		var fixed = topic.getAttribute("fixed");
		if (!(fixed && fixed == "fixed")) {
			if (topic.swapNode) {
				topic.swapNode(randomizedItems.pop());
			} else {
				topic.innerHTML = randomizedItems.pop().innerHTML;
			}
		}
	}
};


/// <summary>
/// Private - Randomizes an array of items.
/// </summary>
/// <param name="heading">Array of items to randomize</param>
VcSurvey.prototype.randomizeArray = function(array) {
	for (var i = 0; i < array.length; i++) {
		var j = Math.floor(Math.random() * array.length);
		var item1 = array[i];
		var item2 = array[j];
		array[i] = item2;
		array[j] = item1;
	}
	return array;
};

/// <summary>
/// Jumps to the specified question on the current page and displays an optional alert message.
/// </summary>
/// <obsolete>
/// Used for pre Vovici v5 client-side validation. Maintained for backwards compatibility.
/// <obsolete>
/// <param name="heading">Anchor Heading to jump to e.g. A1 for Question Q1</param>
/// <param name="message">Alert message to display</param>
VcSurvey.prototype.GotoQuestion = function(heading, message) {
	window.location = "#" + heading;
	if (message) {
		alert(message);
	}
};

/// <summary>
/// Jumps to the first validation error on the page.
/// Returns true if success.
/// </summary>
VcSurvey.prototype.GotoFirstError = function() {
	if (this.firstValidationMessage) {
		var messageElement = document.getElementById(this.firstValidationMessage);
		var selectedPosX = 0;
		var selectedPosY = 0;
		while(messageElement != null){
			selectedPosX += messageElement.offsetLeft;
			selectedPosY += messageElement.offsetTop;
			messageElement = messageElement.offsetParent;
		}
		window.scrollTo(selectedPosX,selectedPosY);
		return true;
	}
	return false;
};

/// <summary>
/// Given a Choose One Dropdown or List Box question
/// Jumps to the anchor specified in the destination attribute for the selected choice.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
VcSurvey.prototype.SelectJump = function(heading) {
	// Get Selected Choice
	var choiceList = document.getElementById(heading);
	var selectedOption = choiceList.options[choiceList.selectedIndex];
	// Jump to destination if set
	var destination = selectedOption.getAttribute("destination");
	if (destination && destination != '') {
		window.location = "#" + destination;
	}
}

/// <summary>
/// Configure's a Rank Order Question displayed as Radio Buttons
/// To only allow each rank to only be selected once.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
/// <param name="topics">Number of topics in question</param>
/// <param name="choices">Number of choices(ranks) in question</param>
VcSurvey.prototype.ConfigureRankOrder = function(heading, topics, choices) {
	this.HideTableColumn(heading + "_C0");
	for (var topic = 1; topic <= topics; topic++) {
		for (var choice = 1; choice <= choices; choice++) {
			var id = heading + "_" + topic + "_" + choice;
			var element = document.getElementById(id);
			if (element) {
				survey.AddEvent(element, "click", function(e) {
					var targ;
					if (!e) var e = window.event;
					if (e.target) targ = e.target;
					else if (e.srcElement) targ = e.srcElement;
					for (var topic = 1; topic <= topics; topic++) {
						for (var choice = 1; choice <= choices; choice++) {
							var id = heading + "_" + topic + "_" + choice;
							var element = document.getElementById(id);
							if (element.value == targ.value && element.id != targ.id) {
								element.checked = false;
							}
						}
					}
				});
			}
		}
	}
}

/// <summary>
/// Update sliders vs text boxes.
/// </summary>
VcSurvey.prototype.UpdateSliders = function() {
	$('input.slidertb').each(function() {
		var fieldName = $(this).attr('id');
		var sliderID = "#" + fieldName + "S";
		var minVal = $(sliderID).slider('option', 'min');
		var val = (!isNaN(parseFloat($(this).val()))) ? $(this).val() : minVal;
		$("#" + fieldName + "S").slider('option', 'value', survey.CheckSliderValue(fieldName,
				$(sliderID).slider('option', 'step'),
				val,
				minVal,
				$(sliderID).slider('option', 'max'))
				);
	});
}

/// <summary>
/// Set appropriate boundary values for slider.
/// </summary>
VcSurvey.prototype.CheckSliderValue = function(fieldName, stepVal, val, minVal, maxVal) {
	val = parseFloat(val);
	if (isNaN(val)) return $("#" + fieldName + "S").slider('option', 'value');
	var smin = $("#" + fieldName + "S").slider('option', 'min') + stepVal;
	var smax = $("#" + fieldName + "S").slider('option', 'max') - stepVal;
	if (val <= minVal) return smin - stepVal;
	if (val >= maxVal) return smax + stepVal;
	var v = val;
	if (val < smin) v = stepVal * ((val - minVal) / (smin - minVal)) + (smin - stepVal);
	else if (val > smax) v = stepVal * ((val - smax) / (maxVal - smax)) + smax;
	return v;
}

/// <summary>
/// Private function for slider support.
/// Update slider value for both:UI text box and hidden value.
/// </summary>
VcSurvey.prototype.UpdateSliderValue = function(fieldName, currentvalue, minVal, maxVal, stepVal) {
	var defaultVal = $("#" + fieldName + "S").slider('option', 'value');
	var v = currentvalue;
	if (isNaN(defaultVal) || isNaN(currentvalue)) return;
	if ($("#" + fieldName).val() != v) $("#" + fieldName).val(v);
	v = survey.CheckSliderValue(fieldName, stepVal, v, minVal, maxVal);
	if (defaultVal != v) {
		$("#" + fieldName + "S").slider('option', 'value', v);
	}
}

/// <summary>
/// Private function for slider support.
/// Provide appropriate round for real numbers.
/// </summary>
VcSurvey.prototype.RoundToGrid = function(val, defaultVal, minVal, maxVal, valueInterval) {
	val = parseFloat(val);
	if (isNaN(val)) {
		if (isNaN(parseFloat(defaultVal))) return minVal;
		return defaultVal;
	}
	val = Math.round(val / valueInterval) * valueInterval;
	val = Math.round(val * 10000) / 10000;
	if (val < minVal) val = minVal;
	if (val > maxVal) val = maxVal;
	return val;
}

/// <summary>
/// Private function for slider support.
/// In case of enable JavaScript show variant with JS.
/// </summary>
VcSurvey.prototype.checkJavascript = function(fieldName) {
	$(".slider-cell").show();
	$(".marksTbl").show();
	$(".slider :text").addClass("slidertb");
	$(".sliderdivJS").addClass("sliderdiv");
	$(".sliderJS").addClass("slider");
}

/// <summary>
/// Adds a slider control for the specified fill in the blank topic to the page.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
/// <param name="minVal">Minimum Range of Slider</param>
/// <param name="maxVal">Maximum Range of Slider</param>
/// <param name="stepVal">Step between values</param>
/// <param name="totalFunction">Function to call after slider changed (e.g. Show Running Total)</param>
VcSurvey.prototype.CreateSlider = function (fieldName, minVal, maxVal, stepVal, size, totalFunction) {
	// If the Javascript is enabled then this call is initialize the necessary elements visible
	survey.checkJavascript(fieldName);
	var sliderID = "#" + fieldName + "S";
	var slidervalueID = "#" + fieldName;
	var slidermaxval = maxVal;
	var sliderminval = minVal;
	if (stepVal > 0) {
		sliderminval = survey.RoundToGrid(minVal + stepVal, minVal + stepVal, minVal, maxVal, stepVal) - stepVal;
		if (sliderminval > minVal) sliderminval -= stepVal;
		slidermaxval = Math.ceil((maxVal - sliderminval) / stepVal) * stepVal + sliderminval;
	}

	// Assign the jQuery Slider to element
	$(sliderID).slider({
		range: "min",
		min: sliderminval,
		max: slidermaxval,
		step: stepVal,
		slide: function (e, ui) {
			var newValue = ui.value;
			if (e.originalEvent && e.originalEvent.type == "keydown") {
				// Round Value to precision of step on left/right arrow
				newValue = survey.RoundToGrid(ui.value, ui.value, minVal, maxVal, stepVal);
			}
			survey.UpdateSliderValue(fieldName, newValue, minVal, maxVal, stepVal);
		}
	});

	// Set value from form (Preselected, Piped or Infused)
	// If not valid, set to blank, Not Answered
	var formValue = this.GetTextValue(fieldName);
	try {
		$(sliderID).slider('option', 'value', parseFloat(formValue));
	} catch (e) { }

	// Set the text box size near the slider
	$(slidervalueID).attr('size', size);

	if (totalFunction) {
		$(sliderID).bind('slidechange', function (event, ui) { totalFunction(); });
	}

	// Set the initial values of the slider
	survey.UpdateSliderValue(fieldName, $(sliderID).slider("value"), minVal, maxVal, stepVal);

	// is text box has incorrect value then clear it
	if (isNaN(parseFloat(formValue))) {
		$(slidervalueID).val('');
		$(sliderID).slider('option', 'value', survey.CheckSliderValue(fieldName, stepVal, minVal, minVal, maxVal));
	}

	// Handle the slider change event
	$(slidervalueID).change(function (e) {
		survey.UpdateSliderValue(fieldName, $(this).val(), minVal, maxVal, stepVal);
		if (totalFunction) totalFunction();
	});

	// Handle the slider keyup event
	$(slidervalueID).keyup(function (e) {
		if (!isNaN(parseFloat($(this).val()))) {
			$(sliderID).slider('option', 'value', survey.CheckSliderValue(fieldName, stepVal, $(this).val(), minVal, maxVal));
		}
	});

	// Handle the reset input to set default value
	$('input[type = "reset"]').unbind('click.resetSliders').bind('click.resetSliders', function () {
		$('input.slidertb').each(function () {
			$(this).val($(this)[0].defaultValue);
		});
		survey.UpdateSliders();
	})
}


/// <summary>
/// Resets client-side validation.
/// </summary>
VcSurvey.prototype.ResetValidation = function(messageId) {
	this.firstValidationMessage = null;
	for (messageId in this.validationMessages) {
		var messageElement = document.getElementById(messageId);
		messageElement.style.display = "none";
	}
};

/// <summary>
/// Sets ghost text for the spcified fill in the blank question.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
/// <param name="text">Text to display when field is empty.</param>
VcSurvey.prototype.SetGhostText = function(heading, text) {
	var element = document.getElementById(heading);
	if (element) {
		element.setAttribute("ghostText", text);
		element.setAttribute("originalStyle", element.className);
		if (element.value == '') {
			element.value = text;
			element.className += " ghost-text";
			this.AddEvent(element, "focus", function(e){
			if (element.className.match("ghost-text")) {
					element.className = element.getAttribute("originalStyle");
					element.value = '';
				}
			});
			this.AddEvent(element, "blur", function(e){
				if (element.value == '') {
					element.className += " ghost-text";
					element.value = element.getAttribute("ghostText");
				}
			});
		}
	}
};

/// <summary>
/// Clear ghost text on all text boxes for submission.
/// </summary>
VcSurvey.prototype.ClearGhostText = function() {
	var form = survey.SurveyForm();
	var inputElements = form.getElementsByTagName("input");
	for (var i = 0; i < inputElements.length; i++) {
		var inputElement = inputElements.item(i);
		if (inputElement.type == "text") {
			var ghostText = inputElement.getAttribute("ghostText");
			if (ghostText && ghostText == inputElement.value) {
				inputElement.value = '';
			}
		}
	}
};

/// <summary>
/// Displays the specified validation message.
/// </summary>
/// <param name="messageId">Id of validation message to display</param>
/// <param name="placeHolder1">Optional value to replace %1 in validation message</param>
/// <param name="placeHolder2">Optional value to replace %2 in validation message</param>
VcSurvey.prototype.ShowValidationMessage = function(messageId, placeHolder1, placeHolder2) {
	var messageElement = document.getElementById(messageId);
	if (messageElement) {
		// We need to store the validation message to preserve placeholders
		if (!this.validationMessages[messageId]) {
			this.validationMessages[messageId] = messageElement.innerHTML;
		}
		// Get message text and replace place holders
		var messageText = this.validationMessages[messageId];
		if (placeHolder1 != undefined) messageText = messageText.replace("%1", placeHolder1);
		if (placeHolder2 != undefined) messageText = messageText.replace("%2", placeHolder2);
		messageElement.innerHTML = messageText;
		// Make Visible
		messageElement.style.display = "";
		if (!this.firstValidationMessage) this.firstValidationMessage = messageId;
	}
};

/// <summary>
/// Shows a Tool Tip for the specified glossary id relative to the calling word.
/// </summary>
/// <param name="heading">The element triggering the tool tip</param>
/// <param name="glossaryId">A valid glossary id</param>
VcSurvey.prototype.ShowToolTip = function(element, glossaryId) {
	var glossaryElement = document.getElementById(glossaryId);
	if (glossaryElement) {
		glossaryElement.style.visibility = "visible";
		// Set Top
		var top = 0;
		var topElement = element;
		while(topElement.offsetParent) {
			top += topElement.offsetTop;
			topElement = topElement.offsetParent;
		}
		top -= glossaryElement.offsetHeight
		if (top < 0) top = element.offsetTop + element.offsetHeight;
		glossaryElement.style.top = top + "px";
		// Set Left
		var width = document.body.offsetWidth;
		var left = 0;
		var leftElement = element;
		while(leftElement.offsetParent) {
			left += leftElement.offsetLeft;
			leftElement = leftElement.offsetParent;
		}
		if ((left + glossaryElement.offsetWidth) > width) {
			left = Math.max(0, width - glossaryElement.offsetWidth);
		}
		glossaryElement.style.left = left + "px";
	}
};

/// <summary>
/// Hides the Tool Tip with the specified glossary id for the calling word.
/// </summary>
/// <param name="heading">The element triggering the tool tip</param>
/// <param name="glossaryId">A valid glossary id</param>
VcSurvey.prototype.HideToolTip = function(element, glossaryId) {
	var glossaryElement = document.getElementById(glossaryId);
	if (glossaryElement) {
		glossaryElement.style.visibility = "hidden";
	}
};

/// <summary>
/// Displays the survey Jump Page.
/// </summary>
VcSurvey.prototype.ShowJumpPage = function () {
	var is_chrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;
	var is_opera = navigator.userAgent.toLowerCase().indexOf('opera') > -1;
	var url = document.PdcSurvey.action + "?s=" + document.PdcSurvey.PdcSessionId.value + "&jump=1";
	if (!is_chrome && !is_opera && window.showModalDialog) {
		// Open up Jump Window 90% of Parent
		var height = parseInt($(window).height() * .90) + "px";
		var width = parseInt($(window).width() * .90) + "px";
		window.showModalDialog(url, document.PdcSurvey, "dialogHeight:" + height + ";dialogWidth:" + width + ";status:no;resizable:yes;center:yes;help:no;minimize:no;maximize:yes;scroll:yes;statusbar:no;");
	} else {
		window.open(url, document.PdcSurvey.PdcSessionId.value + "JUMP", "modal=yes, location=no, menubar=no, resizable=yes, scrollbars=yes, status=no, toolbar=no, dialog=yes");
	}
};

/// <summary>
/// Emails the current result page to the participants e-mail address on file.
/// </summary>
/// <param name="confirmation">Optional confirmation text to display after sending Ajax request.</param>
VcSurvey.prototype.EmailResults = function(confirmText) {
	var currentPage = document.getElementById("PdcCurrentPage");
	if (currentPage) {
		var args = "EMAILRESULTS;" + currentPage.value;
		this.AjaxRequest(args);
		if (confirmText) alert(confirmText);
	}
};

/// <summary>
/// Emails the current result page to the participant prompting for an e-mail address.
/// </summary>
/// <param name="promptText">Text to prompt for e-mail address.</param>
/// <param name="confirmText">Optional confirmation text to display after sending Ajax request.</param>
/// <param name="incorrectEmailText">Optional text to display if entered email address is incorrect.</param>
VcSurvey.prototype.EmailResultsPrompt = function(promptText, confirmText, incorrectEmailText) {
	var currentPage = document.getElementById("PdcCurrentPage");
	if (currentPage) {
		var email = prompt(promptText, '');
		if (email) {
			if (email.match(/^[\w_\-\.\']+[\%\+]?[\w_\-\']*\@[0-9a-zA-Z\-]+\.[0-9a-zA-Z\-\.]+$/)) {
				var args = "EMAILRESULTS;" + currentPage.value + ";" + email;
				this.AjaxRequest(args);
				if (confirmText) alert(confirmText);
			} else if (incorrectEmailText && incorrectEmailText != '') {
				alert(incorrectEmailText);
			}
		}
	}
};

/// <summary>
/// Populates the following list based on the
/// item selected in the specified list.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
/// <param name="index">Index of list who's value has changed</param>
VcSurvey.prototype.GetNextList = function(heading, index) {
	this.ClearSubsequentLists(heading, index);
	var listElement = document.getElementById(heading + "_" + index);
	var selectedItem = listElement.options[listElement.selectedIndex];
	var listId = selectedItem.getAttribute("listid");
	if (listId && listId != 0) {
		var args = "GETLIST;" + heading + ";" + index + ";" + listId;
		this.AjaxRequest(args);
	}
};

/// <summary>
/// Populates the first list based on the listid.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
/// <param name="index">Index of list who's value has changed</param>
VcSurvey.prototype.GetFirstList = function(heading, listId) {
	var args = "GETLIST;" + heading + ";" + 0 + ";" + listId;
	this.AjaxRequest(args);
};

/// <summary>
/// Populates the following list using a web service call.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
/// <param name="index">Index of list who's value has changed</param>
VcSurvey.prototype.GetNextListWS = function(heading, index) {
	// Get selected values of list items up to and including this list
	var listValues;
	for(var i = 1; i <= index; i++) {
		var nextListElement = document.getElementById(heading + "_" + i);
		if (nextListElement && nextListElement.tagName == "SELECT") {
			var selectedIndex = nextListElement.selectedIndex;
			if (selectedIndex >= 0) {
				var selectedValue = nextListElement.options[selectedIndex].value;
				listValues += ";" + heading + "_" + i + "=" + selectedValue;
			}
		}
	}
	this.ClearSubsequentLists(heading, index);
	var args = "GETLISTWS;" + heading + ";" + index + listValues;
	this.AjaxRequest(args);
};

/// <summary>
/// Removes all the choices in the list following the
/// specified index except for the list caption.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
/// <param name="index">Index of list after which choices should be removed</param>
VcSurvey.prototype.ClearSubsequentLists = function(heading, index) {
	var nextListIndex = parseInt(index) + 1;
	var nextListElement = document.getElementById(heading + "_" + nextListIndex);
	while (nextListElement && nextListElement.tagName == "SELECT") {
		var optionCount = nextListElement.options.length;
		for(var i = 0; i < optionCount; i++) {
			nextListElement.options[1] = null;
		}
		nextListElement.disabled = true;
		nextListIndex++;
		nextListElement = document.getElementById(heading + "_" + nextListIndex);
	}
};

/// <summary>
/// Populates the specified list from an XML collection of ListItems.
/// </summary>
/// <param name="heading">A valid dbHeading</param>
/// <param name="index">Index of list after to populate</param>
VcSurvey.prototype.PopulateList = function(heading, index, xml) {
	var listElement = document.getElementById(heading + "_" + index);
	var listItems = xml.documentElement;
	var optionCount = 1;
	for (i = 0; i < listItems.childNodes.length; i++) {
		var listItem = listItems.childNodes[i];
		if (listItem.nodeType == 1) {
			listElement.options[optionCount] = new Option(listItem.firstChild.firstChild.nodeValue, listItem.getAttribute('value'));
			listElement.options[optionCount].setAttribute("listid", listItem.getAttribute('targetlistid'));
			if (listItem.getAttribute("selected") == "true") {
				listElement.options[optionCount].setAttribute("selected", "selected");
				if(listElement.onchange) {
					listElement.onchange();
				}
			}
			optionCount++;
		}
	}
	listElement.disabled = false;
};

/// <summary>
/// Creates an instance of the XML HTTP Request object
/// Used for subsequent Ajax Requests.
/// </summary>
VcSurvey.prototype.GetXmlHTTP = function() {
	if (window.XMLHttpRequest) {
		return new XMLHttpRequest();
	} else if (window.ActiveXObject) {
		return new ActiveXObject("Microsoft.XMLHTTP");
	}
};

/// <summary>
/// Submits an Ajax Request to the Survey Engine.
/// </summary>
/// <param name="parameters">Arguments to submit with Ajax Request</param>
VcSurvey.prototype.AjaxRequest = function(parameters) {
	var xmlhttp = this.GetXmlHTTP();
	if (xmlhttp != null) {
		xmlhttp.onreadystatechange = function() {
			if (xmlhttp.readyState == 4) {
				// Safari may return undefined
				if (xmlhttp.status == 200 || typeof(xmlhttp.status) == 'undefined') {
					var parts = parameters.split(';');
					var xml = null;
					if (window.ActiveXObject) {
						xml = new ActiveXObject("Microsoft.XMLDOM");
						xml.loadXML(xmlhttp.responseText);
					} else {
						xml = xmlhttp.responseXML;
					}
					switch(parts[0]) {
						case "GETLIST":
						case "GETLISTWS":
							survey.PopulateList(parts[1], parseInt(parts[2]) + 1, xml);
							break;
					}
				} else {
					// Do not show error in SWB UI
					if (survey.SurveyForm().action.indexOf(".ashx") != -1) {
						alert("Ajax Request Failed: " + xmlhttp.status);
					}
				}
			}
		}
		// Strip server path
		var url = this.SurveyForm().action;
		if(url.indexOf("/") > 0) {
			var pos = url.indexOf("//");
			pos = url.indexOf("/", pos + 2);
			url = url.substr(pos);
		}
		url = url.replace("se.ashx", "list.ashx");
		xmlhttp.open("GET", url, true);
		// Safari Caching Bug
		xmlhttp.setRequestHeader('If-Modified-Since','Wed, 15 Nov 1995 00:00:00 GMT');
		xmlhttp.setRequestHeader("isajaxrequest", "1");
		xmlhttp.setRequestHeader("ajaxargs", parameters);
		xmlhttp.setRequestHeader("PdcSessionId", this.GetTextValue("PdcSessionId"));
		xmlhttp.send('');
	}
};

/// <summary>
/// Registers an event for an element.
/// </summary>
/// <param name="element">Element on which to fire an event</param>
/// <param name="eventName">Name of event to fire</param>
/// <param name="eventFunction">Function to run on element event</param>
VcSurvey.prototype.AddEvent = function(element, eventName, eventFunction) {
	if (element.addEventListener) {
		element.addEventListener(eventName, eventFunction, false);
	} else if (element.attachEvent) {
		element.attachEvent("on" + eventName, eventFunction);
	} else {
		element["on" + eventName] = eventFunction;
	}
};

/// <summary>
/// Prevents form from submitting by pressing Enter key in a Fill In Question.
/// </summary>
VcSurvey.prototype.DisableEnterKey = function() {
	var form = survey.SurveyForm();
	if (form) {
		var inputElements = form.getElementsByTagName("input");
		for (var i = 0; i < inputElements.length; i++) {
			var inputElement = inputElements.item(i);
			// Attach OnKeyPress event to fill in's
			if (inputElement.type == "text" || inputElement.type == "password") {
				survey.AddEvent(inputElement, "keypress", function(e){
					// If use hits Enter
					if(e.keyCode==13) {
						// Cancel Form Submission that bypasses onsubmit event
						e.returnValue = false;
						e.cancel = true;
						// Required For FireFox
						if(e.preventDefault)e.preventDefault();
						// Submit the form, calling validation
						survey.AutoAdvance();
					}
				});
			}
		}
	}
};

/// <summary>
/// Update Rank numbers on right pane
/// </summary>
VcSurvey.prototype.UpdateRankNumberList = function(rank_area_id) {
	var j = 0;
	var lastLiElement = null;
	var rankTop = null;
	var sourceElement = $("ul.sortable_source[rank_area_id='" + rank_area_id + "']");
	var destinationElement = $("ul.sortable_destination[rank_area_id='" + rank_area_id + "']");

	destinationElement.find("li.choice_item").each(function(i, liElement) {
		lastLiElement = liElement;
		var jq_liElement = $(liElement);
		jq_liElement.find("img").css("width", "40px"); // Hack for IE 6
		jq_liElement.find("div.img").css("width", "40px"); // Hack for IE 6
		jq_liElement.find("div.left_margin").css("width", "8px"); // Hack for IE 6
		
		if (rankTop == null) {
			rankTop = jq_liElement.attr("rankTop");
		}
	});

	if (lastLiElement != null) {
		destinationElement.find("li.drag_here").insertAfter(lastLiElement);
	}

	$("div.response-set[rank_area_id='" + rank_area_id + "'] input[type='radio']").each(function(i, radioButton) {
		$(radioButton).attr("checked", false);
	});

	j = 0;
	$("ul.sortable_destination[rank_area_id='" + rank_area_id + "'] li:visible").each(function (i, liElement) {
		var jq_liElement = $(liElement);

		if (!jq_liElement.hasClass("drag_here")) {
			// Set number of rank in right panel
			j++;
			jq_liElement.find("div.rank_number").html(j.toString() + '.');
		}

		// Check necessary radio buttons
		$("#" + jq_liElement.attr("choice_id") + "_" + j.toString()).attr("checked", "checked");
		jq_liElement.css("border", "none 0px");

		// Fix the height of choice in right panel
		var textCellDiv = jq_liElement.find("p.text_cell");
		var lineHeight = $(textCellDiv).css("line-height");
		var fontSize = $(textCellDiv).css("font-size");
		var twoLineHeight = 2 * parseFloat(lineHeight);
		var maxHeight = 40;

		if (twoLineHeight <= maxHeight) {
			jq_liElement.find("div.choice_text").css("height", twoLineHeight.toString() + "px");
		} else if (twoLineHeight / 2 <= maxHeight) {
			twoLineHeight /= 2;
			jq_liElement.find("div.choice_text").css("height", twoLineHeight.toString() + "px");
		}
	});
	destinationElement.find("li.drag_here div.rank_number").html((j + 1).toString() + '.');

	$("ul.sortable_source[rank_area_id='" + rank_area_id + "'] li.choice_item").each(function (i, liElement) {
		var jq_liElement = $(liElement);
		jq_liElement.find("div.choice_text").css("height", "auto");
		jq_liElement.find("div.rank_number").html('');

		jq_liElement.css("border", "none 0px");
		jq_liElement.css("border-bottom", "solid 1px #eeeeee");

		jq_liElement.find("img").css("width", "90px"); // Hack for IE 6
		jq_liElement.find("div.img").css("width", "90px"); // Hack for IE 6
		jq_liElement.find("div.left_margin").css("width", "8px"); // Hack for IE 6
	});

	if (rankTop != null) {
		rankTop = parseInt(rankTop);
		
		// Top x Topics is selected
		if (rankTop > 0) {
			if (j >= rankTop) {
				var disabledDragging = "ul.sortable_source[rank_area_id='" + rank_area_id + "'], ul.sortable_destination[rank_area_id='-1']";
				sourceElement.sortable("option", "connectWith", disabledDragging);
				destinationElement.find("li.drag_here").hide();
			} else {
				var enabledDragging = "ul.sortable_source[rank_area_id='" + rank_area_id + "'], ul.sortable_destination[rank_area_id='" + rank_area_id + "']";
				sourceElement.sortable("option", "connectWith", enabledDragging);
				destinationElement.find("li.drag_here").show();
			}
		}
	} else {
		var enabledDragging = "ul.sortable_source[rank_area_id='" + rank_area_id + "'], ul.sortable_destination[rank_area_id='" + rank_area_id + "']";
		sourceElement.sortable("option", "connectWith", enabledDragging);
		destinationElement.find("li.drag_here").show();
	}

	// ===================================================
	// Height fixing for left & right panels
	
	// Update heigth of left & right panels
	sourceElement.css("height", "auto");
	destinationElement.css("height", "auto");
	
	var rankLabelHeight = 30;
	var sourceHeight = sourceElement.height();
	var destinationHeight = destinationElement.height();
	
	// Protect when it contained in step by step designer
	if (sourceHeight < 5) {
		return;
	}

	// right panel consists of rank label's height and list of choices height
	destinationHeight = destinationHeight + rankLabelHeight;

	// Update the height of left & right panels
	if (destinationHeight < sourceHeight) {
		sourceElement.height(sourceHeight);
		destinationElement.height(sourceHeight - rankLabelHeight);
	} else {
		sourceElement.height(destinationHeight);
		destinationElement.height(destinationHeight - rankLabelHeight);
	}
}

/// <summary>
/// Copy saved choices to setup Drag&Drop question on start
/// </summary>
VcSurvey.prototype.CopySavedChoicesToDragDrop = function() {
	$("div.response-set[rank_order='1']").each(function (i, wrapDivElement) {
		var rankAreaId = $(wrapDivElement).attr("rank_area_id");
		var j = 0;
		var selectedChoices = new Array();
		var li_choice_items = $("ul.sortable_source[rank_area_id='" + rankAreaId + "'] li.choice_item");
		var topicsCount = li_choice_items.length;

		for (var k = 0; k < topicsCount; k++) {
			li_choice_items.each(function (i, liElement) {
				j++;
				var radioSelector = "#" + $(liElement).attr("choice_id") + "_" + (k + 1).toString();
				var isChecked = $(radioSelector).attr("checked");

				if (isChecked) {
					selectedChoices.push(liElement);
				}
			});
		}

		for (var i = 0; i < selectedChoices.length; i++) {
			$(selectedChoices[i]).appendTo("ul.sortable_destination[rank_area_id='" + rankAreaId + "']");
		}

		survey.UpdateRankNumberList(rankAreaId);
	});
}


/// <summary>
/// Copy saved choices to setup Scale Slider question on start
/// </summary>
VcSurvey.prototype.CopySavedChoicesToScaleSlider = function(rate) {
	var survey = this;
	var shift = (1 << (rate - 1));
	
	$("div.response-set[scale_slider='1']").each(function(i, wrapDivElement) {
		$(wrapDivElement).find("input:radio").filter(":checked").each(function(i, radioInputElement) {
			var value = parseInt($(radioInputElement).val());
			var name = $(radioInputElement).attr("name");
			value = $("div.slider-container[topic_id = '" + name + "'] div.slider-item-label a[sv = '" + value + "']").attr("iv");
			
			var maxVal = parseInt($("div.slider-container[topic_id = '" + name + "']").attr("sc"));
			var sliderElement = $("div.slider-container[topic_id = '" + name + "'] div.textfield div.scale-slider");
			survey.UpdateScaleSliderValue(sliderElement, value);

			var sliderposition = ($(sliderElement).width() * value) / maxVal;
			value = (value << rate) + shift;
			$(sliderElement).slider("value", value);
			$(sliderElement).find("div.ui-slider-range").css("width", sliderposition + 'px');
			$(sliderElement).find("a.ui-slider-handle").css("left", sliderposition + 'px');
		});
	});
}


/// <summary>
/// Updates the Slider (Scale) appearance
/// </summary>
VcSurvey.prototype.UpdateScaleSliderValue = function(sliderContainer, value) {
	$(sliderContainer).find("div.ui-slider-range").css("height", "19px"); // Hack for IE 6.0
	$(sliderContainer).find("div.slider-item-label a").removeClass("current"); // Set the labels default style

	var currentLabel = $($(sliderContainer).find("div.slider-item-label a")[value]); // Get label for current slider value
	var sliderValue = parseInt(currentLabel.attr("iv"));
	var radioButtonElementId = null;
	var row = null;
	
	currentLabel.addClass("current"); // Set the current label with black bold style
	
	// If current label is N/A
	if (sliderValue <= 0) {
		radioButtonElementId = $(sliderContainer).attr("choice_id") + "_1";
		
		// Uncheck the all radio buttons that concern for current slider
		row = $("#" + radioButtonElementId).parents("tr.odd-row, tr.even-row");
		row.find("input[type='radio']").attr("checked", false);
	} else { // Other labels
		radioButtonElementId = $(sliderContainer).attr("choice_id") + "_" + currentLabel.attr("iv");

		// Uncheck the all radio buttons that concern for current slider
		row = $("#" + radioButtonElementId).parents("tr.odd-row, tr.even-row");
		row.find("input[type='radio']").attr("checked", false);
		// Check the radio button that concerns to current slider current label
		$("#" + radioButtonElementId).attr("checked", true);
	}
}


/// <summary>
/// Creates the Slider (Scale) question
/// </summary>
VcSurvey.prototype.CreateScaleSlider = function(rate, clickableLabels) {
	var shift = (1 << (rate - 1));
	var mask = (~0) << rate;
	var survey = this;
	
	// Each slider is wrapped by div.slider-container
	$("div.slider-container").each(function(i, element) {
		var maxVal = parseInt($(element).attr("sc"));
		var selectedValue = parseInt($(element).attr("sv"));
		var sliderElement = $($(element).find("div.scale-slider")[0]);

		// Assign the slider
		$(sliderElement).slider({
			animate: true,
			range: "min",
			min: shift,
			max: (maxVal << rate) + shift,
			step: 1,
			slide: function(event, ui) {
				if (ui.value >> rate != $(sliderElement).slider("value") >> rate) {
					survey.UpdateScaleSliderValue(element, ui.value >> rate);
				}
			},
			change: function(event, ui) {
				survey.UpdateScaleSliderValue(element, ui.value >> rate);
				var value = ui.value & mask;
				var sliderposition = ($(sliderElement).width() * (value >> rate)) / maxVal;
				value += shift;
				
				var width = $(sliderElement).find("div.ui-slider-range").width();
				if (Math.abs(width - sliderposition) < 5) {
					return;
				}

				$(sliderElement).find("div.ui-slider-range").animate({ width: sliderposition + 'px' }, 100);
				$(sliderElement).find("a.ui-slider-handle").animate({ left: sliderposition + 'px' }, 100, function() { $(ui).slider("value", value); });
			}
		});
		
		// Update the keydown behavior of slider
		$(sliderElement).find("a.ui-slider-handle").unbind("keydown").keydown(function(event) {
			var value = sliderElement.slider("value");
			var offset = 0;
			var isLeft = true;

			switch (event.keyCode)
			{
				case 37: // arrow left
					break;
				case 39: // arrow right
					isLeft = false;
					break;
				default:
					return;
			}
			
			value = value >> rate;

			if (isLeft) {
				value--;
			} else {
				value++;
			}

			if ((value >= 0) && (value <= maxVal)) {
				sliderElement.slider("value", shift + (value << rate));
			}
		});
		
		// Handle the hovering of the Scale Slider labels
		$(element).find("div.slider-item-label a").hover(function(event) {
			$(event.currentTarget).addClass("hovered");
		},
		function(event) {
			$(event.currentTarget).removeClass("hovered");
		});

		// Calculate the the location and sizes of labels and margin of slider
		var itemWidth = 100; // Width of slider item
		var maxSliderWidth = -1; //10 * itemWidth; // Maximum width of slider, if sum of all sliders items is greather then this value, then items width will proportionally truncated
		
		var sliderWidth = itemWidth * maxVal; // Calculate a slider's width
		var markWidth = 0; // Width of slider mark div element
		var labelWidth = 0; // Width of slider mark's label's div element
		var sliderMarginLeft = 0; // Slider left margin
		var sliderCompleteWidth = 0; // Width of slider with labels
		var completeWidth = 0; // Width of: topic text + topic image + width of slider with labels
		
		if (maxSliderWidth > 0 && sliderWidth > maxSliderWidth) {
			sliderWidth = maxSliderWidth;
		}
		
		markWidth = Math.round(sliderWidth / maxVal) - 1;
		sliderCompleteWidth = markWidth + sliderWidth;
		labelWidth = Math.round(sliderCompleteWidth / (maxVal + 1));
		sliderMarginLeft = parseInt(labelWidth / 2) + 1;
		completeWidth = 20 + 80 + 20 + sliderCompleteWidth;
		
		$(element).parent().css("width", completeWidth.toString() + "px");
		$(element).css("width", completeWidth.toString() + "px");
		$(element).find("div.textfield").css("margin-left", ((labelWidth / 2) - sliderMarginLeft).toString() + "px")
		$(sliderElement).css("margin-left", sliderMarginLeft.toString() + "px");
		$(sliderElement).css("margin-right", parseInt(labelWidth / 2).toString() + "px");
		$(sliderElement).css("width", sliderWidth.toString() + "px");
		$(element).find("div.marks div").css("width", markWidth.toString() + "px");
		$(element).find("div.slider-item-label").css("width", labelWidth.toString() + "px");

		// If we want to make the labels clickable
		// Assign the click event for handle it
		if (clickableLabels) {
			$(element).find("div.slider-item-label a").click(function(event) {
				var value = parseInt($(event.currentTarget).attr("sv"));
				var sliderElement = $(event.currentTarget).parents("div.textfield").find("div.scale-slider");
				$(event.currentTarget).parents("div.sliderlabels").find("div.slider-item-label a").removeClass("current");
				$(event.currentTarget).addClass("current");
				survey.UpdateScaleSliderValue($(event.currentTarget).parents("div.slider-container"), value);

				var sliderposition = ($(sliderElement).width() * value) / maxVal;
				//var sliderposition = 100.0 * value / maxVal;
				value += shift;
				$(sliderElement).find("div.ui-slider-range").animate({ width: sliderposition + 'px' }, 100, null);
				$(sliderElement).find("a.ui-slider-handle").animate({ left: sliderposition + 'px' }, 100, function() { $(this).slider("value", value); });
			});
		}
	});
	
	// Copy saved choices from matrix to Scale Sliders
	survey.CopySavedChoicesToScaleSlider(rate);
}


/// <summary>
/// Update Scrolling Matrix appearance
/// </summary>
VcSurvey.prototype.UpdateScrollingMatrixAppearance = function(id) {
	var maxHeight = 0;
	var lineHeight = 0;
	$(id).each(function(i, wrapperElement) {
		maxHeight = 0;
		$(wrapperElement).find(".buttons div.choice").each(function(i, buttonElement) {
			maxHeight = Math.max(maxHeight, $(buttonElement).height());
		});
		$(wrapperElement).find(".buttons div.choice").height(maxHeight);
		lineHeight = $(wrapperElement).find(".buttons div.choice div.btnText").css("line-height");
		if (lineHeight == "normal") lineHeight = $(wrapperElement).find(".buttons div.choice div.btnText").css("font-size");
		lineHeight = parseInt(lineHeight.replace("px", ""));
		
		// Hack for Firefox and Opera
		if ($.browser.mozilla || $.browser.opera) {
			lineHeight += 1;
		}
		
		// Hack for IE 7.0 and 8.0
		if ($.browser.msie && ($.browser.version.substr(0,1) == 7 || $.browser.version.substr(0,1) == 8)) {
			lineHeight += 2;
		}
		
		// Hack for IE 6.0
		if ($.browser.msie && $.browser.version.substr(0,1) == 6) {
			lineHeight += 3;
		}
		
		$(wrapperElement).find(".buttons div.choice div.btnText :radio").css("margin-top", ((lineHeight - 13) / 2).toString() + "px");
		
		var top = lineHeight * 2.7;
		
		$(wrapperElement).find("div.selection ul li:visible").each(function (i, liElement) {
			var captionHeight = $(liElement).find("div.caption").height();
			
			if (top > captionHeight) {
				top = captionHeight + 6;
			}

			if ($(liElement).find("img").length != 0) {
				$(liElement).find("div.caption").css("top", "-85px");
				$(liElement).find("img").css("top", top.toString() + "px");
			}
		});
	});
}


/// <summary>
/// Main function, OnLoadPage
/// </summary>
$(document).ready(function () {

	// Check all Choose One/Many with Images and update choices appearance if any
	survey.UpdateChoicesAppearance();

	/////////////////////////////////
	// Drag & Drop Rank Order implementation
	/////////////////////////////////

	// Copy saved choices from native matrix
	survey.CopySavedChoicesToDragDrop();
	var li_choice_item = $("li.choice_item");
	li_choice_item.addClass("pointer");

	var ul_sortable_source = $("ul.sortable_source");
	var ul_sortable_destination = $("ul.sortable_destination");
	// Assign to each ul.sortable_source jQuery Sortable for make it to support drag & drop operations
	ul_sortable_source.each(function (i, ulElement) {
		// Each sortable area marked theirs ID for optimization of update opetations
		var rankOrderId = $(ulElement).attr("rank_area_id");

		// Assign the jQuery Sortable
		$(ulElement).sortable({
			connectWith: "ul.sortable_source[rank_area_id='" + rankOrderId + "'], ul.sortable_destination[rank_area_id='" + rankOrderId + "']",
			tolerance: 'intersect',
			dropOnEmpty: true,
			opacity: 0.6,
			placeholder: "choice_destination",
			items: "li.choice_item[rank_area_id='" + rankOrderId + "']",
			start: function (event, ui) {
				ui.helper.css("border", "solid 1px #cccccc");
			},
			update: function (event, ui) {
				var ul_sortable_source = $("ul.sortable_source[rank_area_id='" + rankOrderId + "'] li.selected_rank_choice");
				var ul_sortable_destination = $("ul.sortable_destination[rank_area_id='" + rankOrderId + "'] li.selected_rank_choice");
				ul_sortable_source.find("div.arrow_button").hide();
				ul_sortable_destination.find("div.arrow_button").hide();
				ul_sortable_source.removeClass("selected_rank_choice");
				ul_sortable_destination.removeClass("selected_rank_choice");
				survey.UpdateRankNumberList($(ulElement).attr("rank_area_id"));
				if ($.browser.msie) {
					// fix issue IE8 in "Document Mode: IE8 Standards" (for IE7 & 6 all worked before and works now too):
					//		Drag&Drop RO has bolded item numbers + some black border around images and selected item in general.
					// Solution: clean up filter style to avoid incorrect transparency
					$(ui)[0].item.css('filter', '');
				}
			}
		});
	});

	// Assign to each ul.sortable_destination jQuery Sortable for make it to support drag & drop operations
	ul_sortable_destination.each(function (i, ulElement) {
		// Each sortable area marked theirs ID for optimization of update opetations
		var rankOrderId = $(ulElement).attr("rank_area_id");

		// Assign the jQuery Sortable
		$(ulElement).sortable({
			connectWith: "ul.sortable_source[rank_area_id='" + rankOrderId + "'], ul.sortable_destination[rank_area_id='" + rankOrderId + "']",
			tolerance: 'intersect',
			dropOnEmpty: true,
			opacity: 0.6,
			placeholder: "choice_destination",
			items: "li.choice_item[rank_area_id='" + rankOrderId + "']",
			update: function (event, ui) {
			    var ul_sortable_source = $("ul.sortable_source[rank_area_id='" + rankOrderId + "'] li.selected_rank_choice");
				var ul_sortable_destination = $("ul.sortable_destination[rank_area_id='" + rankOrderId + "'] li.selected_rank_choice");
			    ul_sortable_source.find("div.arrow_button").hide();
			    ul_sortable_destination.find("div.arrow_button").hide();
				ul_sortable_source.removeClass("selected_rank_choice");
				ul_sortable_destination.removeClass("selected_rank_choice");
				survey.UpdateRankNumberList(rankOrderId);
			}
		});
	});

	// Disable the selection inside the draggable items when it dragging
	ul_sortable_source.disableSelection();
	ul_sortable_destination.disableSelection();

	// Handle the click on the choice
	// Make the choice that clicked is selected
	/* Disable click handler, because hover is enabled
	$(".choice_item").click(function(event) {
	$("ul.sortable_source li").each(function(i, liElement) {
	$(liElement).removeClass("selected_rank_choice");
	$(liElement).find("div.arrow_button").hide();
	});

	$("ul.sortable_destination li").each(function(i, liElement) {
	$(liElement).removeClass("selected_rank_choice");
	$(liElement).find("div.arrow_button").hide();
	});

	if ($(event.currentTarget).parents("ul.sortable_destination")[0] != undefined) {
	$(event.currentTarget).addClass("selected_rank_choice");
	$(event.currentTarget).find("div.arrow_button").show();
	}

	survey.UpdateRankNumberList($(event.currentTarget).parents("ul.sortable_destination").attr("rank_area_id"));
	});
	*/

	// Handle the hovering on the choice
	// Make the hovered choice selected
	li_choice_item.hover(function () {
		var rankOrderId = $(this).parents(".sortable_destination").attr("rank_area_id");

		if (rankOrderId == undefined) {
			rankOrderId = $(this).parents(".sortable_source").attr("rank_area_id");
		}

		$("ul.sortable_source[rank_area_id='" + rankOrderId + "'] div.arrow_button").hide();
		$("ul.sortable_source[rank_area_id='" + rankOrderId + "'] li.selected_rank_choice").removeClass("selected_rank_choice");
		$("ul.sortable_destination[rank_area_id='" + rankOrderId + "'] div.arrow_button").hide();
		$("ul.sortable_destination[rank_area_id='" + rankOrderId + "'] li.selected_rank_choice").removeClass("selected_rank_choice");

		$(this).find("div.arrow_button").show();
		$(this).addClass("selected_rank_choice");

		survey.UpdateRankNumberList(rankOrderId);
	},
	function () {
		var rankOrderId = $(this).parents(".sortable_destination").attr("rank_area_id");

		if (rankOrderId == undefined) {
			rankOrderId = $(this).parents(".sortable_source").attr("rank_area_id");
		}

		$("ul.sortable_source[rank_area_id='" + rankOrderId + "'] li.selected_rank_choice").find("div.arrow_button").hide();
		$("ul.sortable_destination[rank_area_id='" + rankOrderId + "'] li.selected_rank_choice").find("div.arrow_button").hide();
		$("ul.sortable_source[rank_area_id='" + rankOrderId + "'] li.selected_rank_choice").removeClass("selected_rank_choice");
		$("ul.sortable_destination[rank_area_id='" + rankOrderId + "'] li.selected_rank_choice").removeClass("selected_rank_choice");

		survey.UpdateRankNumberList(rankOrderId);
	});

	// Handle the click on remove icon
	$("div.remove").click(function (event) {
		var rankOrderId = $(event.currentTarget).parents("ul.sortable_destination").attr("rank_area_id");
		var liElement = $(event.currentTarget).parents("li");
		liElement.removeClass("selected_rank_choice");
		$("ul.sortable_source[rank_area_id='" + rankOrderId + "']").append($(liElement));
		survey.UpdateRankNumberList(rankOrderId);
		//$(liElement).click(); // Hack for IE 6
	});

	// Handle the click on up/down arrow inside the choice
	$("div.arrow_button").click(function (event) {
		var rankOrderId = $(event.currentTarget).parents("ul.sortable_destination").attr("rank_area_id");
		var selectedLiElement = $("ul.sortable_destination[rank_area_id='" + rankOrderId + "'] li.selected_rank_choice");
		var neighbourElement = null;

		if ($(event.currentTarget).hasClass("rank_up_item")) {
			neighbourElement = selectedLiElement.prev("li");
			$(neighbourElement).before(selectedLiElement);
		}
		else if ($(event.currentTarget).hasClass("rank_down_item")) {
			neighbourElement = selectedLiElement.next("li");

			if (!$(neighbourElement).hasClass("drag_here")) {
				$(neighbourElement).after(selectedLiElement);
			}
		}

		if ((neighbourElement != null) && (!neighbourElement.hasClass("drag_here")) && (neighbourElement.length > 0)) {
			$(selectedLiElement).find("div.arrow_button").hide();
			$(selectedLiElement).removeClass("selected_rank_choice");
			$(neighbourElement).find("div.arrow_button").show();
			$(neighbourElement).addClass("selected_rank_choice");
			//$(neighbourElement).hover();
		}

		survey.UpdateRankNumberList(rankOrderId);
		//$(event.currentTarget).parents("li").click(); // Hack for IE6, 7, 8
	});

	//////////////////////////////
	//Scrolling matrix support//
	//////////////////////////////

	/// <summary>
	/// Defining global scrolling matrix selector
	/// </summary>
	sMatrixContainerClass = '.sm_wraper';
	var sMatrixCountLabel = null;



	/// <summary>
	/// Check whenever jQuery animation is running 
	/// </summary>
	/// <param name="sender">Matrix container inside of which performe actions</param>
	sMatrixAnimation = function (sender) {
		if (sender.queue("fx") != null) return sender.queue("fx").length != 0;

		return false;
	}
	/// <summary>
	/// Get next image from  Scrolling matrix images queue.
	/// </summary>
	/// <param name="sender">Matrix container inside of which performe actions</param>
	sMatrixFindNext = function (oEl) {
		var nextEl = oEl.nextAll(':not(.added):not(.excluded):first');
		if (nextEl.length == 0) {
			nextEl = oEl.prevAll(':not(.added):not(.excluded):first');
			if (nextEl.length == 0) {
				nextEl = null;
			}
		}
		return nextEl;
	}
	/// <summary>
	/// Show "bubble" hint over image
	/// </summary>
	sMatrixShowBubble = function (event) {
		var img = $(this);
		$('.bubble').hide();
		var bubble = $('<div>').addClass('bubble').hide()
				.append($('<span>').addClass('arrow'))
				.append($('<div>').addClass('content').append($(this).parents(sMatrixContainerClass).find('.bubbleText').val()));
		$(this).parents(sMatrixContainerClass).append(bubble);
		bubble.css({ top: /*img.position().top*/event.pageY + 25, left: /*img.position().left*/event.pageX - (bubble.outerWidth() / 2) })
		bubble.fadeIn();
	};
	/// <summary>
	/// Hide all hints
	/// </summary>
	sMatrixHideBubble = function () {
		var img = $(this);
		var bubble = $('.bubble');
		bubble.fadeOut('normal', function () { bubble.remove() });
	};
	/// <summary>
	/// Update "X of Y" label according to currently selected element.
	/// </summary>
	/// <param name="container">Matrix container inside of which performe actions</param>
	sMatrixUpdateCounter = function (container) {
		$(container).each(function (idx, el) {
			if (!sMatrixCountLabel) sMatrixCountLabel = $(el).find('.count').text();
			var current = $(el).find('.selection li:not(.excluded)').index($(el).find('.selection li.selected')) + 1;
			var total = $(el).find('.selection li:not(.excluded)').length;
			if (current == 0) current = total;

			$(el).find('.count').text(
				sMatrixCountLabel
					.replace('%1', current)
					.replace('%2', $(el).find('.selection li:not(.excluded)').length)
				)
		});
	}
	/// <summary>
	/// Togling Topic buttons disabled/enebled
	/// </summary>
	/// <param name="sender">Matrix container inside of which performe actions</param>
	/// <param name="disable">Whenever to disable or eneble buttons</param>
	sMatrixToggleButtons = function (sender, disable) {
		var sender_parents_sMatrixContainerClass = $(sender).parents(sMatrixContainerClass);
		var div_skipbtn = sender_parents_sMatrixContainerClass.find('div.skipbtn')
		if (disable) {
			sender_parents_sMatrixContainerClass.find('.buttons').addClass('disabled');
			sender_parents_sMatrixContainerClass.find('.buttons :radio').attr('disabled', 'disabled')
			div_skipbtn.addClass('disabled');
			// Fix for ie 6
			if ($.browser.msie) {
				div_skipbtn.css('color', 'Gray');
			}
			div_skipbtn.css('cursor', 'default');
		} else {
			sender_parents_sMatrixContainerClass.find('.buttons').removeClass('disabled');
			sender_parents_sMatrixContainerClass.find('.buttons :radio').removeAttr('disabled');
			div_skipbtn.removeClass('disabled');
			// Fix for ie 6
			if ($.browser.msie) {
				div_skipbtn.css('color', 'Transparent');
			}
			div_skipbtn.css('cursor', 'pointer');
		}
	}
	/// <summary>
	/// Check whenever Topic buttons are disabled
	/// </summary>
	/// <param name="sender">Matrix container inside of which performe actions</param>	
	sMatrixAreButtonsDisabled = function (sender) {
		return $(sender).parents(sMatrixContainerClass).find('.buttons').hasClass('disabled');
	}

	sMatrixToggleRated = function (sender) {
		$(sender).find('.rated div:not(.heading)').each(function (idx, el) {
			if ($(el).find('ul:empty').length != 0) {
				$(el).addClass('empty');
			} else {
				$(el).removeClass('empty');
			}
		});

		$(sender).find('.rated div.odd').removeClass('odd');
		$(sender).find('.rated div[result="1"]:not(.heading):not(.empty):even').addClass('odd');

		if ($(sender).find('.rated div:not(.heading) ul:not(:empty)').length == 0) {
			$(sender).find('.edge').slideUp();
		} else {
			$(sender).find('.edge').slideDown();
		}

	}

	/// <summary>
	/// Global IntecativeMatrix initialization:
	///	-Shows/hides elements depends on Javascript state.
	///	-Initialy enables/disables arrows.
	///	-Set "X of Y" label to "1 of <Count>"
	///	-Creates Choises labels inside results window.
	/// </summary>
	sMatrixInit = function (id) {
		var el = $("#W" + id);
		var questionId = $(el).attr('table_id');
		$('#T' + questionId).hide();
		$('#W' + questionId).find('.selection li:not(.added):not(.excluded):first').addClass('selected');
		$('#W' + questionId).find('.selection li td').each(function (idx, el) {
			if ($(this).find('img').length == 0) $(this).find('span.caption').addClass('no_image');
		});
		var maxHeight = 0;
		$('#W' + questionId).show();

		$('#T' + questionId).find('tr:visible :radio:checked').each(function (idx, el) {

			var q = $(el).attr('id').split('_');
			if ($('#' + q[0] + '_T' + q[2]).find('img').length > 0)
				el = $('#' + q[0] + '_T' + q[2]).find('img').clone().css('width', '45px');
			else
				el = $('<a href="#"></a>').append($('#' + q[0] + '_T' + q[2]).find('.caption').clone());

			$('#' + q[0] + '_T' + q[2]).removeClass('selected').addClass('added');
			var item = sMatrixFindNext($('#' + q[0] + '_T' + q[2]))
			if (item != null) {
				$(item).addClass('selected');
			}
			$('#' + q[0] + '_b' + q[3]).append($('<li>').mouseover(sMatrixShowBubble).mouseout(sMatrixHideBubble).append(el));
		})

		sMatrixUpdateCounter($(el));
		$(el).find('div[btn]:not(.skipbtn)').each(function (idx, item) {
			$(sMatrixContainerClass + ' #' + $(item).attr('btn')).before($(item).text());
		});

		sMatrixToggleRated($('#W' + questionId));
		survey.UpdateScrollingMatrixAppearance(el);

		if ($("div.selection ul li:visible", el).length == 0) {
			$(sMatrixContainerClass + " .buttons").addClass("disabled");
			$(sMatrixContainerClass + " .buttons :radio").attr('disabled', 'disabled')
		}


		//Handle selection buttons intermediate ("clicking") state
		$(" .buttons div.choice", el).mousedown(function () {
			if ($(this).parents('.buttons').hasClass('disabled')) return false;
			$(this).addClass('clicking');
		});

		$(" .buttons div.choice", el).mouseup(function () {
			if ($(this).parents('.buttons').hasClass('disabled')) return false;
			$(this).removeClass('clicking');
		});

		//Process element selection
		$(" .buttons div.choice, div.skipbtn", el).click(function () {

			var button = $(this);
			if (button.parents('.buttons').hasClass('disabled') || button.hasClass('none')) return false;

			var sm_wraper = $(this).parents(sMatrixContainerClass);
			var oEl = $(this).parents(sMatrixContainerClass).find(".selection .selected");
			var img = oEl.find('img');
			var caption = oEl.find('.caption');
			//If animation (selection) in progress, skip
			if (sMatrixAnimation(oEl)) return false;

			//get legacy (hidden QMatrix) matrix choise id components
			var topicId = oEl.attr('topicidx');
			var choiseId = button.attr('choiseidx');
			var questionId = sm_wraper.attr('table_id');
			//Set up legacy (hidden QMatrix) matrix choise.
			$('#' + questionId + '_A_' + topicId + '_' + choiseId).attr("checked", "checked");

			button.find('input:radio').attr('checked', 'checked');

			//set image to gefault absolute position before animation
			oEl.css({ position: 'relative' });
			oEl.css({ top: 0 });
			var nextEl = sMatrixFindNext(oEl);

			//begin main animation (Currently visible image slides to the left and fades out.)
			oEl.animate({ top: 200 }, 'slow', 'swing', /* animation finished callback*/function () {
				//creating duplicate image, to use in results window
				if ($(this).find('img').length > 0)
					el = $(this).find('img').clone().css('width', '45px');
				else
					el = $('<a href="#"></a>').append($(this).find('.caption').clone());

				oEl.addClass('added');
				$(this).attr('style', '');
				$(this).removeAttr('style');
				button.parents(sMatrixContainerClass).find('#' + button.attr('btn')).append($('<li>').mouseover(sMatrixShowBubble).mouseout(sMatrixHideBubble).append(el));

				//show next available image, or disable buttons in none 
				if (nextEl) {
					nextEl.addClass('selected');
				} else {
					sMatrixToggleButtons(this, true);
				}
				button.find('input:radio').attr('checked', '');
				oEl.removeClass('selected');
				sMatrixToggleRated(sm_wraper);
				sMatrixUpdateCounter(sm_wraper);
				return true;
			});

			if (nextEl) {
				nextEl.css('display', 'block');
				nextEl.css({ 'position': 'relative' });
				nextEl.css({ 'top': -400 });
				survey.UpdateScrollingMatrixAppearance("#" + $(nextEl).parents("div.sm_wraper").attr("id"));
				//begin seccondary animation (Next image fade in on the right and slides to the center.)

				nextEl.animate({ top: -200 }, 'slow', 'swing', function () {
					nextEl.css('top', '0px');
					sMatrixUpdateCounter(sm_wraper);
				});
			}

			return true;
		});

		//Changing answer (image in results window clicked)
		$(' .rated li', el).live('click', function () {
			var sm_wraper = $(this).parents(sMatrixContainerClass);
			var container = $(this).parents(sMatrixContainerClass).find('.selection');
			var oEl = $(this).parents(sMatrixContainerClass).find(".selection .selected");
			var newEl = $(this).parents(sMatrixContainerClass).find('#' + $(this).find('[im]').attr('im'));
			$('.bubble').remove();
			oEl.removeClass('selected');
			newEl.removeClass('added');

			$(this).parents(sMatrixContainerClass).find('.selection li:not(.added):not(.excluded):first').addClass('selected')

			var topicId = $(this).find('[topicidx]').attr('topicidx');
			var questionId = sm_wraper.attr('table_id');
			//Unckeck legacy (hidden QMatrix) matrix choise.
			$("[id^='" + questionId + '_A_' + topicId + '_' + "']:checked").removeAttr('checked');

			//hide results window.
			$(this).parents(sMatrixContainerClass).find('.ratedBtn.close').click();
			$(this).remove();

			sMatrixToggleRated(sm_wraper);
			if (sMatrixAreButtonsDisabled(container))
				sMatrixToggleButtons(container, false);

			sMatrixUpdateCounter(sm_wraper);
			return false;
		});

		// Show/Close results window
		$(' .ratedBtn', el).click(function (sender) {
			var btn = $(this);
			sMatrixHideBubble();
			// Update 'bottom' property of '.results' to support correct answer box position when Scrolling Matrix is taller (e.g. when Skip Choice button has a lot of text).
			// 20 - base value of 'div.skipbtn' height, 75 - base value of '.results' height.
			$(this).parents(sMatrixContainerClass).find('.results').css('bottom', $(this).parents(sMatrixContainerClass).find('div.skipbtn').height() - 20 + 75 + "px");
			$(this).parents(sMatrixContainerClass).find('.results').addClass('opening').find('.rated').slideToggle('slow', function () {
				$(this).parents(sMatrixContainerClass).find('.results').removeClass('opening').toggleClass('opened');

				//Switch between View or change answers/Hide answers labels
				if ($(this).parents(sMatrixContainerClass).find('.results').hasClass('opened')) {
					btn.parent().find('.ratedBtn.open').hide();
					btn.parent().find('.ratedBtn.close').show();

				} else {
					btn.parent().find('.ratedBtn.open').show();
					btn.parent().find('.ratedBtn.close').hide();
				}

			})
			return false;
		})


		$(" .buttons div.choice", el).hover(
		function () {
			if ($(this).parents('.buttons').hasClass('disabled')) return false;
			$(this).addClass('hover');
		},
		function () {
			$(this).removeClass('hover');
		});
	}
	//Handle skip button pressed state
	var div_skipbtn = $("div.skipbtn");
	div_skipbtn.mousedown(
		function () {
			if ($(this).hasClass('disabled')) return false;
			$(this).addClass('pressed');
		});
	div_skipbtn.mouseup(function () {
		if ($(this).hasClass('disabled')) return false;
		$(this).removeClass('pressed');
	}
	);

	div_skipbtn.hover(
		function () {
			if ($(this).hasClass('disabled')) return false;
			$(this).addClass('hover');
		},
		function () {
			if ($(this).hasClass('disabled')) return false;
			$(this).removeClass('hover');
		}
	);

	/////////////////////////////////
	// Slider (Scale) implementation
	/////////////////////////////////

	// Initialize the Scale Sliders on the page
	survey.CreateScaleSlider(6, true);
});

/// <summary>
/// Image Button click event handler
/// </summary>
VcSurvey.prototype.ImageButtonClick = function(heading, event) {
if ($(event.target).hasClass('specify') || $(event.srcElement).hasClass('specify')) return;
	var inputElement = document.getElementById(heading);
	if (inputElement.type == 'radio')
		inputElement.checked = true;
	else
		inputElement.checked = !inputElement.checked;
	survey.UpdateChoicesAppearance();
}

/// <summary>
/// Check box click
/// </summary>
VcSurvey.prototype.CheckBoxClick = function(heading, event) {
	survey.UpdateChoicesAppearance();
	event.cancelBubble = true;
}

/// <summary>
/// Update appearance of choices
/// </summary>
VcSurvey.prototype.UpdateChoicesAppearance = function() {
	var sfEls = document.getElementsByTagName("DIV");
	var length = sfEls.length;

	for (var i = 0; i < length; i++) {
		if ($(sfEls[i]).hasClass("choice-box")) {
			inputElement = sfEls[i].getElementsByTagName("INPUT")[0];

			if (inputElement.checked) {
				if (!$(sfEls[i]).hasClass("selected")) {
					$(sfEls[i]).addClass("selected");
				}
			}
			else {
				if ($(sfEls[i]).hasClass("selected")) {
					$(sfEls[i]).removeClass("selected");
				}
			}
		}
	}
}
if ($.browser.msie && $.browser.version == '6.0') {
	/// <summary>
	/// Implementation of hover logic (only for IE6)
	/// </summary>
	SFHover = function () {
		var sfEls = document.getElementsByTagName("DIV");
		for (var i = 0; i < sfEls.length; i++) {
			if ($(sfEls[i]).hasClass("choice-box")) {
				sfEls[i].onmouseover = function () {
					this.className += " hover";
				}
				sfEls[i].onmouseout = function () {
					this.className = this.className.replace(new RegExp(" hover"), "");
				}
			}
		}
	}

	if (window.attachEvent) window.attachEvent("onload", SFHover);
}
