/* $Revision$ */

var USGN = function() {
	return {
		util    : {},
		storage : {},
		excel   : {}
	};
}();

// the following are stubs for 'hidden' functions or variables encased in
// closures. this is mainly to assist jslint
function date_today() {}
function new_Option() {}
function new_Options() {}
function signature_check() {}
function QueryString() {}
function CGI() {}
var calendar, f_callback_data;

var _loc = window.location;
var url_prefix = _loc.href.match(/\/\/[^\/]*(\/[^\/]*\/)/) ? RegExp.$1 : undefined;

function cleanNum(n) {
	var a = String(n).replace(/,/g, '');
	a = Number(a.match(/([\-+]?(?:\d+(?:\.\d*)?|\.\d+))/) ? RegExp.$1 : '');
	return a;
}
// backwards compatibility
window._x = cleanNum;

function hid(obj) { return obj.type.toUpperCase() == 'HIDDEN'; }

var re_amp = new RegExp('&', 'g');
var re_eq  = new RegExp('=', 'g');
function ue(x) { return x.replace(re_amp, '%26').replace(re_eq, '%3D'); }

function evil(x) { return eval(x); }

function commify(num) {
	var a = String(num).split('.');
	var b = a[1];
	a = a[0];
	var x_out = 0;
	while (a.match(/(\d+)(\d{3})/g)) {
		a = a.replace(/(\d+)(\d{3})/g, '$1,$2');
		if (x_out++ > 5) {
			USGN.util.log('commify: error, too many commas');
			break;
		}
	}
	return b ? a + '.' + b : a;
}

function dollicommify(val) {
	var tmp = val;
	if (tmp === null || tmp == '') {
		tmp = 0;
	}
	return ('$' + commify(cleanNum(tmp).toFixed(2)));
}

function dateNum(d) { return Math.floor((new Date(d)).getTime()/86400000); }
// backwards compatibility
window._d = dateNum;

function dateNow(n) {
	var a = new Date();
	return dateNum(a.getTime() - (-(n||0) * 86400000) - (a.getTimezoneOffset() * 60 * 1000));
}

function numDate(n) {
	var a = new Date((Number(n) + 1) * 1000 * 60 * 60 * 24);
	var m = a.getMonth() + 1;
	var d = a.getDate();
	if (m < 10) {
		m = '0' + m;
	}
	if (d < 10) {
		d = '0' + d;
	}
	return a.getFullYear() + '/' + m + '/' + d;
}

(function() {
	var _t = {};
	date_today = function(n) {
		if (n in _t) {
			return _t[n];
		}
		var tmp = numDate(dateNow(n)).split('/');
		return (_t[n] = [tmp[1],tmp[2],tmp[0]].join('/'));
	};
}());

function is_leap_year(y) {
	// leap year is every 4 years except for every 100th year except for every 400th year
	// ie 2000 = yes, 2100 = no, 2400 = yes
	return y % 400 === 0 ? true : y % 100 === 0 ? false : y % 4 === 0 ? true : false;
}

function dateFormat(format) {
	var f = [];
	switch (Number(format)) {
		case 1: f[0] = 1; f[1] = 2; f[2] = 0; break; //us - mm/dd/yyyy
		case 2: f[0] = 2; f[1] = 1; f[2] = 0; break; //eu - dd/mm/yyyy
		// case 0:  and
		default: f[0] = 0; f[1] = 1; f[2] = 2; break; //ux - yyyy/mm/dd
	}
	return f;
}

function dateCheck(value, format, separator) {
	if (!value) {
		return false;
	}

	var date = value.split(separator);
	var f = dateFormat(format);
	var y = date[f[0]];
	var m = date[f[1]];
	var d = date[f[2]];

	if (y=='' || y < 1000 || y > 9999) {
		return false;
	}
	if (m=='' || m < 1 || m > 12) {
		return false;
	}
	if (d=='' || d < 1 || d > 31) {
		return false;
	}
	if (m == 2 && d > 29) {
		return false;
	}
	if (m == 2 && d > 28 && !is_leap_year(y)) {
		return false;
	}

	// February needs 29 days in the array below for leap years... February 29th for non-leap years is filtered out above
	if (d > [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][m-1]) {
		return false;
	}

	return true;
}

function setbyvalue(obj, val) {
	var type = obj.type ? obj.type : obj[0] ? obj[0].type : undefined;
	if (arguments.length == 1 || val === undefined) {
		val = null;
	}
	var i, l, j, l2;
	switch (type) {
		case 'radio':
		case 'checkbox':
			var elems = obj.type ? obj.form[obj.name] : obj;
			l = elems.length;
			if (val === null) {
				for (i = 0; i < l; i++) {
					elems[i].checked = false;
				}
			} else if (val.constructor == Array) {
				for (j = 0, l2 = val.length; j < l2; j++) {
					for (i = 0; i < l; i++) {
						if (elems[i].value == val[j]) {
							elems[i].checked = true;
						}
					}
				}
			} else {
				for (i = 0; i < l; i++) {
					if (elems[i].value == val) {
						return (elems[i].checked = true);
					}
				}
			}
			break;
		case 'select-multiple':
		case 'select-one':
			obj.selectedIndex = -1;
			obj = obj.options;
			l = obj.length;
			if (val === null) {
				return true;
			} else if (val.constructor == Array) {
				for (j = 0, l2 = val.length; j < l2; j++) {
					for (i = 0; i < l; i++) {
						if (obj[i].value == val[j]) {
							obj[i].selected = true;
						}
					}
				}
			} else {
				for (i = 0; i < l; i++) {
					if (obj[i].value == val) {
						return (obj[i].selected = true);
					}
				}
			}
			break;
		case 'text':
		case 'textarea':
		case 'password':
		case 'hidden':
			obj.value = val === null ? '' : val.constructor == Array ? val[0] : val;
			break;
		default:
			alert('setbyvalue: unknown type [' + type + ']');
	}
	return true;
}

function select_all(oList) {
	var opt = oList.options;
	for (var i = 0, l = opt.length; i < l; i++) {
		opt[i].selected = true;
	}

}

function populateList(oList, textList, valueList) {
	oList.options.length = 0;
	if (!textList || textList.length === 0) {
		return;
	}
	var i;
	if (textList.constructor == Array) {
		if (valueList) {
			for (i = 0; i < textList.length; i++) {
				oList.options[i] = new_Option(textList[i], valueList[i]);
			}
		} else if (textList[0].constructor == Array) {
			for (i = 0; i < textList.length; i++) {
				oList.options[i] = new_Option(textList[i][1], textList[i][0]);
			}
		} else {
			for (i = 0; i < textList.length; i++) {
				oList.options[i] = new_Option(textList[i], textList[i]);
			}
		}
	} else if (typeof(textList) == 'object') {
		var a = 0;
		for (i in textList) {
			if (textList[i].constructor !== Function) {
				oList.options[a++] = new_Option(textList[i], i);
			}
		}
	} else {
		//alert("don't know what to do with " + typeof(textList))
		//alert(typeof(textList) == 'function')
	}
}

function _b_zero(v)  { if (v == '') { return 0      ; } else { return v; } }
function _b_abort(v) { if (v == '') { throw 'abort' ; } else { return v; } }
function _b_fail(v)  { if (v == '') { throw 'fail'  ; } else { return v; } }

/*
returns array of values of SELECTED items
works on select lists or check boxes
use: document.form1.selectList.getSelections = selections
or : selections(document.form1.selectList)
*/
function selections(obj, get, params) {
	if (this != window) {
		params = get;
		get = obj;
		obj = this;
	}

	if (!params) {
		params = {};
	}

	var a, i;
	if (!get) {
		get = 'value';
	}
	switch (get) {
		case 'index':
			get = function() { return i; };
			break;
		case 'text':
			get = function() { return a[i].text; };
			break;
		default:
			get = function() { return a[i].value; };
	}

	var ret = [];
	var type = obj.type ? obj.type : obj[0] ? obj[0].type : undefined;
	if (!type) {
		alert("can't discern type from " + obj);
		throw 'error';
	}
	if (type == 'checkbox') {
		a = obj.type ? obj.form[obj.name] : obj;
		for (i = 0; i < a.length; i++) {
			if (a[i].checked) {
				ret.push(get());
			}
		}
	} else if (type == 'select-multiple') {
		a = obj.options;
		for (i = 0; i < a.length; i++) {
			if (a[i].selected) {
				ret.push(get());
			}
		}
	} else if (type == 'select-one') {
		if (obj.selectedIndex == -1) {
			ret = '';
		} else {
			a = obj.options;
			i = obj.selectedIndex;
			ret = get();
		}
	} else if (type == 'radio') {
		a = obj.type ? obj.form[obj.name] : obj;
		for (i = 0; i < a.length; i++) {
			if (a[i].checked) {
				ret = get();
				break;
			}
		}
	} else if (type == 'text' || type == 'textarea' || type == 'password' || type == 'hidden') {
		ret = obj.value;
	} else {
		ret = null;
		alert('unknown element type: ' + type);
	}

	return params.force_array && ret.constructor != Array ? [ ret ] : ret;
}

function _all(obj, get, return_type) {
	if (this != window) {
		return_type = get;
		get = obj;
		obj = this;
	}

	var a, i;
	if (!get) {
		get = 'value';
	}
	if (!return_type) {
		return_type = 'array';
	}
	switch (get) {
		case 'index':
			get = function() { return i; };
			break;
		case 'text':
			get = function() { return a[i].text; };
			break;
		case 'both':
			get = return_type == 'hash'
				? function() { return { value : a[i].value, text : a[i].text }; }
				: function() { return [ a[i].value, a[i].text ]; };
			break;
		default:
			get = function() { return a[i].value; };
	}

	var ret = [];
	var type = obj.type ? obj.type : obj[0] ? obj[0].type : undefined;
	if (!type) {
		alert("can't discern type from " + obj);
		throw 'error';
	}
	if (type == 'checkbox') {
		a = obj.type ? obj.form[obj.name] : obj;
		for (i = 0; i < a.length; i++) {
			ret.push(get());
		}
	} else if (type == 'select-multiple') {
		a = obj.options;
		for (i = 0; i < a.length; i++) {
			ret.push(get());
		}
	} else if (type == 'select-one') {
		a = obj.options;
		for (i = 0; i < a.length; i++) {
			ret.push(get());
		}
	} else if (type == 'radio') {
		a = obj.type ? obj.form[obj.name] : obj;
		for (i = 0; i < a.length; i++) {
			ret.push(get());
		}
	} else if (type == 'text' || type == 'textarea' || type == 'password' || type == 'hidden') {
		ret = obj.value;
	} else {
		ret = null;
		alert('unknown element type: ' + type);
	}

	return ret;
}

// this will be assigned by _sort_list_cmp()
function _sort_list_cmp(){}

function sort_list(obj, options) {
	if (this != window) {
		options = obj;
		obj = this;
	}

	// returns [value, text]
	var data = _all(obj, 'both', 'array');

	var sorted;
	_sort_list_cmp = _sort_list_cmp_simple; 
	if (options.smart) {
		// pre-sort with quick match so we're quicker
		sorted = data.sort(_sort_list_text_a);
		_sort_list_cmp = _sort_list_cmp_smart;
		sorted = sorted.sort(_sort_list_text_a);
	} else {
		sorted = data.sort(_sort_list_text_a);
	}

	if (options.reverse) {
		sorted = sorted.reverse();
	}

	populateList(obj, sorted);
}

function _sort_list_cmp_simple(a,b) {
	a = a.toLowerCase(), b = b.toLowerCase();
	return a < b ? -1 : a > b ? 1 : 0;
}

function _sort_list_cmp_smart(_a, _b) {
	var a = _a.toLowerCase();
	var b = _b.toLowerCase();
	if (a === b) {
		return 0;
	}
	if (a.match(/\d+/) && b.match(/\d+/)) {
		var x1 = a.split(/\d+/);
		var x2 = a.match(/(\d+)/g);
		var y1 = b.split(/\d+/);
		var y2 = b.match(/(\d+)/g);
		var l1, l2, s1, s2;
		// if a is longer than b, then is should come 2nd
		var long_a, long_b;
		if (x1.length >= y1.length) {
			long_a = 1;
			long_b = -1;
			l1 = x1;
			l2 = x2;
			s1 = y1;
			s2 = y2;
		} else {
			long_a = -1;
			long_b = 1;
			l1 = y1;
			l2 = y2;
			s1 = x1;
			s2 = x2;
		}
		for (var i = 0, l = s1.length; i < l; i++) {
			if (l1[i] !== s1[i]) {
				return l1[i] < s1[i] ? long_b : long_a;
			}
			var n1 = Number(l2[i]), n2 = Number(s2[i]);
			if (n1 !== n2) {
				return n1 < n2 ? long_b : long_a;
			}
		}
		return long_a;
	} else {
		return a < b ? -1 : 1;
	}
}

function _sort_list_text_a  (a, b) { return _sort_list_cmp(a[1], b[1]); }
function _sort_list_value_a (a, b) { return _sort_list_cmp(a[0], b[0]); }
function _sort_list_text_h  (a, b) { return _sort_list_cmp(a.text, b.text); }
function _sort_list_value_h  (a, b) { return _sort_list_cmp(a.value, b.value); }

function move_options(src, dest, try_insert) {
	var fields = selections(src, 'index');
	if (fields.length === 0) {
		alert('Nothing selected.');
		return false;
	}

	var z, x, tmp;
	if (try_insert && dest.selectedIndex != -1) {
		z = dest.selectedIndex;
		for (x = 0; x < fields.length; x++) {
			tmp = src.options[fields[x]];
			dest.options.add(new_Option(tmp.text, tmp.value), z);
			//dest.options[z].selected = true;
		}
	} else {
		z = dest.options.length;
		for (x = 0; x < fields.length; x++, z++) {
			tmp = src.options[fields[x]];
			dest.options[z] = new_Option(tmp.text, tmp.value);
			//dest.options[z].selected = true;
		}
	}

	for (x = fields.length - 1; x >= 0; x--) {
		src.options[fields[x]] = null;
	}

	return true;
}

function swap_options(first, second) {
	var v = second.value;
	var t = second.text;
	var s = second.selected;
	second.value = first.value;
	second.text = first.text;
	second.selected = first.selected;
	first.value = v;
	first.text = t;
	first.selected = s;
}

function option_up(oList) {
	var x = 0;
	oList = oList.options;
	while (oList[x].selected) {
		x++;
	}

	for (var i = x, l = oList.length; i < l; i++) {
		if (oList[i].selected) {
			swap_options(oList[i], oList[i - 1]);
		}
	}
}

function option_down(oList) {
	var x = 1;
	oList = oList.options;
	while (oList[oList.length - x].selected) {
		x++;
	}

	for (var i = oList.length - x; i >= 0; i--) {
		if (oList[i].selected) {
			swap_options(oList[i], oList[i + 1]);
		}
	}
}

function getindexbyvalue(oList, val) {
	oList = oList.options;
	for (var i = 0; i < oList.length; i++) {
		if (oList[i].value == val) {
			return i;
		}
	}
	return -1;
}

function option_delete(list) {
	var o = list.options;
	for (var i = o.length - 1; i >= 0; i--) {
		if (o[i].selected) {
			o[i] = null;
		}
	}
}

function option_add(list, text) {
	var value = arguments.length > 2 ? arguments[2] : text;
	var new_opt = new_Option(text, value);
	var idx = list.selectedIndex;
	if (idx != -1) {
		list.options.add(new_opt, idx);
	} else {
		list.options[list.options.length] = new_opt;
	}
}

function option_update(list, text) {
	var value = arguments.length > 2 ? arguments[2] : text;
	var idx = list.selectedIndex;
	if (idx == -1) {
		return;
	}
	var opt = list.options[list.selectedIndex] = new_Option(text, value);
	opt.selected = true;
}

function checkEmail(address) {
	if ( ! (/\w\S*@\S+\.\w\w+/).test(address) ) {
		alert("Invalid e-mail address:\n\n'" + address + "'");
		return false;
	}
	return true;
}
function checkEmails(addresses) {
	if (addresses == '') {
		return true;
	}
	var address = addresses.replace(/\n/g, ',').replace(/ /g, '').replace(/;/g, ',').replace(/,,+/g, ',').split(/,/);
	for (var i = 0, l = address.length; i < l; i++) {
		if ( ! checkEmail(address[i]) ) {
			return false;
		}
	}

	return true;
}

function form_obj(elem_id) {
	var obj = {
		'project_id' : df.projectID.value,
		'form_id'    : df.FormID.value,
		'elem_id'    : elem_id,
		'entry_id'   : (df.EntryID ? df.EntryID.value : 0),
		// unique_id doesn't necessarily exist on form_builder_mass.cgi
		// so use a conditional
		'unique_id'  : (df.unique_id ? df.unique_id.value : ''),
		'pass'       : (df.pass ? df.pass.value : '')
	};

	obj.qs = [
		'&projectID=', obj.project_id,
		'&FormID=', obj.form_id,
		'&pass=', obj.pass
	].join('');

	obj.rs = [
		'&p0=', obj.project_id,
		'&p1=', obj.form_id,
		'&p2=', obj.pass,
		'&p3=', obj.entry_id,
		'&p4=', obj.elem_id,
		'&p5=', obj.unique_id
	].join('');

	return obj;
}

function datePick(cal, date) {
	if (!cal.dateClicked) {
		return;
	}
	var elem = cal.__elem;
	var method = cal.__method;
	var fmt = cal.__format;
	var separator = cal.__separator;
	var delta = cal.__delta;

	var d = date.split('/');
	if (method == 'select') {
		for (var i = 0; i < 3; i++) {
			switch (fmt[i]) {
				case 0: setbyvalue(elem[i + 3 * delta], d[0]); break;
				case 1: elem[i + 3 * delta].selectedIndex = d[1]; break;
				case 2: elem[i + 3 * delta].selectedIndex = d[2]; break;
			}
		}
	} else {
		//var d = [year, month, day]
		if (elem.length) {
			elem[0 + 1 * delta].value = [d[fmt[0]], d[fmt[1]], d[fmt[2]]].join(separator);
		} else {
			elem.value = [d[fmt[0]], d[fmt[1]], d[fmt[2]]].join(separator);
		}
	}
	cal.callCloseHandler();
}

function closeHandler(cal) {
	cal.hide();
	calendar = null;
}

function datePicker(src, elem_name, method, format, separator, delta) {
	var elem = src.form[elem_name];
	delta = Number(delta) ? Number(delta) : 0;
	format = Number(format);
	var d, m, y;
	var fmt = dateFormat(format);
	var spread;
	var i;
	if (method == 'select') {
		//alert((Number(extra) || 0))
		spread = 3 * delta + 2;
		for (i = 0; i < 3; i++) {
			switch (fmt[i]) {
				case 0: y = elem[i + 3 * delta].value; break;
				case 1: m = elem[i + 3 * delta].value; break;
				case 2: d = elem[i + 3 * delta].value; break;
			}
		}
	} else {
		// method == 'text'
		var txt;
		if (elem.length) {
			spread = delta + 0;
			txt = elem[delta].value;
		} else {
			txt = elem.value;
		}
			
		if (txt) {
			var date = txt.split(separator);
			for (i = 0; i < 3; i++) {
				switch (fmt[i]) {
					case 0: y = date[i]; break;
					case 1: m = date[i]; break;
					case 2: d = date[i]; break;
				}
			}
		}
		
	}

	var dateStr = y && m && d ? [y, m, d].join('/') : '';

	// delete any previous calendar
	if (calendar) {
		calendar.hide();
	}
	calendar = new Calendar(1, null, datePick, closeHandler);
	var cal = calendar;
	cal.showsTime = cal.time24 = false;
	cal.showsOtherMonths = true;
	cal.setRange(1900, 2050);
	cal.create();
	cal.setDateFormat('%Y/%m/%d');
	cal.parseDate(dateStr);
	cal.__elem = elem;
	cal.__method = method;
	cal.__format = fmt;
	cal.__separator = separator;
	cal.__delta = delta;

	// display calendar (B)ottom, (r)ight-aligned of the nextSibling
	cal.showAtElement((elem.length ? elem[spread] : elem).nextSibling.nextSibling);

	return false;
}

function dateError(format, separator) {
	return (
		[
			[ 'yyyy', 'mm', 'dd, 1000', '01', '01 - 9999', '12', '31' ],
			[ 'mm', 'dd', 'yyyy, 01', '01', '1000 - 12', '31', '9999' ],
			[ 'dd', 'mm', 'yyyy, 01', '01', '1000 - 31', '12', '9999' ]
		][Number(format)]
	).join(separator);
}

/*  File Element */

function append_unique_id(href) {
	var id = '&unique_id=' + df.unique_id.value;
	if (!href.match(/&unique_id=/)) {
		if (href.indexOf('#') != -1) {
			href = href.replace('#', id + '#');
		} else {
			href += id;
		}
	} else {
		href = href.replace(/&unique_id=[^&]*/, id);
	}
	return href;
}

function upload_file(elem_id, __submit) {
	var file = df[elem_id];
	if (file.value == '') {
		alert('No file selected to upload!');
		return false;
	}

	if (file.validate() === false) {
		return false;
	}

	f_callback_data = {
		action: df.action
	};

	df[elem_id + "_file_action.value"] = 'add_attachment';
	oWin.open('cgihtml/waiting.html?unique_id=' + df.unique_id.value + '&callback=f_callback','upload','toolbar=no,location=no,directories=no,status=no,menubar=no,copyhistory=no,scrollbars=no,width=300,height=150');


	// must explicilty be false
	if (__submit !== false) {
		df.action = append_unique_id(_loc.href);
		df._submit.value = 1;
		df.submit();
	}
	return true;
}

function view_file(elem_id) {
	// we can at least check for this one easily
	var oList = df[elem_id + '_attachments'];

	if (oList.selectedIndex == -1) {
		alert('You need to select a file to view.');
		return false;
	} else if (oList.value == 'NoFiles') {
		alert('No attached files to view.');
		return false;
	}

	var filename = oList.value;

	oWin.open('/projdata/temp/' + filename, 'ViewFile', 'width=640,height=480,resizable=1');
	return false;
}

function view_f(elem_id) {
	view_file(elem_id);
	return false;
}

function multi_callback_async(obj, data) {
	var files = evil(data);
	var oList = df[obj.elem_id + '_attachments'];
	populateList(oList, files[0], files[1]);
}

function single_callback_async(obj, data) {
	var files = evil(data);
	var elem = df[obj.elem_id + '_attachments'];
	//populateList(oList, files[0], files[1])
	var node = document.getElementById(obj.elem_id + '_current');
	if (files.length && files[1][0] != 'NoFiles') {
		var a = node.getElementsByTagName('a')[0];
		a.href = files[1][0];
		a.innerHTML = files[0][0];
		elem.value = files[1][0];
	} else if (node) {
		node.innerHTML = '';
	}
}

function RS_remove_attachments(obj, callback) {
	if (!callback) {
		callback = multi_callback_async;
	}

	RSGetData(
		// url
		[
		url_prefix + 'form_builder.cgi?_method=RS_remove_attachments',
			'&p0=', obj.project_id,
			'&p1=', obj.form_id,
			'&p2=', obj.pass,
			'&p3=', obj.entry_id,
			'&p4=', obj.elem_id,
			'&p5=', obj.unique_id,
			'&p6=', obj.values.join(',')
		].join(''),

		// data (for POST)
		null,

		// callback function
		function(data) { callback(obj, data); }
	);
}

function remove_file(elem_id) {
	// we can at least check for this one easily
	if (df[elem_id].value != '') {
		upload_file(elem_id, false);
	}

	var attach = df[elem_id + "_attachments"];

	var files = selections(attach);

	var single = Boolean(attach.type == 'hidden');

	if (single) {
		if (files == '') {
			return false;
		}
	} else if (files.length === 0) {
		alert('You need to select one or more files to remove.');
		return false;
	} else if (files[0] == 'NoFiles') {
		alert('No attached files to remove.');
		return false;
	}

	var obj = form_obj(elem_id);
	obj.values = single ? [ files ] : files;

	if (single) {
		RS_remove_attachments(obj, single_callback_async);
	} else {
		RS_remove_attachments(obj);
	}

	return false;
}

function remove_f(elem_id) {
	remove_file(elem_id);
	return false;
}

function RS_get_attachments(obj, callback) {
	if (!callback) {
		callback = multi_callback_async;
	}

	RSGetData(
		// url
		[
		url_prefix + 'form_builder.cgi?_method=RS_get_attachments',
			'&p0=', obj.project_id,
			'&p1=', obj.form_id,
			'&p2=', obj.pass,
			'&p3=', obj.entry_id,
			'&p4=', obj.elem_id,
			'&p5=', obj.unique_id
		].join(''),

		// data (for POST)
		null,

		// callback function
		function(data) { callback(obj, data); }
	);
}

function refresh_files(elem_id) {
	var obj = form_obj(elem_id);
	if (df[elem_id + "_attachments"].type == 'hidden') {
		RS_get_attachments(obj, single_callback_async);
	} else {
		RS_get_attachments(obj);
	}
	return false;
}

function f_callback(obj) {
	window.setTimeout(function() { obj.child.close(); }, 200);
	df.action = f_callback_data.action;
	f_callback_data = null;

	$('input').filter(function(){ return this.type == 'file'; }).each(function() { 
		refresh_files(this.name);
		var clone = this.cloneNode(true);
		try {
			// FF 3.5? (3.0?) started doing full clones
			if (clone.value) {
				clone.value = '';
			}
		} catch (e) { }
		clone.validate = this.validate;
		this.parentNode.replaceChild(clone, this);
	});
}

function do_multi(elem_id, fileTypes) {
	var obj = form_obj(elem_id);
	obj.prefix = [obj.project_id, obj.form_id, obj.entry_id, obj.elem_id, obj.unique_id];

	var cb = function(args) {
		obj.args = args;
		RS_get_attachments(obj);
	};
	var params = {
		prefix   : obj.prefix,
		callback : cb 
	};

	//params.fileTypes   : "All Files:*,AutoCAD Files (=v1):*.dwg;*.dwf;*.dwx,Image Files:*.jpg;*.png;*.gif;*.bmp;*.ico",
	if (fileTypes) {
		params.fileTypes = fileTypes;
	}

	oWin.showDialog(
		'cgihtml/fupload.html',
		params,
		'dialogHeight:340px;dialogWidth:310px'
	);
	return false;
}

function rs_proxy(elem_id, method, params, callback) {
	var obj = form_obj(elem_id);
	var _callback;
	if (callback) {
		_callback = function (data) { callback(obj, data); };
	}

	var extra_args = '';
	for (var i in params) {
		if (params[i].constructor !== Function) {
			extra_args += '&' + i + '=' + params[i];
		}
	}
	return RSGetData(
		// url
		[
			url_prefix + 'form_builder.cgi?_method=rs_proxy',
			obj.rs,
			'&elem_method=', method,
			extra_args
		].join(''),

		// data (for POST)
		null,

		// callback function
		_callback
	);
}

function check_auth(elem_id, pass, callback) {
	if (!window.encrypt) {
		throw new Error('Unable to send password securely. Aborting.');
	}
	return rs_proxy.apply(null,
		[
			// standard args
			elem_id, 'check_auth', { pass : encrypt(pass, getCookie('SessionID')) }
		].concat(
			// optional args
			callback ? [callback] : []
		)
	);
}

function disable(obj) {
	if (!obj) {
		obj = this;
	}
	switch (obj.type) {
		case 'button':
			obj.onclick = null;
			break;
		case 'select-multiple':
			break;
		default:
	}
	obj.disabled = true;
}

function enable(obj, extra) {
	if (!obj) {
		obj = this;
	}
	switch (obj.type) {
		case 'select-multiple':
			if (extra) {
				obj.onchange = extra;
			}
			break;
		case 'button':
			if (extra) {
				obj.onclick = extra;
			}
			break;
		case 'text':
			break;
		default:
	}
	obj.onfocus = null;
	obj.disabled = false;
}

function stop_propagation(e) {
	if (e.preventDefault) {
		e.preventDefault();
		e.stopPropagation();
	} else {
		e.returnValue = false;
		e.cancelBubble = true;
	}
	return false;
}

if (window.addEventListener) {
	window.add_event = function (obj, evt, fn) { obj.addEventListener(evt, fn, false); };
	window.del_event = function (obj, evt, fn) { obj.removeEventListener(evt, fn, false); };
} else {
	window.add_event = function (obj, evt, fn) { obj.attachEvent('on' + evt, fn); };
	window.del_event = function (obj, evt, fn) { obj.detachEvent('on' + evt, fn); };
}

function opt_groups(sel_list) {
	var x = _all(sel_list);
	var z = [];
	var t = [];

	var og = document.createElement('optgroup');

	// cycle through backwards looking for {text}
	for (var i = x.length - 1; i >= 0; i--) {
		if (x[i].indexOf('{') == 0) {
			var ogg = og.cloneNode(true);
			ogg.label = x[i].replace(/[}{]/g, '');
			for (var j = t.length - 1; j >= 0; j--) {
				ogg.appendChild(new_Option(t[j], t[j], true));
			}
			t = [];
			z.push(ogg);
		} else {
			t.push(x[i])
		}
	}
	if (t.length) {
		for (var j = t.length - 1; j >= 0; j--) {
			z.push(new_Option(t[j], t[j], true));
		}
	}
	sel_list.options.length = 0;
	for (var i = z.length - 1; i >= 0; i--) {
		sel_list.appendChild(z[i]);
	}
}

(function() {
	var option = document.createElement('option');
	var _div = document.createElement('div');
	new_Option = function(text, value) {
		if (window.$ && $.browser.msie) {
			new_Option = function(text, value, dirty_ie) {
				if (arguments.length == 1) {
					value = text;
				} else if (arguments.length > 2 && dirty_ie) {
					var opt = new Option(text, value);
					opt.appendChild(document.createTextNode(text));
					return opt;
				}
				return new Option(text, value);
			};
		} else {
			new_Option = function(text, value) {
				var opt = option.cloneNode(true);
				opt.text = text;
				opt.value = arguments.length > 1 ? value : text;
				return opt;
			};
		}
		return new_Option.apply(this, arguments);
	};
	new_Options = function(opts) {
		var html = ['<select>'];
		var l = opts.length;
		if ('value' in opts[0]) {
			for (var i = 0; i < l; i++) {
				var opt = opts[i];
				html = html.concat(['<option value="', opt.value, '">', opt.text, '</option>']);
			}
		} else {
			for (var i = 0; i < l; i++) {
				var opt = opts[i];
				html.concat(['<option>', opt.text, '</option>']);
			}
		}
		html.push('</select>');
		_div.innerHTML = html.join('');
		return _div.firstChild.childNodes;
	};
}());

(function() {
	var cache = {in_elem:{},out_elem:{},pass:{}};

	var signature_callback = function(obj, data, not_forced) {
		var ret = evil(data);
		var params = { message: 'Password is ' + (ret ? 'valid' : 'invalid'), css: { fontFamily : 'Arial' } };
		if (not_forced) {
			params.timeout = 3000;
		} else {
			params.message += '<br /><input type="button" value="OK" onclick="$.unblockUI()">';
		}
		$.blockUI(params);
		var password = cache.in_elem[obj.elem_id].value;
		cache.out_elem[obj.elem_id].value = encrypt(password, getCookie('SessionID'));
		if (ret) {
			cache.pass[password] = true;
		}
		return ret;
	};

	signature_check = function(elem, force) {
		var pass_input;
		if (elem.name in cache.in_elem) {
			pass_input = cache.in_elem[elem.name];
		} else {
			pass_input = document.getElementById(elem.name + '_pass');
			cache.in_elem[elem.name] = pass_input;
			cache.out_elem[elem.name] = elem;
		}

		var password = pass_input.value;

		if (password == '') {
			if (force) {
				alert('Password can not be empty');
				return false;
			}
			// if we weren't forced into this, then we probably are not approving
			return true;
		}

		if (password in cache.pass) {
			if (!force) {
				return true;
			}
			delete cache.pass[password];
		}

		if (!window.encrypt) {
			alert('Unable to send password securely. Aborting.');
			return false;
		}

		$.blockUI({message: 'Validating password', css: { fontFamily : 'Arial' } });

		var ret;

		try {
			ret = check_auth.apply(null, [elem.name, password].concat(force ? [signature_callback] : []));
		} catch(e) {
			alert(e.message);
			$.unblockUI({fadeOut: 0});
			return false;
		}

		if (force) {
			return false;
		}

		return signature_callback(form_obj(elem.name), ret, true);
	};

}());

(function() {

	QueryString = function(qs) {
		this.query = qs || window.location.search.substring(1);
		this.names = [];
		this.params = {};
		this.processed = false;
	};

	// for perl likeness
	CGI = QueryString;

	var p = QueryString.prototype;
	p.process = function() {
		if (this.processed) {
			return;
		}
		this.processed = true;
		if (!this.query) {
			return;
		}

		var chunks = this.query.split(re_amp);

		for (var i = 0; i < chunks.length; i++) {
			var pair = chunks[i].split(re_eq, 2);
			var v = unescape(pair[1]);
			if (pair[0] in this.params) {
				var tmp = this.params[pair[0]];
				if (tmp.constructor == Array) {
					tmp.push(v);
				} else {
					tmp = [ tmp, v];
					this.params[pair[0]] = tmp;
				}
			} else {
				this.names.push(pair[0]);
				this.params[pair[0]] = v;
			}
		}
	};

	p.param = function(name, value) {
		this.process();
		if (!name) {
			return this.names;
		}
		if (arguments.length === 2) {
			if ((name in this.params) === false) {
				this.names.push(name);
			}
			return (this.params[name] = value);
		} else {
			return this.params[name];
		}
	};

	p.toString = function() {
		var str = [];
		for (var i = 0, l = this.names.length; i < l; i++) {
			var a = this.names[i];
			var b = this.params[a];
			if (b.constructor == Array) {
				for (var j = 0, k = b.length; j < k; j++) {
					str.push(a + '=' + b[j]);
				}
			} else {
				str.push(a + '=' + b);
			}
		}
		return str.join('&');
	};

}());

// static class
USGN.util = {
	log : null,
	warn : null,
	error : null
};

(function() {
	var _self = USGN.util;
	_self.log = window.console ? function(msg) { window.console.log(msg); } : function() {};
	_self.warn = _self.log;
	_self.error = function(msg) { _self.log(msg); alert(msg); };
}());

// static class
USGN.storage = {
	localStore : null,
	store_type : null,
	can_store  : null,
	store      : null,
	retrieve   : null,
	clear      : null,
	set_up_local_store : null
};

(function() {
 	var _self = USGN.storage;
	_self._log = '';
	_self.log = function(x) { _self._log += x.constructor === Array ? x.join(' ') : x };

	var localStore;
	_self.set_up_local_store = function() {
		if (!$.browser.msie) {
			_self.log('browser is not ie, or local_store already exists');
			return true;
		} else if (localStore = _self.localStore = $('#local_store').get(0)) {
			_self.log('local_store already exists');
			return true;
		}

		_self.log('browser is ie and local_store does not exist');

		$(document.body).append('<div id="local_store" style="behavior:url(#default#userData);"></div>');

		_self.log('added local_store');

		localStore = _self.localStore = $('#local_store')[0];
	};

	var _ST_X = -1;
	var _ST_NONE = 0, _ST_IE = 1, _ST_MOZ = 2, _ST_STD = 3;
	var store_x;
	_self.store_type = function() {
		if (_ST_X !== -1) {
			return _ST_X;
		}
		if (!window.$) {
			USGN.util.error('jQuery needed for this to complete');
		}
		if (typeof window.localStorage != 'undefined') {
			store_x = window.localStorage;
			return (_ST_X = _ST_STD);
		}
		if (typeof window.globalStorage != 'undefined') {
			store_x = window.globalStorage[window.location.hostname];
			return (_ST_X = _ST_MOZ);
		}
		if ($.browser.msie && !localStore) {
			_self.set_up_local_store();
		}
		if (localStore && typeof(localStore.XMLDocument) != 'undefined') {
			return (_ST_X = _ST_IE);
		}
		return (_ST_X = _ST_NONE);
	};

	_self.store_type_text = function() { return [ 'None', 'IE Session', 'Mozilla Session', 'Standard Session (best)' ][_self.store_type()]; };

	_self.can_store = function() { return _self.store_type() != _ST_NONE ? true : false; };
}());


// jslint stuff
/*jslint evil: true */
/*global window,console,alert,df,document,Calendar,oWin,RSGetData,encrypt,getCookie,unescape,$ */
/*members $1, EntryID, FormID, __delta, __elem, __format, __method, 
    __separator, _d, _submit, _x2, action, add, addEventListener, add_event, 
    appendChild, apply, args, attachEvent, blockUI, callCloseHandler, 
    callback, cancelBubble, checked, child, cloneNode, close, concat, 
    console, constructor, create, createElement, createTextNode, css, 
    dateClicked, del_event, detachEvent, disabled, each, elem_id, encrypt, 
    entry_id, fadeOut, fileTypes, filter, floor, fontFamily, force_array, 
    form, form_id, getDate, getElementById, getElementsByTagName, 
    getFullYear, getMonth, getTime, getTimezoneOffset, hide, href, in_elem, 
    indexOf, innerHTML, join, length, location, log, match, message, name, 
    names, nextSibling, onchange, onclick, onfocus, open, options, out_elem, 
    param, params, parentNode, parseDate, pass, prefix, preventDefault, 
    process, processed, projectID, project_id, prototype, push, qs, query, 
    removeEventListener, replace, replaceChild, returnValue, rs, search, 
    selected, selectedIndex, setDateFormat, setRange, setTimeout, 
    showAtElement, showDialog, showsOtherMonths, showsTime, split, 
    stopPropagation, submit, substring, test, text, time24, timeout, 
    toString, toUpperCase, type, unblockUI, unique_id, validate, value, 
    values
*/
