// Initialize page on load; necessary for dynamic checkbox/button interaction
window.onload = init;
var menuTimerID = null;
var menuTimerActive = false;
var menuResetTimerID = null;
var menuResetTimerActive = false;
var fixIEMenus = false;
var fixHeaderTimer;
var entryEditorForm;
var tipBoxes;

var numberOfOpenAjaxRequests = 0;
var systemIsBusyAlert;

// Global property to keep track of when there is a menu open
var oldMenuItem = null;

function roundedCornerGenerator(className) {
	function addCorners(number) {
		if (!number) number = 10;
		var html = '';
		for (var i = 1; i <= number; i++) {
			html += '<div class="roundCorner roundCorner' + i + '"></div>';
		}
		return html;
	}
	$$('.' + className + ' > li').invoke('append', addCorners(10));
}

function cumulativeOffset(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      element = element.offsetParent;
    } while (element);
    return [valueL, valueT];
}

// Execute some initialization when DOM has loaded
if (typeof(domLoadedHandlerHasRun) == 'undefined' || !domLoadedHandlerHasRun) {
	var domLoadedHandlerHasRun = true;
	document.observe("dom:loaded", function() {
		preCacheSpinnerImage();
		roundedCornerGenerator("roundCornerTabs");
		Event.observe(document, "click", clickHandler);
		Event.observe(document, "click", shiftClickHandler);
		EncryptedData.init();
		SummaryLinks.init();
		initEntryEditor();
		Autocompleters.init();
		initEditColumns();
		ClickEditTable.init();
		initTips();
		Hotkeys.init();
		InitialSelectValues.init();
	});
}

// Window initializer
function init() {
	CategoryMenu.init();
	GlobalPageTimer.reset();
}

GlobalPageTimer = {
	ID: null,
	hasTimedOut: function() {
		new ModalConfirm('This session has timed out. Click OK to reload the page, or click Cancel if you still need to access the page. (You will be unable to perform any actions without reloading.)', function() { window.location.reload(); });
	},
	reset: function() {
		if (this.ID) {
			window.clearTimeout(this.ID);
		}
		this.ID = window.setTimeout(GlobalPageTimer.hasTimedOut, 7200000); // timeout the page in 2 hours
	}
};

function initTips() {
	tipBoxes = $$('div.tip');
	window.setTimeout(alternateTips, 1000);
	$$('a.hideTip').invoke('observe', 'click', hideTip);
	$$('a.hideAllTips').invoke('observe', 'click', hideAllTips);
}

function initEntryEditor() {
	entryEditorForm = $(document.forms['objectEditor']);
	if (!entryEditorForm) return;
	entryEditorForm.getElementsBySelector('input[type="submit"]').invoke('observe','click', function(evt) {
		Attachments.submitButtonName = Event.element(evt).name;
	});
	entryEditorForm.observe('submit', submitEntryEditor);
}

function initEditColumns() {
	var editColumnForm = $(document.forms['tableReportForm']);
	if (!editColumnForm) return;
	editColumnForm.observe('submit', function(evt) {
		EncryptedData.encryptAll();
	});
}

function submitEntryEditor(evt, callback) {
	if (callback) {
		Attachments.submitButtonName = callback;
	}
	EncryptedData.encryptAll();
	Attachments.startUploads();
	Attachments.submitIfFilesFinished(evt);
}

var AutocompleteField = Class.create();
AutocompleteField.prototype = {
	initialize: function(fieldBox) {
		this.request = null;
		this.fieldBox = fieldBox;
		this.field = fieldBox.down('.objectAdderAutocompleteSearch');
		if (!this.field && !$(fieldBox.id + '-search')) {
			var select = fieldBox.down('select');
			if (select && !select.id) {
				select.id = fieldBox.id + '-search';
			}
			return;
		}
		this.addValueButton = this.field.next('input[type="submit"]');
		if (!this.addValueButton) return;
		this.addValueButton.onclick = this.submitHighlightedResultIfPossible.bind(this);
		this.loading = $E('ul.popMenu');
		var loadingListItem = this.loading.appendChild($E('li'));
		var spinnerImg = SpinnerImage.cloneNode(true);
		spinnerImg.className = 'objectAdderAutocompleteLoading';
		loadingListItem.appendChild(spinnerImg);

		if (!this.field) return null;

		this.hiddenField = $E('input#' + this.field.name + '-autocomplete', { type: 'hidden', name: this.field.name + '-autocomplete' });
		
		this.hiddenFieldID = $(this.field.id + '-autocompleteID');

		if (this.field.style.color != 'gray') {
			this.hiddenField.value = this.field.value; // if a value is present, put it in the hidden field too
		}

		this.fieldBox.insertBefore(this.hiddenField, this.field);
		this.searchResults = $E('div#s' + this.field.name + '-searchResults' + '.' + 'objectAdderAutocompleteSearchResults' + '.' + 'popMenuBox');
		this.fieldBox.appendChild(this.searchResults);
		this.searchResults.style.display = 'none';
		new Form.Element.Observer(this.field, 0.1, this.update.bind(this));
		this.field.onkeyup = this.handleCursorKeys.bindAsEventListener(this);
		this.field.onkeypress = this.handleReturnKey.bindAsEventListener(this);
		this.field.observe('click', function() { this.select() }.bind(this.field));
	},
	
	submitHighlightedResultIfPossible: function(evt) {
		if (oldMenuItem == this.searchResults && oldMenuItem.visible()) {
			var link = this.searchResults.down('li.objectAdderAutocompleteHighlightedResult>a');
			if (link && link.onclick) {
				link.onclick();
			}
		} else {
			var element = Event.element(evt);
			// if we're in a filter and there are no search results, clear the filter and submit
			if (!this.searchResults.visible() && element.up('.filterInput')) {
				var form = this.field.form;
				this.hiddenField.value = this.field.value = '';
				if (this.hiddenFieldID) {
					this.hiddenFieldID = this.field.value;
				}
				form.appendChild($E('input', { type: 'hidden', name: this.addValueButton.name, value: this.addValueButton.value }));
				window.setTimeout(function() { form.submit(); }, 10);
			}
		}
		return false;
	},
	
	highlightResult: function(evt) {
		var element = Event.element(evt);
		if (element.getNodeName() != 'li') {
			element = element.up('li');
		}
		if (element) {
			var oldItem = this.searchResults.down('li.objectAdderAutocompleteHighlightedResult');
			if (oldItem) {
				oldItem.removeClassName('objectAdderAutocompleteHighlightedResult');
			}
			element.addClassNameOnce('objectAdderAutocompleteHighlightedResult');
		}
	},
	
	highlightSiblingResult: function(index) {
		var oldItem = this.searchResults.down('li.objectAdderAutocompleteHighlightedResult');
		if (oldItem) {
			var newItem;
			if (index > 0) {
				newItem = oldItem.next('li', (index - 1));
			} else if (index < 0) {
				newItem = oldItem.previous('li', (index + 1));
			}
			if (newItem && !newItem.hasClassName('objectAdderAutocompleteInvalid')) {
				oldItem.removeClassName('objectAdderAutocompleteHighlightedResult');
				newItem.addClassNameOnce('objectAdderAutocompleteHighlightedResult');
			}
		}
	},
	
	handleCursorKeys: function(evt) {
		var keyCode = evt.keyCode || evt.which;
		switch(keyCode) {
			case Event.KEY_UP:
			case 63232: // wtfhax: safari has different keycodes for cursor keys
				this.highlightSiblingResult(-1);
				return false;
				break;
			case Event.KEY_DOWN:
			case 63233:
				this.highlightSiblingResult(1);
				return false;
				break;
			default:
				break;
		}
		return true;
	},

	handleReturnKey: function(evt) {
		var keyCode = evt.keyCode || evt.which;
		switch(keyCode) {
			case Event.KEY_RETURN:
				this.submitHighlightedResultIfPossible(evt);
				return false;
				break;
			default:
				break;
		}
		return true;
	},

	update: function(element, value) {
		if (this.requestTimer) {
			window.clearTimeout(this.requestTimer);
		}
		if (element.style.color == 'gray') {
			element.style.color = '';
		}
		this.searchResults.hide();
		if (value == this.hiddenField.value) return;
		if (value.length > 0) {
			this.requestTimer = window.setTimeout(this.startRequest.bind(this, value), 200);
		}
	},
	
	startRequest: function(value) {
		if (this.request && this.request.transport && !this.request._complete) {
			this.request.transport.abort();
		}
		while (this.searchResults.firstChild) {
			this.searchResults.removeChild(this.searchResults.firstChild);
		}
		this.searchResults.appendChild(this.loading.cloneNode(true));
		swapItem(this.searchResults);
		this.request = this.getResults(value);
	},
	
	addResultItem: function(list, text, value) {
		text = text.strip(); // trim leading/trailing spaces
		var listItem = $E('li');
		var link = listItem.appendChild($E('a', {
			href: 'javascript:void(0)',
			innerHTML: (text == value && (text == 'anything' || text == 'nothing')) ? '<strong>' + text + '</strong>' : text
		}));
		list.appendChild(listItem);
		link.onclick = function() {
			this.hiddenField.value = this.field.value = value ? text : ''; // only show a value if there is an ID to match
			if (this.hiddenFieldID) {
				this.hiddenFieldID = value;
			}
			this.searchResults.hide();
			if (value != '') {
				var form = $(this.field.form);
				if (form.name == 'objectEditor') {
					submitEntryEditor(null, this.addValueButton.name);
				} else {
					form.appendChild($E('input', { type: 'hidden', name: this.addValueButton.name, value: this.addValueButton.value }));
					window.setTimeout(function() { form.submit(); }, 10);
				}
			}
		}.bind(this);
		listItem.onmouseover = this.highlightResult.bindAsEventListener(this);
		return listItem;
	},

	processResults: function(t) {
		while (this.searchResults.firstChild) {
			this.searchResults.removeChild(this.searchResults.firstChild);
		}

		var list = this.searchResults.appendChild($E('ul.popMenu'));

		var resultItems = eval(t.responseText);
		var numItems = resultItems.length;
		for (var i = 0; i < numItems; i++) {
			var item = resultItems[i];
			if (item !== true && item !== false) {
				var listItem;
				if (typeof(item) != 'string') {
					listItem = this.addResultItem(list, item[0], item[1]);
				} else {
					listItem = this.addResultItem(list, item, item);
				}
				if (i == 0) {
					listItem.addClassName('objectAdderAutocompleteHighlightedResult');
				}
			} else if (item === true) {
				this.addResultItem(list, Autocompleters.tooManyMatches, '').addClassName('objectAdderAutocompleteInvalid');
			} else if (i == 0 && item === false) {
				this.addResultItem(list, Autocompleters.noMatches, '').addClassName('objectAdderAutocompleteInvalid');
			}
		}
	},

	getResults: function(value) {
		var params = $(document.forms[0]["_k"]).serialize() + '&' + this.field.serialize();
		GlobalPageTimer.reset();
		return new Ajax.Request(Autocompleters.url, {
			parameters: params,
			onSuccess: this.processResults.bind(this)
		});
	}	
};

var Autocompleters = {
	url: window.location.href,
	noMatches: 'No matches found.',
	tooManyMatches: '<strong>&#8230;and others</strong>',
	init: function() {
		$$('.objectAdderAutocompleteBox').each(function (fieldBox) {
			new AutocompleteField(fieldBox);
		});
	}
};

SummaryLinks = {
	show: function() {
		$$('.' + this.className.match(/summary\d+/)).invoke('addClassName','summaryLinkHover');
		$('reportShowFieldButtonTop').fire();
	},
	hide: function() {
		$$('.' + this.className.match(/summary\d+/)).invoke('removeClassName','summaryLinkHover');
		$('reportShowFieldButtonTop').extinguish();	
	},
	init: function() {
		$$(".summaryLink").each(function (item) {
			item.title = "Click to add this field as a column in the table";
			item.observe("mouseover", SummaryLinks.show.bindAsEventListener(item));
			item.observe("mouseout", SummaryLinks.hide.bindAsEventListener(item));
		});
	}
};

EncryptedData = {
	verificationNumber: null,
	text: {
		pageContainsEncryptedData: 'This page contains encrypted data. ',
		valueContainsEncryptedData: 'To view or edit this value, you must insert your pass phrase. (Click to open the pass phrase input window.)',
		openWindow: 'Click here to insert your pass phrase.'
	},
	isDecrypted: false,
	keyWindowURL: '/weblatest/encryption-key.html',
	setKeyWindowURL: '/weblatest/encryption-key-set.html',
	keyWindow: null,
	key: null,
	localStorageKey: window.location.host + '-databaseEncryption',
	placeholder: '********',
	displayValues: [],
	inputs: [],
	decryptedValues: {},
	keyWindowOpen: function() {
		return (this.keyWindow && this.keyWindow.DabbleKey);
	},
	addClickHandler: function(item) {
		item.title = EncryptedData.text.valueContainsEncryptedData;
		item.onclick = EncryptedData.openKeyWindow;
	},
	removeClickHandler: function(item) {
		item.title = '';
		item.onclick = '';
	},
	verifyKey: function() {
		if (!this.keyWindow.DabbleKey.key) return false;
		var verifyNumbers = this.verificationNumber.match(/(\w+)-(\d+)/);
		if (!verifyNumbers) return false;
		var verified = this.keyWindow.DabbleKey.decrypt(verifyNumbers[1], verifyNumbers[2]);
		if (!verified || verified.search(/^\d+$/) == -1) {
			return false;
		}	else {
			return true;
		}
	},
	decryptAll: function() {
		if (!this.keyWindowOpen() || !this.verificationNumber || !this.verifyKey()) return false;
		this.isDecrypted = true;
		this.inputs.each(function (input) {
			var encryptedValue = $(input.id + '-encrypted');
			var values = encryptedValue.value.match(/(\w*)-(\d+)/);
			if (!values) return false;
			var decryptedValue = (values[1] == '') ? '' : EncryptedData.keyWindow.DabbleKey.decrypt(values[1], values[2]);
			if (decryptedValue !== null) {
				EncryptedData.decryptedValues[input.id] = input.value = decryptedValue;
				input.addClassName('formDecryptedInput');
				input.removeAttribute('readonly');
				input.removeAttribute('readOnly'); // IE seems to need this
				EncryptedData.removeClickHandler(input);
			} else {
				EncryptedData.isDecrypted = false;
				EncryptedData.openKeyWindow();
				throw $break;
			}
		});
		this.displayValues.each(function (value) {
			if (value.hasClassName('encryptedDisplayValueDecrypted')) return;
			var encryptedValue = $(value.id + '-encrypted');
			var values = encryptedValue.innerHTML.match(/(\w*)-(\d+)/);
			if (!values) return;
			var decryptedValue = (values[1] == '') ? '' : EncryptedData.keyWindow.DabbleKey.decrypt(values[1], values[2]);
			if (decryptedValue !== null) {
				value.innerHTML = decryptedValue;
				value.addClassName('encryptedDisplayValueDecrypted');
				EncryptedData.removeClickHandler(value);
			} else {
				return;
			}
		});
		return this.isDecrypted;
	},
	generateRandomIV: function() {
		return Math.floor(Math.random() * 10000000 + 1).toString();
	},
	encryptAll: function() {
		if (!this.keyWindowOpen() || !this.verifyKey()) return; 
		this.inputs.each(function (input) {
			var encryptedValue = $(input.id + '-encrypted');
			if (EncryptedData.decryptedValues[input.id] && input.value == EncryptedData.decryptedValues[input.id]) return;
			var iv = EncryptedData.generateRandomIV();
			var newEncryptedValue = EncryptedData.keyWindow.DabbleKey.encrypt(input.value, iv);
			if (newEncryptedValue !== null) {
				encryptedValue.value = newEncryptedValue + '-' + iv;
			}
		});
		this.resetAll();
	},
	resetAll: function() {
		this.isDecrypted = false;	
		this.inputs.each(function (input) {
			input.setAttribute('readonly','readonly');
			input.removeClassName('formDecryptedInput');
			var encryptedValue = $(input.id + '-encrypted');
			if (encryptedValue) {
				input.value = encryptedValue.value;
			}
			EncryptedData.addClickHandler(input);
		});
	},
	openKeyWindow: function() {
		var newWindowFeatures = "dependent=yes,height=350,resizable=yes,scrollbars=yes,width=650,screenX=" + (window.screenX + 40) + ",screenY=" + (window.screenY + 40);
		EncryptedData.keyWindow = window.open('', "dabbleEncryptionKeyWindow", newWindowFeatures);
		window.focus();
		if (!EncryptedData.keyWindow) {
			EncryptedData.addEncryptionNote();
			return;
		}
		if (!EncryptedData.keyWindow.DabbleKey || !EncryptedData.keyWindow.DabbleKey.onKeyEnterPage) {
			EncryptedData.keyWindow.location = EncryptedData.keyWindowURL;
			EncryptedData.keyWindow.focus();
		} else {
			if (EncryptedData.keyWindow.DabbleKey.applyKey()) {
				return;
			}	else {
				EncryptedData.keyWindow.focus();
			}
		}
	},
	openSetKeyWindow: function() {
		EncryptedData.openWindow(EncryptedData.setKeyWindowURL);
	},
	openWindow: function(url) {
		var newWindowFeatures = "dependent=yes,height=350,resizable=yes,scrollbars=yes,width=650,screenX=" + (window.screenX + 20) + ",screenY=" + (window.screenY + 20);
		EncryptedData.keyWindow = window.open('', "dabbleEncryptionKeyWindow", newWindowFeatures);
		window.focus();
		if (EncryptedData.keyWindow) {
			if (EncryptedData.keyWindow.DabbleKey) {
				if (EncryptedData.keyWindow.DabbleKey.onKeyEnterPage && EncryptedData.keyWindow.DabbleKey.applyKey()) {
					return;
				}	else {
					if (!EncryptedData.keyWindow.DabbleKey.onKeyEnterPage && url == EncryptedData.keyWindowUrl) {
						EncryptedData.keyWindow.location = url;
					}
					EncryptedData.keyWindow.focus();
				}
			} else {
				EncryptedData.keyWindow.location = url;
				EncryptedData.keyWindow.focus();
			}
		} else {
			EncryptedData.addEncryptionNote();
		}
	},
	addEncryptionNote: function() {
		var noteBox = $('encryptedValuesOnPageNote');
		if (noteBox) {
			if (!noteBox.visible()) {
				fadeIn(noteBox);
			}
			return;
		}
		var header = $('globalHeader');
		noteBox = $E('div#encryptedValuesOnPageNote');
		noteBox.style.display = 'none';
		var note = noteBox.appendChild($E('p'));
		note.appendChild(document.createTextNode(this.text.pageContainsEncryptedData));
		var link = $E('a', { href: 'javascript:void(0)', innerHTML: this.text.openWindow });
		note.appendChild(link);
		header.up().insertBefore(noteBox, header);
		link.observe('click', EncryptedData.openKeyWindow.bind(EncryptedData));
		fadeIn(noteBox);
	},
	init: function() {
		this.displayValues = $$('.encryptedDisplayValue');
		this.inputs = $$('input.formEncryptedInput');
		if (this.displayValues.length === 0 & this.inputs.length === 0) return;
		this.displayValues.each(this.addClickHandler);
		this.inputs.each(this.addClickHandler);
		this.openKeyWindow();
	}
};

function ModalBox() {
	this.initializeAlert = function(text, action) {
		this.text = text || '';
		this.action = action || function() {};	
		this.hiddenBox = $E('div.hiddenBox');
		this.popWindow = this.hiddenBox.appendChild($E('div.popWindow'));
		this.promptBox = this.popWindow.appendChild($E('div.promptBox'));
		if (typeof(this.text) == 'string') {
			this.p = this.promptBox.appendChild($E('p', { innerHTML: this.text }));
		} else if (this.text.nodeName) {
			this.p = this.promptBox.appendChild(this.text);
		}
		this.p2 = this.promptBox.appendChild($E('p'));
		this.okay = $E('input.button.formButton', { type: 'button', value: 'OK' });
		this.p2.appendChild(this.okay);
		this.okayAction = function() {
			this.action();
			demoteFixedContainer();
			this.hiddenBox.remove();
		}.bind(this);
	}
	
	this.addCancel = function(actionFailure) {
		this.actionFailure = actionFailure || function() {};
		this.cancel = this.p2.appendChild($E('input.button.formButton', { type: 'button', value: 'Cancel' }));	
		this.cancelAction = function() {
			this.hiddenBox.remove();
			this.actionFailure();
			demoteFixedContainer();
		}.bind(this);
	}
	
	this.attachToPage = function() {
		$$('.globalBox')[0].appendChild(this.hiddenBox);
		this.okay.observe('click', this.okayAction);
		if (this.cancel && this.cancelAction) {
			this.cancel.observe('click', this.cancelAction);
		}
	}
	
	this.display = function() {
		promoteFixedContainer();
	}

	return this;
}

function ModalAlert(text, action) {
	this.initializeAlert(text, action);
	this.attachToPage();
	this.display();
	return this;
}
ModalAlert.prototype = new ModalBox;

function ModalConfirm(text, action, actionFailure) {
	this.initializeAlert(text, action);
	this.addCancel(actionFailure);
	this.attachToPage();
	this.display();
	return this;
}
ModalConfirm.prototype = new ModalBox;

function ModalPrompt(text, action, actionFailure, defaultValue, inputType, inputLabel) {
	this.initializeAlert(text, action);
	defaultValue = defaultValue || '';
	inputType = inputType || 'text';
	this.addCancel(actionFailure);
	this.p1 = this.promptBox.insertBefore($E('p'), this.p2);

	if (inputType == 'text') {
		this.promptField = $E('input.text.formTextInput', { type: 'text', value: defaultValue });
	} else if (inputType == 'checkbox') {
		this.promptField = $E('input.checkbox#modalPromptCheckbox', { type: 'checkbox', value: defaultValue });
	}

	if (inputLabel) {
		var label = $E('label', { 'for': 'modalPromptCheckbox' });
		label.insert(this.promptField);
		label.insert('&nbsp;' + inputLabel);
		this.p1.insert(label);
	} else {
		this.p1.insert(this.promptField);
	}
	
	this.okayAction = function() {
		var value;
		value = (inputType == 'checkbox' && !this.promptField.checked) ? '' : this.promptField.value;
		this.action(value);
		demoteFixedContainer();
		this.hiddenBox.remove();
	}.bind(this);

	this.attachToPage();

	if (inputType == 'text') {
		this.promptField.onkeyup = function(e) {
			var code;
			e = e || window.event;
			code = e.keyCode || e.which;
			if (code == 13) { // Return
				this.okayAction();
			} else if (code == 27) { // Esc
				this.cancelAction();
			}
		}.bindAsEventListener(this);
	}
	this.display();

	this.promptField.activate();
	return this;
}
ModalPrompt.prototype = new ModalBox;

function promoteFixedContainer() {
	var configBox = $('configure');
	if (!configBox) return;
	configBox.getElementsBySelector('input[type="submit"]').invoke('observe','click', function(evt) {
		Attachments.submitButtonName = Event.element(evt).name;
	});
}

function demoteFixedContainer() {
}

function fixCalendarEvents() {
}

function fixFormBuilderPopupMenu() {
}

function showReportOptions(hideContents) {
	$('reportTitleStatic').hide();
	var titleRename = $('reportTitleRename');
	titleRename.show();
	$('reportTitleTextInput').focus();
	if (fixIEMenus && !titleRename.down('iframe.reportTitleRenameFix')) {
		titleRename.innerHTML = '<iframe class="reportTitleRenameFix" src="/weblatest/blank.html" scrolling="no" frameborder="0" style="height: ' + titleRename.offsetHeight + 'px"></iframe>' + titleRename.innerHTML;
	}
}

function hideReportOptions() {
	$('reportTitleStatic').show();
	$('reportTitleRename').hide();
}

function showAlertBox(hideContents) {
	if (hideContents) {
		$("reportContents").hide();
	}
	$("activateAlertBox").show();
}

function hideAlertBox() {
	$("reportContents").show();
	$("activateAlertBox").hide();
}

function reportTitleNameHandler() {
	var reportTitleText = $('reportTitleTextInput');
	var reportTitleButton = $('reportTitleAcceptButton');
	var reportTitleIsValid = !(disallowedReportNames.any(function (name) { return name == reportTitleText.value; }));
	reportTitleButton.disabled = (reportTitleText.value.length == 0);
	reportTitleIsValid ? $('reportTitleWarning').hide() : $('reportTitleWarning').show();
	reportTitleButton.disabled = !(reportTitleIsValid && reportTitleText.value.length > 0);
}

function removeHiddenBox(box) {
  $("configure").removeChild($(box));
  demoteFixedContainer();
}

function splitFieldWithTextIntoTwoFields(originalValue, splitText, container1, container2) {
	if (!originalValue || originalValue == undefined) {
		container1.innerHTML = container2.innerHTML = '';
	} else if (splitText == '') {
		container1.innerHTML = originalValue;
		container2.innerHTML = '';
		return;
	} else {
		var splitValues = originalValue.split(splitText);
		container1.innerHTML = splitValues[0].replace(/ /g,'&nbsp;');
		container2.innerHTML = '';
		for (var i = 1, j = splitValues.length; i < j; i++) {
			container2.innerHTML += splitValues[i].replace(/ /g,'&nbsp;');
			if (i + 1 < j) {
				container2.innerHTML += splitText.replace(/ /g,'&nbsp;');
			}
		}
	}
}

function systemIsBusy() {
	if (numberOfOpenAjaxRequests > 0) {
		if (!systemIsBusyAlert) {
			systemIsBusyAlert = new ModalAlert('The system is transferring data. Please wait a moment and try again.');
		}
		window.setTimeout(systemIsBusy, 1500);
	} else if (systemIsBusyAlert) {
		systemIsBusyAlert.hiddenBox.remove();
		demoteFixedContainer();
		systemIsBusyAlert = null;
	}
}

// Check global mouse clicks to release popped menus and check for shift key where necessary

function clickHandler(event) {
	var targ = Event.element(event);
	if (targ) {
		if (numberOfOpenAjaxRequests > 0 && targ.getNodeName() == 'a' && targ.href != 'javascript:void(0)') {
			Event.stop(event);
			systemIsBusy();
		}
		if (targ.hasClassName("noClickThrough") || targ.up('.noClickThrough')) {
			return true;
		}
	}
	if (oldMenuItem && oldMenuItem.visible() && menuResetTimerActive === false) {
		oldMenuItem.hide();
		menuResetTimerActive = true;
		menuResetTimerID = window.setTimeout("menuResetTimerActive = false", 50);
	}
}

function shiftClickHandler(event) {
	if (!event.shiftKey) return;
	var targ = Event.element(event);
	if (!targ) return;
	var linkSibling = targ.next();
	var href;
	if (linkSibling) {
		href = linkSibling.readAttribute('href');
	}
	if (targ.hasClassName("checkShift")) {
	// If the shift key was pressed, look for the adjacent link and use its href that instead
		if (linkSibling && href) {
			Event.stop(event);
			if (linkSibling.onclick) {
				targ.nextSibling.onclick();
			}
			if (numberOfOpenAjaxRequests > 0) {
				systemIsBusy();
			} else {
				window.location = href;
			}
			return false;
		} else {
			return true;
		}
	}
}

// For database import, find <select>s and add onchange handler
function handleImportFields(classPrefix) {
  $$("select." + classPrefix).each(function (selector) {
    selector.onchange = function () {
      var attachedField = $(this.id.match(/column\d+/) + "NewField");
      if (this.selectedIndex == this.options.length - 1) {
        attachedField.visibilize();
        attachedField.focus();
      } else {
        //attachedField.invisibilize();
        document.confirmationForm.submit();
      }
    };
  });
}

function camelcase( s ) { 
	s = s.strip();
	return ( /\S[A-Z]/.test( s ) ) ? s.replace( /(.)([A-Z])/g, function(t,a,b) { return a + ' ' + b.toLowerCase(); } ) : s.replace( /( )([a-z])/g, function(t,a,b) { return b.toUpperCase(); } );
}  

String.prototype.camelCase = function() { 
	var s = this.strip();  
	return ( /\S[A-Z]/.test( s ) ) ? s.replace( /(.)([A-Z])/g, function(t,a,b) { return a + ' ' + b.toLowerCase(); } ) : s.replace( /( )([a-z])/g, function(t,a,b) { return b.toUpperCase(); } ); 
}

function capitalizeField(aString) {
	var list = aString.camelCase().split(" ");
	var max = list.length;
	for (var i = 0; i < max; i++) {
		list[i] = list[i].split("_");
	}
	list = list.flatten();
	max = list.length; 
	for (var i = 0; i < max; i++) {
		list[i] = list[i].capitalize();
	} 
	return list.join(" ");
}

function copyCellsToFormFields(targetPrefix, selectorPrefix, destinationPrefix) {
	var targetCells = $$("td." + targetPrefix);
	var selectors = $$("select." + selectorPrefix);
	var destinationFields = $$("input." + destinationPrefix);
	for (var i = 0, j = targetCells.length; i < j; i++) {
		var matchWithSelect = false;
		if (selectors[i]) {
			$A(selectors[i].options).each(function (option) {
				if (option.text == targetCells[i].innerHTML) {
					option.selected = true;
					destinationFields[i].up().invisibilize();
					matchWithSelect = true;
					throw $break;
				}		
			});
		}
		if (!matchWithSelect) {
			if (selectors[i]) {
				$A(selectors[i].options).last().selected = true;
			}
			destinationFields[i].up().visibilize();
			destinationFields[i].value = capitalizeField(targetCells[i].innerHTML);
		} 
	}
	return true;
}

// Match search to field names and offer to add filter
function filterSearchHandler(event) {
	if (filterSearchTimer != null) {
		window.clearTimeout(filterSearchTimer);
	}
	filterSearchTimer = window.setTimeout("filterSearchParser()",50);
}

function filterSearchParser(value) {
	var filterSearchResults = $("filterSearchResults");
	var filterSearchBox = $("addFilterSearch");

	if (!filterSearchResults || !filterSearchBox || !validFieldNames) return false;

	filterSearchResults.innerHTML = "";
	filterSearchBox.onkeypress = null;

	var value = filterSearchBox.value.replace(/\s+/g, ' ');
	var parsedValue = value.match(/((.+):\s*)*(.*)/i);
	var fieldName = parsedValue[2];
	var filterValue = parsedValue[3];
	var numberOfMatches = 0;

	if (!fieldName && filterValue) {
		fieldName = filterValue;
		filterValue = "";
	}
	
	function rejectEnterKey(e) {
		var code;
		e = e || window.event;
		code = e.keyCode || e.which;
		return (code != 13);
	}

	function addThisValueAsPossibility(key) {
		var addFilterLink = '<div class="reportFilter"><input type="submit" name="' + key + '" value="Filter" class="formButton" /><div class="filterDescription"><span class="icon field">' + validFieldNames[key] + '</span>';
		if (filterValue) {
			addFilterLink += '&nbsp;is&nbsp;' + filterValue;
		}
		addFilterLink += '</div><div class="clear">&nbsp;</div></div>';
		filterSearchResults.innerHTML += addFilterLink;
	}

	for (fieldKey in validFieldNames) {
		if (!value || !fieldName) return false;
		var actualFieldName = validFieldNames[fieldKey].toLowerCase().replace(/\s+/g, ' ');
		if (fieldName.length > 2) {
			if (actualFieldName.indexOf(fieldName.toLowerCase()) != -1) {
				addThisValueAsPossibility(fieldKey);
				numberOfMatches++;
			}
		} else {
			if (fieldName.toLowerCase() == actualFieldName) {
				addThisValueAsPossibility(fieldKey);			
				numberOfMatches++;
			}
		}
	}
	
	if (numberOfMatches > 0) {
		filterSearchBox.onkeypress = rejectEnterKey;
	}
}

ClickEditTable = {
	mouseHasMoved: false,
	uncheckAll: function() {
		this.checkboxes.each(function (checkbox) {
			checkbox.checked = false;
		});
		this.actionMenuControl();
		return false;
	},
	checkAll: function() {
		this.checkboxes.each(function (checkbox) {
			checkbox.checked = true;
		});
		this.actionMenuControl();
		return false;
	},
	actionMenuControl: function() {
		if (this.checkboxes.findAll(function (c) { return c.checked; }).size() > 0) {
			$("actionMenuChecked").show();
			$("actionMenuAll").hide(); 
		} else {
			$("actionMenuAll").show();
			$("actionMenuChecked").hide();
		}  
	},
	highlightRow: function(event) {
		var targ;
		event = event || window.event;
		targ = $(event.target || event.srcElement);
		if (!targ.nodeNameMatches(['input','select','option','textarea','label']) && !targ.hasClassName('reportTableObjectCheck') && !targ.hasClassName('encryptedDisplayValue') && !targ.down('input') && !targ.down('select')) {
			if (targ.getNodeName() != 'tr') {
				targ = targ.up('tr');
				if (targ.up('table').hasClassName('objectFieldValueControls')) return;
			}
			targ.addClassName('clickRowHover');
		}
	},
	unhighlightRow: function(event) {
		var targ;
		event = event || window.event;
		targ = $(event.target || event.srcElement);
		while (targ && targ.getNodeName() != 'tr' && !targ.hasClassName('entryRow')) {
			targ = $(targ.parentNode);
		}
		if (targ) {
			targ.removeClassName('clickRowHover');
		}
	},
	mouseMoved: function() {
		this.mouseHasMoved = true;
	},
	mouseDownOnRow: function() {
		this.mouseHasMoved = false;
	},
	mouseUpOnRow: function(event) {
		if (this.mouseHasMoved) return;
		var targ = Event.element(event);
		if (targ && (!targ.nodeNameMatches(['a','input','select','option','textarea','label']) && !targ.hasClassName('reportTableObjectCheck') && !targ.hasClassName('encryptedDisplayValue') && !targ.down('input') && !targ.down('select'))) {
			if (targ.getNodeName() != 'tr') {
				targ = targ.up('tr.entryRow');
			}
			if (numberOfOpenAjaxRequests > 0) {
				systemIsBusy();
			} else {
				window.location = $('entry' + targ.id).href;
			}
		}
	},
	init: function() {
		var selectAll = $('reportTableObjectCheckbox');
		if (selectAll) {
			selectAll.observe('click', function() {
				ClickEditTable[selectAll.checked ? 'checkAll' : 'uncheckAll']();
			});
		}
		this.checkboxes = $$("input.entryCheckbox");
		this.checkboxes.invoke('observe', 'click', function() { ClickEditTable.actionMenuControl(); });
		this.rows = $$("tr.entryRow");
		this.rows.each(function(row) {
			row.observe('mouseover', ClickEditTable.highlightRow.bind(ClickEditTable));
			row.observe('mouseout', ClickEditTable.unhighlightRow.bind(ClickEditTable));
			row.observe('mousemove', ClickEditTable.mouseMoved.bind(ClickEditTable));
			row.observe('mousedown', ClickEditTable.mouseDownOnRow.bind(ClickEditTable));
			row.observe('mouseup', ClickEditTable.mouseUpOnRow.bindAsEventListener(ClickEditTable));
		});
		if ($("actionMenuAll")) {
			this.actionMenuControl();
		}
	}
};

// Function to reveal menu on rollover

function reveal(menuName) {
	menuName = $(menuName);
	var link = menuName.previous('a');
	if (!menuName.visible()) {
	  menuName.showBlock();
  	fixPositionOfMenuLeft(menuName);
  }
  if (link) {
  	link.addClassName('menuHover');
	}
	if (fixIEMenus && menuName.hasClassName('popMenuBox')) {
		fixOnePopMenu(menuName);
	}
  if (oldMenuItem && menuName === oldMenuItem && menuTimerActive) {
    window.clearTimeout(menuTimerID);
    menuTimerActive = false;
  } else if (oldMenuItem && menuName !== oldMenuItem) {
    if (menuTimerActive) {
    	window.clearTimeout(menuTimerID);
    }
    menuTimerActive = false;    
    oldMenuItem.hide();
  }
  oldMenuItem = menuName;

}

function concealAll() {
  if (menuTimerActive) {
    window.clearTimeout(menuTimerID);
    menuTimerActive = false;
  }
	if (oldMenuItem) {
		var link = oldMenuItem.previous('a');
		if (link) {
			link.removeClassName('menuHover');
		}
		menuTimerID = window.setTimeout(function() { oldMenuItem.hide(); }, 300);
		menuTimerActive = true;
	}
	
  return false;
}

function switchItems(itemToShow, itemToHide) {
  $(itemToShow).show();
  $(itemToHide).hide();
  return false;
}

function showItem(item) {
  $(item).show();
  return false;
}

function showVisibleItem(item) {
  $(item).visibilize();
  return false;
}

function hideItem(item) {
  $(item).hide();
  return false;
}

function hideVisibleItem(item) {
  $(item).invisibilize();
  return false;
}

SpinnerImage = {};

function preCacheSpinnerImage() {
	SpinnerImage = $E('img', {
		src: '/weblatest/images/spinner.gif',
		alt: 'Loading',
		width: '16',
		height: '16',
		border: '0'
	});
}

function showSpinnerMenu(item) {
	if (item.hasClassName('popMenuBox') && !item.hasClassName('objectAdderAutocompleteSearchResults') && item.empty()) {
		var popMenu = $E('ul.popMenu.popMenuLoading');
		var li = popMenu.appendChild($E('li'));
		var a = li.appendChild($E('a', { href: 'javascript:void(0)' }));
		var img = a.appendChild(SpinnerImage.cloneNode(true));
		item.appendChild(popMenu);
	}
}

function swapItem(item) {
  item = $(item);
	if (menuResetTimerActive === false || oldMenuItem !== item) {
		if (!item.visible()) {
			var popMenuButton;
			if (oldMenuItem) {
				popMenuButton = oldMenuItem.up('.popMenuButton');
				if (popMenuButton) {
					popMenuButton.removeClassName('temporaryOverlay');
				}
				oldMenuItem.hide();
			}

			window.setTimeout(function() { showSpinnerMenu(item) }, 500);

			item.showBlock();
			
			// If this is a column menu, add some window collision detection to make sure we don't scroll off
			if (item.hasClassName('columnToolsBox')) {
				fixPositionOfMenu(item);
			}

			// if IE6, then fix height of iframe inside container
			if (item.hasClassName('popMenuBox')) {
				if (fixIEMenus) {
					fixOnePopMenu(item);
				}
				if (Browser.name == 'Internet Explorer' && Browser.version <= 7) {
					popMenuButton = item.up('.popMenuButton');
					if (popMenuButton) {
						popMenuButton.addClassNameOnce('temporaryOverlay');
					}
				}
			}

			oldMenuItem = item;
			menuResetTimerActive = true;
			menuResetTimerID = window.setTimeout("menuResetTimerActive = false", 50);
		} else {
			item.hide();
			if (Browser.name == 'Internet Explorer' && item.hasClassName('popMenuBox')) {
				var popMenuButton = item.up('.popMenuButton');
				if (popMenuButton) popMenuButton.style.zIndex = '';
			}
		}
	}
  return false;
}

// Detect collisions of category menus with left edge and move menu over to compensate
function fixPositionOfMenuLeft(obj) {
	obj.setStyle({ right: "0" });
	var objectLeft = cumulativeOffset(obj)[0];
	if (objectLeft < 0) {
		obj.setStyle({ right: objectLeft + "px" });
	}
}

// Detect collisions with the edge of the window and move the menu over to compensate
function fixPositionOfMenu(obj) {
	obj.setStyle({ left: "-6px" });
	
	// IE7 screws up the meaning of offsetLeft, so we don't use the cumulative offset
	if (Browser.name == "Internet Explorer" && Browser.version == "7") {
		objectLeft = obj.offsetParent.offsetLeft;
	} else {
		objectLeft = cumulativeOffset(obj)[0];
	}

// if menu is too close to left edge, make it open to the right instead
	if (objectLeft < 100) {
		obj.removeClassName('right');
		obj.removeClassName('columnToolsBox');
	}
	
 	var positionOffset = objectLeft + obj.offsetWidth + 12 - document.documentElement.clientWidth;
// cross-browser scroll offset:
	positionOffset -= window.pageXOffset || document.documentElement.scrollLeft;
	
	if (positionOffset > 0) {
		obj.setStyle({ left: 0 - positionOffset + "px" });
	}
}

// Register buttons on the page for highlighting/timing purposes
// Deprecated... now just returns a Prototype-extended element
function buttonRecord(id, bg) {
  return $(id);
}

Attachments = {
	strings: {
		'uploadingFiles': 'Uploading files'
	},
	submitButtonName: '',
	buildUploadStatusBox: function() {
		if (!entryEditorForm) return;
		var attachmentStatusHTML = '<div class="hiddenBox" id="attachmentStatusBox" style="display: none">' +
			'<div class="popWindow"><table class="popWindowTable attachmentStatusTable"><thead><tr><th class="popWindowHeader">' +
			Attachments.strings['uploadingFiles'] + 
			'</th></tr></thead><tbody><tr><td><ul id="attachmentStatus"></ul>' +
			'<p><input type="button" value="Cancel" class="button formButton" onclick="Attachments.stopUploadsAndSubmit()" /></p>' +
			'</td></tr></tbody></table></div></div>';
		entryEditorForm.appendChild($E('div#configure2', { innerHTML: attachmentStatusHTML }));
	},
	startUploads: function() {
		if ($$('input[type="file"]').any(function (input) { return input.value })) {
			$('attachmentStatusBox').show();
			promoteFixedContainer();	
		}
	},
	submitIfFilesFinished: function(evt) {
		if (evt) Event.stop(evt);
		this.forceSubmit();
	},
	stopUploadsAndSubmit: function() {
		window.location.reload();
		$('attachmentStatusBox').hide();
		demoteFixedContainer();
	},
	forceSubmit: function() {
		if (this.submitButtonName != '') {
			entryEditorForm.appendChild($E('input', { type: 'hidden', name: this.submitButtonName, value: this.submitButtonName }));
		}
		entryEditorForm.submit();
	},
	add: function(container, callback) {
		if (!entryEditorForm) return;
		this.buildUploadStatusBox();
		var li = $E('li');
		li.appendChild(SpinnerImage.cloneNode(true));
		$('attachmentStatus').appendChild(li);
	}
};

function fadeIn(id, durationLength) {
	if (!durationLength) durationLength = 1;
	new Effect.Appear(id, {duration: durationLength, queue: 'end'});
}

function fadeOut(id, durationLength, callback) {
	if (!durationLength) durationLength = 0.4;
	if (callback) {
		new Effect.Fade(id, {duration: durationLength, queue: 'end', afterFinish: callback});
	} else {
		new Effect.Fade(id, {duration: durationLength, queue: 'end'});
	}
}

function highlight(id, durationLength) {
	if (!$(id)) return; // null check
	if (!durationLength) durationLength = 3;
	new Effect.Highlight(id, {duration: durationLength});
}

function rollDown(id, durationLength, callback) {
	if (!durationLength) durationLength = 0.4;
	if (callback) {
		new Effect.BlindDown(id, {duration: durationLength, queue: 'end', afterFinish: callback});
	} else {
		new Effect.BlindDown(id, {duration: durationLength, queue: 'end'});	
	}
}

function rollUp(id, durationLength, callback) {
	if (!durationLength) durationLength = 0.4;
	if (callback) {
		new Effect.BlindUp(id, {duration: durationLength, queue: 'end', afterFinish: callback});
	} else {
		new Effect.BlindUp(id, {duration: durationLength, queue: 'end'});
	}
}

function switchBoxesWithRoll(idToShow, idToHide, durationLength, callback) {
	if (!durationLength) durationLength = 0.5;
	if (callback) {
		new Effect.Parallel([
			new Effect.BlindDown(idToShow),
			new Effect.BlindUp(idToHide)
		], { duration: durationLength, afterFinish: callback });
	} else {
		new Effect.Parallel([
			new Effect.BlindDown(idToShow),
			new Effect.BlindUp(idToHide)
		], { duration: durationLength });	
	}
}

function serializeField(id) {
	return Form.Element.serialize(id);
}

function fixOnePopMenu(menu) { // used by IE6 and FF/Linux
	if (!fixIEMenus && Browser.OS != 'Linux') return;
 	menu = $(menu);
 	if (!menu || menu.empty()) {
 		return;
 	}
 	if (menu.firstChild.nodeName.toLowerCase() != 'iframe') {
 		var iframe = $E('iframe.popMenuFix');
 		iframe.src = "/weblatest/blank.html";
 		iframe.style.height = menu.firstChild.offsetHeight + "px";
 		iframe.setAttribute('scrolling', 'no');
 		iframe.setAttribute('frameborder', '0');
 		menu.insertBefore(iframe, menu.firstChild);
 		fixPopMenuChildren(menu);
 	}
   return true;
}

function fixPopMenuChildren(popMenuParent) {
	var listItems = popMenuParent.getElementsByTagName('li');
	for (var i = 0, j = listItems.length; i < j; i++) {
		var item = $(listItems[i]);
		if (item.hasClassName('popSubMenu')) {
	 		var iframe = '<iframe class="IEHoverFix" src="/weblatest/blank.html" scrolling="no" frameborder="0"></iframe>';
	 		item.innerHTML = iframe + item.innerHTML;
			item.onmouseover = popItemHover;
			item.onmouseout = popItemUnhover;
		}
	}
}

function popItemHover() {
	this.className += " showOnHover";
	this.firstChild.style.display = "block";
	this.firstChild.style.height = this.lastChild.offsetHeight + 'px';
}

function popItemUnhover() {
	this.className = this.className.replace(" showOnHover", "");
	this.firstChild.style.display = "none";
}

function postRequest(postData, updateID) {
	GlobalPageTimer.reset();
	if (updateID) {
		var callback = function() {};
		var box = $(updateID);
		if (box && box.hasClassName('popMenuBox') && !box.empty() && !box.down('.popMenuLoading')) {
			return; // do nothing if the box already has content
		}
		if (updateID == 'fieldConfigure') {
			callback = FieldTypes.getFieldConfigureCallback();
		}
		new Ajax.Updater(updateID, document.location.pathname, {
			parameters: postData,
 			evalScripts: true,
 			onComplete: callback
		});
		if (updateID == 'configure') {
			promoteFixedContainer();
		}
	}	else {
		numberOfOpenAjaxRequests++;
		new Ajax.Request(document.location.pathname, {
			parameters: postData,
			onComplete: function() {
				numberOfOpenAjaxRequests--;
			}
		});
	}
}

function submitFieldAndUpdate(fieldID, updateID, callbackID) {
	var postData = "_k=" + document.forms[0]["_k"].value + '&' + callbackID;
	if (fieldID) {
		var arrayOfFields = [];
		if (typeof fieldID == 'object' && fieldID.length) {
			arrayOfFields = fieldID;
		} else {
			arrayOfFields[0] = fieldID;
		}
		for (var i = 0, numFields = arrayOfFields.length; i < numFields; i++ ) {
			postData += "&" + serializeField(arrayOfFields[i]);
		}
	}
	postRequest(postData, updateID);
}

function submitFormAndUpdate(formName, updateID, callbackID) {
	var postData = Form.serializeElements($(document.forms[formName]).getUsefulElements()) + '&' + callbackID;
	postRequest(postData, updateID);
}

FieldTypes = {
	currentType: null,
	show: function(fieldTypeToShow) {
		var label, container;
		if (this.currentType && this.currentType.toLowerCase() != fieldTypeToShow.toLowerCase()) {
			container = $('fieldTypeOptions' + this.currentType.capitalize());
			if (container) {
				this.deactivateContainer(container);
			}
			label = $('fieldType' + this.currentType.capitalize() + 'Label');
			if (label) label.removeClassName('selectedFieldType');
		}
		this.currentType = fieldTypeToShow.capitalize();
		container = $('fieldTypeOptions' + this.currentType);
		if (container) {
			this.activateContainer(container);
		}
		label = $('fieldType' + this.currentType + 'Label');
		if (label) label.addClassName('selectedFieldType');
		this.showFieldOptions();
		return true;
	},
	deactivateContainer: function(container) {
		container.removeClassName('activeFieldTypeOptionsBox');
		container.hide();	
	},
	activateContainer: function(container) {
		container.addClassNameOnce('activeFieldTypeOptionsBox');
		container.showBlock();
	},
	showFieldOptions: function() {
		switchItems('fieldValueOptionsBox', 'fieldValueTypeBox');
	},
	showFieldTypes: function() {
		switchItems('fieldValueTypeBox', 'fieldValueOptionsBox');
	},
	getFieldConfigureCallback: function() {
		var fieldInputs = {};
		var fieldValues = {};
		fieldInputs.name = getSingleElementFromSelector('#fieldConfigureName input');
		fieldInputs.category = getSingleElementFromSelector('#fieldConfigureCategory select');
		fieldInputs.note = getSingleElementFromSelector('#fieldConfigureNote input');
		for (var p in fieldInputs) {
			var target = fieldInputs[p];
			var original = fieldValues[p] = {};
			if (target) {
				if (target.getNodeName() == 'input') {
					original.value = target.value;
					original.color = target.style.color;
				} else if (target.getNodeName() == 'select') {
					original.index = target.selectedIndex;
				}
			}
		}
		return function() {
			if (fixIEMenus && Browser.name == 'Internet Explorer') {
				putContainerOnTop();
			}
			fieldInputs.name = getSingleElementFromSelector('#fieldConfigureName input');
			fieldInputs.category = getSingleElementFromSelector('#fieldConfigureCategory select');
			fieldInputs.note = getSingleElementFromSelector('#fieldConfigureNote input');
			for (var p in fieldInputs) {
				var target = fieldInputs[p];
				var original = fieldValues[p];
				if (target && original) {
					if (target.getNodeName() == 'input') {
						target.value = original.value;
						target.style.color = original.color;
					} else if (target.getNodeName() == 'select') {
						target.selectedIndex = original.index;
					}
				}
			}
		};	
	}
};

function collectEntryNameSnippets(className) {
	return $$('.' + className).collect(function(snippet) {
		return (snippet.getNodeName() == 'select') ? snippet.options[snippet.selectedIndex].innerHTML : snippet.value;
	}).join('').replace('&','&amp;').replace('<','&lt;').replace('>','&gt;');
}

function selectedTagChanged() {
	var updateTagNamePreview = function(newTagName, existingTagName) {
		if (existingTagName && existingTagName.selectedIndex == existingTagName.length - 1) {
			if (!newTagName.visible()) {
				newTagName.show();
			}
		} else {
			if (newTagName) {
				newTagName.hide();
			}
		}
	};
	
	updateTagNamePreview($('newTagOptionMultiple'), $('existingTagOptionMultiple'));
	updateTagNamePreview($('newTagOptionObject'), $('existingTagOptionObject'));
}

CategoryMenu = {
	adminWidth: 0,
	redrawTimer: null,
	setAvailWidth: function() {
		this.availWidth = this.categoryMenu.getWidth() - this.adminWidth - 20;	
	},
	readjustCategoryMenu: function() {
		this.setAvailWidth();
		this.categoryMenuItems.invoke('invisibilize');
		this.categoryMenuItems.invoke('show');
		if (fixIEMenus) {
			var moreCatDivFirst = $("moreCategories").firstDescendant();
			if (moreCatDivFirst.getNodeName() == "iframe" && moreCatDivFirst.hasClassName("popMenuFix")) {
				moreCatDivFirst.remove();
			}
		}
		
		window.clearTimeout(this.redrawTimer);
		this.redrawTimer = window.setTimeout(function() { CategoryMenu.hideOverflowCategories() }, 75);
	},
	hideOverflowCategories: function() {
		var alreadyMovedMenu;
		var menuItem;
		for (var i = this.categoryMenuItems.length - 1; i >= 0; i--) {
			menuItem = this.categoryMenuItems[i];
			if (menuItem.id.indexOf("category") != -1) {
				alreadyMovedMenu = $(menuItem.id + "MovedToMenu");
				if (alreadyMovedMenu) {
					alreadyMovedMenu.hide();
				}
				if (this.categoryPositionWrong(menuItem)) {
					if (alreadyMovedMenu) {
						alreadyMovedMenu.show();
					} else {
						this.copyCategoryMenu(menuItem);
					}
					menuItem.hide();
				}
			}
		}
		this.categoryMenuItems.invoke('visibilize');
	},
	copyCategoryMenu: function(oldMenuItem) {
		var newMenuItem, newLink, newMenu;
		var catMenuLink = oldMenuItem.down('a');
		if (!catMenuLink) return false;
		var catMenuSubMenu = catMenuLink.next('div.popMenuBox').down('ul');
		if (!catMenuSubMenu) return false;
		
		newMenuItem = $E('li#' + oldMenuItem.id + 'MovedToMenu.popSubMenu');
		newLink = catMenuLink.cloneNode(true);
		newLink.className = 'subMenu';
		newLink.onmouseover = newLink.onmouseout = null;
		newMenu = catMenuSubMenu.cloneNode(true);
		newMenu.className = '';
		newMenuItem.appendChild(newLink);
		newMenuItem.appendChild(newMenu);
		this.moreCategoriesMenu.insertBefore(newMenuItem, this.moreCategoriesMenuInitialLastChild.nextSibling);
	},
	categoryPositionWrong: function(menuItem) {
		return (menuItem.offsetLeft + menuItem.offsetWidth > this.availWidth || menuItem.offsetTop > 0);
	},
	init: function() {
		this.categoryMenu = $("categoryMenu");
		this.moreCategoriesMenu = $("moreCategoriesMenu");
		if (!this.categoryMenu || !this.moreCategoriesMenu) return false;
		this.moreCategoriesMenuInitialLastChild = this.moreCategoriesMenu.lastChild;
		var menuItem;
		this.categoryMenuItems = this.categoryMenu.immediateDescendants();
		for (var i = this.categoryMenuItems.length - 1; i >= 0; i--) {
			menuItem = this.categoryMenuItems[i];
			if (menuItem.hasClassName("admin")) {
				this.adminWidth += menuItem.offsetWidth;
			}
		}
		this.setAvailWidth();
		for (var i = this.categoryMenuItems.length - 1; i >= 0; i--) {
			menuItem = this.categoryMenuItems[i];
			if (menuItem.id.indexOf("category") != -1) {
				if (this.categoryPositionWrong(menuItem)) {
					this.copyCategoryMenu(menuItem);
					menuItem.style.display = "none";
				}
			}
		}
			
		Event.observe(window, "resize", function() { CategoryMenu.readjustCategoryMenu(); });
	}
};

// Category menu layout
// If there are too many categories, shift them to the More menu
function CropCategoryMenu() {
	return this;
}

// Force Safari to accept clicks on labels for checkboxes and radio buttons
function switchToStyleSheet(id) {
	var sheet = $(id);
	sheet.disabled = true;
	sheet.disabled = false;
}

function fixExportScrollBox() {
	var box = $('exportScrollBox');
	var height = window.innerHeight || document.documentElement.clientHeight;
	var header = $('applicationTitleBox').up('.exportHeader');
	box.setStyle({ height: height - header.offsetHeight + "px" });
	if (Browser.name == "Internet Explorer" && Browser.version == "6") {
		if (box.offsetWidth > box.parentNode.offsetWidth) {
			box.setStyle({ width: box.parentNode.offsetWidth + "px" });
		} else {
			box.setStyle({ width: "100%" });
		}
	}
}

function submitFormTriggeringCallback(formName, callbackKey, value) {
	document.forms[formName].appendChild($E("input", { type: "hidden", name: callbackKey, value: value }));
	document.forms[formName].submit();
}

InitialSelectValues = {
	values: {},
	getValue: function(element) {
		if (element.id && element.id.indexOf('inputid') == 0) {
			InitialSelectValues.values[element.id] = element.value;
		}
	},
	init: function() {
		$$('.objectFieldValue select').each(InitialSelectValues.getValue);
		$$('.reportTableFieldValue select').each(InitialSelectValues.getValue);
	}
}

function chooseOther(select, hiddenId, p) {
	function failure() {
		for (var i = 0, numOptions = select.options.length; i < numOptions; i++) {
			if (select.options[i].value == InitialSelectValues.values[select.id]) {
				select.selectedIndex = i;
				break;
			}
		}
		if ($(select).up('.reportTableFieldValue')) { // submit ajax if we're in an edit column
			submitFieldAndUpdate(select.id, null, null);
		}
	}
	function success(value) {
		if (!value) {
			failure();
			return;
		}
		$(hiddenId).value = value;
		select.options[select.options.length-1].text = value;
		if ($(select).up('.reportTableFieldValue')) { // submit ajax if we're in an edit column
			submitFieldAndUpdate([select.id, hiddenId], null, null);
		}
	}
	new ModalPrompt(p, success, failure);
}

function matchCheckedStateWithInput(checkbox, inputID) {
	(checkbox.checked) ? $(inputID).enable().focus() : $(inputID).disable();
}

function enableChoice(enableID, disableID) {
	$(enableID).disabled = false;
	$(disableID).disabled = true;
}

function alternateTips() {
	tipBoxes.each(function (tipBox) {
		if (!tipBox.visible()) {
			rollDown(tipBox, .2);
		}
	});
	window.setTimeout(hideCompletedTips, 500);
}

function hideCompletedTips() {
	tipBoxes.each(function (tipBox) {
		var completedTips = tipBox.down('.completedTips');
		if (completedTips) {
			fadeOut(completedTips, 1.0, function() {
				completedTips.immediateDescendants().invoke('hide');
				if (!tipBox.down('.newTips')) {
					hideTipBoxIfEmpty(tipBox);
				}
			});
		}
	});
	window.setTimeout(showNewTips, 1000);
}

function showNewTips() {
	tipBoxes.each(function (tipBox) {
		var newTips = tipBox.down('.newTips');
		if (newTips && !newTips.visible()) {
			rollDown(newTips, .3);
		}
	});
}

function hideTip(event) {
	Event.stop(event);
	var link = Event.element(event);
	var tip = link.up('p');
	var tipBox = tip.up('.tip');
	GlobalPageTimer.reset();
	new Ajax.Request(link.href);
	rollUp(tip, 0.2, function() {	hideTipBoxIfEmpty(tipBox); });
}

function hideAllTips(event) {
	Event.stop(event);
	var link = Event.element(event);
	GlobalPageTimer.reset();
	new Ajax.Request(link.href);
	link.up('p').hide();
	$$('div.tip').each(function (div) {
		rollUp(div, 0.2);
	})
}

function hideTipBoxIfEmpty(tipBox) {
	if (tipBox.getElementsBySelector('p').all(function (eachTip) { return !eachTip.visible(); })) {
		rollUp(tipBox, 0.2);
	}
}

UpgradeAccount = {
	errors: {
		notEnoughUsers: function() { return 'Your account can not have fewer than ' + UpgradeAccount.minUsers + (UpgradeAccount.minUsers > 1 ? ' users.' : ' user.'); },
		notEnoughStorage: function() { return 'You cannot subscribe to a plan with less storage than currently in use.'; }
	},
	minUsers: 0,
	minStorage: 0,
	userUnitPrice: 8,
	storageUnitPrice: 2,
	storagePerUser: 0.25,
	customDomainPrice: 0,
	restrictAccessPrice: 0,
	update: function(event) {
		var userInput = $('addUsersInput');
		var storageSelect = $('addStorageSelect');
		var storageQuota = $('includedStorageQuota');
		var total = $('addExtraTotal');
		var updatePlanButton = $('updatePlanButton');
		window.setTimeout(function() {
			var errorMessages = [];
			var numberOfUsers = parseInt(userInput.value, 10);
			numberOfUsers = (isNaN(numberOfUsers) || numberOfUsers < 0) ? 0 : numberOfUsers;
			
			if (numberOfUsers < UpgradeAccount.minUsers) {
				errorMessages[errorMessages.length] = UpgradeAccount.errors.notEnoughUsers();
				numberOfUsers = UpgradeAccount.minUsers;
				userInput.addClassName('error');
			} else {
				userInput.removeClassName('error');
			}
			
			var addStorageAmount = storageSelect.options[storageSelect.selectedIndex].id.replace(/addStorage/, '');
			addStorageAmount = parseInt(addStorageAmount, 10);
			
			var includedStorage = numberOfUsers * UpgradeAccount.storagePerUser;
			var totalStorage = includedStorage + addStorageAmount;
			
			if (totalStorage < UpgradeAccount.minStorage) {
				errorMessages[errorMessages.length] = UpgradeAccount.errors.notEnoughStorage();
			}
			
			var userPrice = numberOfUsers * UpgradeAccount.userUnitPrice;
			var addStoragePrice = addStorageAmount * UpgradeAccount.storageUnitPrice;
			var totalPrice = userPrice + addStoragePrice;
			
			storageQuota.update(includedStorage + ' GB');
			totalPrice += UpgradeAccount.customDomainPrice + UpgradeAccount.restrictAccessPrice;
			
			total.update('New total: $' + totalPrice);
			total.addClassNameOnce('newAddExtraTotal');
			UpgradeAccount.error(errorMessages);
			updatePlanButton.disabled = errorMessages.length ? true : false;
		}, 100);
	},
	error: function(messages) {
		var errorBox = $('upgradeError');
		if (messages.length) {
			errorBox.update();
			messages.each(function(m) { errorBox.insert($E('p', { innerHTML: m })); });
			if (!errorBox.visible()) {
				errorBox.blindDown({ duration: .3, queue: 'end' });
			}
		} else if (errorBox.visible()) {
			errorBox.blindUp({ duration: .1, queue: 'end' });
		}
	},
	updateUsers: function(event) {
		var input = Event.element(event);
	},
	updateStorage: function(event) {
		var select = Event.element(event);
	}
};

HotkeyElement = function(element) {
	this.element = element;
	this.key = element.getAttribute('accesskey').toLowerCase();
	if (this.key) {
		element.removeAttribute('accesskey');
		if (element.accessKey) {
			element.accessKey = null;
		}
		Event.observe(document, 'keyup', this.eventHandler.bindAsEventListener(this));
	}
};

HotkeyElement.prototype.eventHandler = function(event) {
	var keyPressed = String.fromCharCode(event.which || event.keyCode).toLowerCase();
	if (keyPressed == this.key && event.altKey && event.ctrlKey && !event.shiftKey) {
		Event.stop(event);
		this.fire();
	}
};

HotkeyElement.prototype.fire = function() {
	if (this.element.getNodeName() == 'input' && this.element.type == 'submit') {
		this.element.addClassNameOnce('activeButton');
		submitFormTriggeringCallback(this.element.form.name, this.element.name, '');
	} else if (this.element.getNodeName() == 'a') {
		this.element.addClassNameOnce('activeLink');
		var href = this.element.href;
		if (href) {
			window.location = href;
		}
	}
};

Hotkeys = {
	init: function() {
		var elements = $$('input[accesskey]', 'a[accesskey]');
		var isIE = false;
		elements.each(function(element) {
			if (element.accessKey) {
				isIE = true;
			}
			new HotkeyElement(element);
		});
		if (elements.length === 0 || !entryEditorForm || (Browser.name == 'Safari' && Browser.safariVersion >= 4)) {
			return;
		}
		var oldAccessKeyButton = new Element('input', { 'id': 'shortcutKeysButton', 'class': 'button', 'type': 'button' });
		oldAccessKeyButton.setAttribute(isIE ? 'accessKey' : 'accesskey', 's');
		entryEditorForm.appendChild(oldAccessKeyButton);
		oldAccessKeyButton.observe('click', function() {
			window.open('/errorpages/shortcutkeys.html', 'shortcutKeys', 'width=550,height=400,resizable=yes,scrollbars=yes');
		});
	}
};

Browser = {
	name: '',
	version: '',
	fullVersion: '',
	safariVersion: 0,
	OS: '',
	flashVersion: '',
	versionLocationInString: 8,
	agentString: navigator.userAgent.toLowerCase(),
	browserStrings: {
		'konqueror': "Konqueror",
		'webkit': "Safari",
		'omniweb': "OmniWeb",
		'opera': "Opera",
		'webtv': "WebTV",
		'icab': "iCab",
		'msie': "Internet Explorer",
		'firefox': "Firefox"
	},
	OSStrings: {
		'linux': "Linux",
		'x11': "Unix",
		'mac': "Mac",
		'win': "Windows"
	},
	findOS: function() {
		for (s in this.OSStrings) {
			var index = this.agentString.indexOf(s);
			if (index != -1) {
				this.OS = this.OSStrings[s];
				return;
			}
		}
		this.OS = "An unknown operating system";
		return;
	},
	getFlashVersionFromIE: function() {
		var version = -1;
		var versionMatch;
		var versionInfo = ["", "", "", ""];
		var axo, e;
		try {
			axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
			version = axo.GetVariable("$version");
			versionMatch = version.match(/WIN (\d*)\,(\d*)\,(\d*).*/);
			versionInfo = [versionMatch[1], versionMatch[2], versionMatch[3]];
		} catch (e) {}
		return versionInfo;
	},
	getFlashVersion: function() {
		var flashVer = -1;
		
		if (navigator.plugins != null && navigator.plugins.length > 0) {
			if (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]) {
				var swVer2 = navigator.plugins["Shockwave Flash 2.0"] ? " 2.0" : "";
				var flashDescription = navigator.plugins["Shockwave Flash" + swVer2].description;			
				var descArray = flashDescription.split(" ");
				var tempArrayMajor = descArray[2].split(".");
				var versionMajor = tempArrayMajor[0];
				var versionMinor = tempArrayMajor[1];
				if ( descArray[3] != "" ) {
					tempArrayMinor = descArray[3].split("r");
				} else {
					tempArrayMinor = descArray[4].split("r");
				}
				var versionRevision = tempArrayMinor[1] > 0 ? tempArrayMinor[1] : 0;
				var flashVer = [versionMajor, versionMinor, versionRevision];
			}
		}	else if (this.name == "Internet Explorer" && this.OS == "Windows") {
			flashVer = this.getFlashVersionFromIE();
		}	
		return flashVer;
	},
	getSafariVersion: function() {
		var versionArray = Browser.fullVersion.split('.');
		if (versionArray.length > 0) {
			var safariBuild = parseInt(versionArray[0], 10);
			if (isNaN(this.safariVersion)) {
				this.safariVersion = 0;
			} else if (safariBuild >= 526) {
				this.safariVersion = 4;
			} else if (safariBuild >= 522) {
				this.safariVersion = 3;
			} else if (safariBuild >= 412) {
				this.safariVersion = 2;
			} else {
				this.safariVersion = 1;
			}
		}
	},
	detect: function() {
		for (s in this.browserStrings) {
			var index = this.agentString.indexOf(s);
			if (index != -1) {
				this.name = this.browserStrings[s];
				var versionIndex = index + s.length + 1;
				this.version = this.agentString.charAt(versionIndex);
				this.fullVersion = this.agentString.substr(versionIndex).match(/^([\d.]+)/)[1];
				if (this.name == 'Safari') {
					this.getSafariVersion();
				}
				this.findOS();
				this.flashVersion = this.getFlashVersion();
				return;
			}			
		}
		
		if (this.agentString.indexOf('compatible') == -1) {
			this.name = "Netscape Navigator";
			this.version = this.agentString.charAt(8);
		} else {
			this.name = "An unknown browser";
		}
		
		this.findOS();
		
		this.flashVersion = this.getFlashVersion();
		
		return;
	}
};

Browser.detect();

if (Browser.OS == 'Linux') {
	fixIEMenus = true;
}

function findTagWithPrefix(tag, className) {
	return $$(tag + '.' + className);
}

function addEvent( obj, type, fn ) {
	Event.observe(obj, type, fn);
}

function removeEvent( obj, type, fn ) {
	Event.stopObserving(obj, type, fn);
}

function stopEvent(event) {
	if (event) {
		if (event.stopPropagation) {
		// this code is for Mozilla and Opera
			event.preventDefault();
			event.stopPropagation();
		} else if (window.event) {
		// this code is for IE
			window.event.cancelBubble = true;
		}
	}
}

Element.addMethods({
	showBlock: function(element) {
		element.setStyle({ display: 'block' });
	},
	showInline: function(element) {
		element.setStyle({ display: 'inline' });
	},
	visibilize: function(element) {
		element.setStyle({ visibility: 'visible' });
	},
	invisibilize: function(element) {
		element.setStyle({ visibility: 'hidden' });
	},
	append: function(element, content) {
		element.update(element.innerHTML + content);
	},
	fire: function(element) {
		var bgColor = '#F45D21';
		bgColor = '#FFDB38';
		element.setStyle({ backgroundColor: bgColor });
	},
	extinguish: function(element) {
		element.setStyle({ backgroundColor: '' });
	},
	toggleChecked: function(element, flag) {
		element.checked = (flag === true || flag === false) ? flag : !element.checked;
	},
	getNodeName: function(element) {
		return element.nodeName.toLowerCase();
	},
	nodeNameMatches: function(element, array) {
		return $A(array).any(function (t) {
			return element.getNodeName() == t;
		});
	},
	getUsefulElements: function(element) {
		if (element.getNodeName() != 'form') return null;
		var allFormElements = element.getElements();
		var usefulFormElements = [];
		for (var i = 0, j = allFormElements.length; i < j; i++) {
			var el = $(allFormElements[i]);
			if (el.getNodeName() != 'input' || (el.getNodeName() == 'input' && el.type != 'submit' && el.type != 'button' && el.type != 'img' && el.type != 'reset')) {
				usefulFormElements.push(el);
			}
		}
		return usefulFormElements;
	},
	addClassNameOnce: function(element, className) {
		if (element.hasClassName(className)) return;
		element.addClassName(className);
	}
});

function getSingleElementFromSelector(selector) {
	var array = $$(selector);
	if (array.length > 0) {
		return array[0];
	} else {
		return null;
	}
}

// Element builder with support for classes and IDs using CSS style selectors
function $E(tag, attributes) {
	var tagComponents = tag.match(/([A-Za-z]+[0-9]*)([\.\#]?.*)/);
	var tagName = tagComponents[1];
	var selectors = tagComponents[2];
	var classes = [];
	var id = '';
	if (selectors) {
		classes = selectors.split('.');
		for (var i = classes.length - 1; i >= 0; i--) {
			var possibleIDs = classes[i].match(/(.*)\#(.+)/);
			if (possibleIDs && possibleIDs.length > 1) {
				id = possibleIDs[2];
				classes[i] = possibleIDs[1];
			}
		}
	}
	var element = $(document.createElement(tagName));
	if (classes.length >= 1) {
		element.className = classes.join(' ');
	}
	if (id) {
		element.id = id;
	}
	for (a in attributes) {
		element[a] = attributes[a];
	}
	return element;
}

// dummy function
function SWFObject() {
	this.write = function() {};
	return this;
}

// Create a console object if undefined to prevent errors from debugging code left in
if (typeof(console) == 'undefined') {
	console = {
		log: function() {},
		dir: function() {}
	};
}
