
function initStartContentBox(part) {
	var i, sec = 'ne';
	for(i = 2; i <=4 ; i++) {
		document.getElementById('container_newest_offers_'+i).style.display = '' + part + sec;
	}
}


function showTabbedContentBox(container,hideId,showId) {
	if(hideId != showId) {
		document.getElementById(container+hideId).style.display = 'none';
		document.getElementById(container+showId).style.display = 'block';
	}
}


function setSecurityToken( token ) {
	if( token != null ) {
		var el = document.getElementById("ajaxSecurityToken");
		if( el != null ) {
			el.value = token;
		}
	}
}

function getSecurityToken() {
	var el = document.getElementById("ajaxSecurityToken");
	if( el != null ) {
		return el.value;
	}
	return "";
}

function toogleMultipleAddressesBox() {
	var checked = document.getElementById("edit_multipleAddresses0").checked;
	if(checked) {
		document.getElementById("multipleAddressesBox").style.display = 'block';
	} else {
		document.getElementById("multipleAddressesBox").style.display = 'none';
	}
}




function showFastSearchBox() {
	document.getElementById("super_search_box_open").style.display = 'none';
	document.getElementById("fast_search_box_open").style.display = 'block';
	document.getElementById("fast1").checked = true;
}

function showSuperSearchBox() {
	document.getElementById("fast_search_box_open").style.display = 'none';
	document.getElementById("super_search_box_open").style.display = 'block';
	document.getElementById("fast1").checked = false;
}





function toggleBoxDisplay(showId, hideId) {
	if( hideId ) {
		document.getElementById(hideId).style.display = 'none';
	}
	if( showId ) {
		document.getElementById(showId).style.display = 'block';
	}
}







function showCVContentinProfile(id) {
	var i, child, el = document.getElementById("CVTabs");
	for(i = 0; i < el.childNodes.length; i++) {
		child = el.childNodes[ i ];
		if( child.nodeName.toUpperCase() == "LI" ) {
			child.className = 'none';
		}
	}
	document.getElementById("CVHeadinginProfile"+id).className = 'active_cv';

	el = document.getElementById("CVContentinProfileContainer");
	for(i = 0; i < el.childNodes.length; i++) {
		child = el.childNodes[ i ];
		if( child.nodeName.toUpperCase() == "DIV" ) {
			child.style.display = 'none';
		}
	}
	document.getElementById("CVContentinProfile"+id).style.display = 'block';
}



function setStateList( country, language, selectBoxId, selectedValue, isKeyValue, addDefaultOption ) {
	setDynamicList( "state", country, language, selectBoxId, selectedValue, isKeyValue, addDefaultOption );
}

function setSectorList( sector, language, selectBoxId, selectedValue, isKeyValue, addDefaultOption ) {
	setDynamicList( "sector", sector, language, selectBoxId, selectedValue, isKeyValue, addDefaultOption );
}

function setDynamicList( namespace, parentList, language, selectBoxId, selectedValue, isKeyValue, addDefaultOption ) {
	if(parentList==null || parentList=="0") {
		dwr.util.removeAllOptions(selectBoxId);
		addDefaultOptionToSelectBox(selectBoxId);
	} else {
		dojo.xhrGet({
			url: "/json/"+namespace+"/"+language+"-"+parentList+".txt",
			handleAs: "json",
			timeout: 3000,
			load: function(response, ioArgs) {
				dwr.util.removeAllOptions(selectBoxId);
				if(addDefaultOption) {
					addDefaultOptionToSelectBox(selectBoxId);
				}
				if(!addDefaultOption || response.length>1) {
					dwr.util.addOptions(selectBoxId, response, 'code', 'label');
				}
				
				if(isKeyValue) {
					if(selectedValue!=null && selectedValue>0) {
						dojo.byId(selectBoxId).value = selectedValue;
					}
				} else {
					var i, options = dojo.byId(selectBoxId).options;
					for(i=0; i<options.length; i++) {
						if(options[i].text == selectedValue) {
							dojo.byId(selectBoxId).selectedIndex = i;
							break;
						}
					}
				}
				
			},
			error: function(response, ioArgs) {
				// returns 301 cuz of redirect to error.html
				//if(response.status=='404') {
					dwr.util.removeAllOptions(selectBoxId);
					if(addDefaultOption) {
						addDefaultOptionToSelectBox(selectBoxId);
					} else {
						addEmptyOptionToSelectBox(selectBoxId);
					}
				//}
			}
		});
	}
}




function addDefaultOptionToSelectBox(selectBoxId) {
	var optionText = document.createTextNode( getLocalizedString('js.domain.helper.SELECTBOX.option.all') ),
		option = document.createElement("option");
	option.setAttribute("value", "0");
	option.appendChild(optionText);
	document.getElementById(selectBoxId).appendChild(option);
}

function addEmptyOptionToSelectBox(selectBoxId) {
	var optionText = document.createTextNode('-'),
		option = document.createElement("option");
	option.setAttribute("value", "0");
	option.appendChild(optionText);
	document.getElementById(selectBoxId).appendChild(option);
}





function showJobTypeOptions(jobTypeId) {
	for(var i = 0; i < 5; i++) {
		document.getElementById("job_type_options_"+i).style.display = 'none';
	}
	document.getElementById("job_type_options_"+jobTypeId).style.display = 'block';
}






function initializeGMap() {
	if (GBrowserIsCompatible()) {
		gmap = new GMap2(document.getElementById("gmap_canvas"));
		gmap.setUIToDefault();
	}
}

function showAddressInGMap(address) {
	var marker,
		geocoder = new GClientGeocoder();
	geocoder.getLatLng(
		address,
		function(point) {
			gmap.setCenter(point, 13);
			marker = new GMarker(point);
			gmap.addOverlay(marker);
			GEvent.addListener(marker, "click", function() {
				marker.openInfoWindowHtml(address);
			});
		}
	);
}







function getLocalizedString(key) {
	var result = localizedJSStrings[key];
	if(!result) {
		result = "-";
	}
	return result;
}




















function getFavoriteEntity(id, rating, includedName) {
	var obj = {}, form = {};
	obj['id'] = id;
	form[includedName] = obj;
	form['rating'] = rating;
	return form;
}


function closeFavoriteJobOfferActionBox(){
	var i, el, elError;
	for(i=2; i<=9; i++) {
		el = document.getElementById('FavoriteJobOfferActionBox'+i);
		if( el != null ) {
			el.style.display = 'none';
		}
	}
	elError = document.getElementById('applicationform_error');
	if( elError != null ) {
		elError.style.display = 'none';
	}
	document.getElementById('FavoriteJobOfferActionBox1').style.display = 'block';
}

function setAsFavoriteJobOffer(id, loggedIn) {
	document.getElementById('FavoriteJobOfferActionBox1').style.display = 'none';
	if(loggedIn==1) {
		document.getElementById('FavoriteJobOfferActionBox2').style.display = 'block';
		PublicAjaxController.setAsFavoriteJobOffer(getFavoriteEntity(id, 0, 'jobOffer'), getSecurityToken(), setAsFavoriteJobOfferDone);
	} else {
		document.getElementById('FavoriteJobOfferActionBox3').style.display = 'block';
	}
}
function setAsFavoriteJobOfferDone(results) {
	setSecurityToken( results.securityToken );
	document.getElementById('FavoriteJobOfferActionBox2').style.display = 'none';
	if(results.resultId==null) document.getElementById('FavoriteJobOfferActionBox3').style.display = 'block';
	else {
		document.getElementById('FavoriteJobOfferActionBox11').style.display = 'none';
		document.getElementById('FavoriteJobOfferActionBox13').style.display = 'block';
		document.getElementById('FavoriteJobOfferActionBox1').style.display = 'block';
	}
}




function applyForJobOffer(id, loggedIn) {
	document.getElementById('FavoriteJobOfferActionBox1').style.display = 'none';
	if(loggedIn==1) {
		document.getElementById('FavoriteJobOfferActionBox5').style.display = 'block';
	} else {
		document.getElementById('FavoriteJobOfferActionBox4').style.display = 'block';
	}
}

function applyForJobOfferPreview(id) {
	var subject = document.getElementById('applicationform_subject').value,
		text = document.getElementById('applicationform_text').value;
	document.getElementById('applicationform_error').style.display = 'none';
	if( subject=='' || text=='' ) {
		document.getElementById('applicationform_error').style.display = 'block';
		return;
	}
	document.getElementById('applicationform_subject_preview').innerHTML = escapeHTMLEntities(subject).replace(/\n/g, '<br />');
	document.getElementById('applicationform_text_preview').innerHTML = escapeHTMLEntities(text).replace(/\n/g, '<br />');
	document.getElementById('FavoriteJobOfferActionBox5').style.display = 'none';
	document.getElementById('FavoriteJobOfferActionBox6').style.display = 'block';
}

function applyForJobOfferSubmit(id) {
	var subject = document.getElementById('applicationform_subject').value,
		text = document.getElementById('applicationform_text').value;
	document.getElementById('FavoriteJobOfferActionBox6').style.display = 'none';
	document.getElementById('FavoriteJobOfferActionBox2').style.display = 'block';
	PublicAjaxController.applyForJobOfferSubmit(id, subject, text, getSecurityToken(), getLocalizedString("locale.dojotype"), applyForJobOfferSubmitDone);
}

function applyForJobOfferBack(id) {
	document.getElementById('FavoriteJobOfferActionBox6').style.display = 'none';
	document.getElementById('FavoriteJobOfferActionBox5').style.display = 'block';
}

function applyForJobOfferSubmitDone(results) {
	setSecurityToken( results.securityToken );
	document.getElementById('applicationform_subject').value = '';
	document.getElementById('applicationform_text').value = '';
	document.getElementById('applicationform_error').style.display = 'none';
	document.getElementById('FavoriteJobOfferActionBox2').style.display = 'none';
	if(results.resultId==null) {
		document.getElementById('FavoriteJobOfferActionBox4').style.display = 'block';
	}
	else {
		document.getElementById('FavoriteJobOfferActionBox7').style.display = 'block';
		document.getElementById('FavoriteJobOfferActionBox91').style.display = 'block';
		document.getElementById('FavoriteJobOfferActionBox92').style.display = 'block';
		document.getElementById('FavoriteJobOfferActionBox93').style.display = 'block';
	}
}




function fillSpamReport() {
	document.getElementById('FavoriteJobOfferActionBox1').style.display = 'none';
	document.getElementById('FavoriteJobOfferActionBox8').style.display = 'block';
}

function fillSpamReportSubmit() {
	document.getElementById('FavoriteJobOfferActionBox8').style.display = 'none';
	document.getElementById('FavoriteJobOfferActionBox2').style.display = 'block';
	var text = document.getElementById('spamreport_text').value;
	PublicAjaxController.fillSpamReport(window.location.href, text, fillSpamReportDone);
}

function fillSpamReportDone() {
	document.getElementById('spamreport_text').value = '';
	document.getElementById('FavoriteJobOfferActionBox2').style.display = 'none';
	document.getElementById('FavoriteJobOfferActionBox9').style.display = 'block';
}







function removeAsFavoriteJobOfferFromList(id) {
	document.getElementById('FavoriteJobOfferBox'+id).style.display = 'none';
	document.getElementById('FavoriteJobOfferWaitBox'+id).style.display = 'block';
	PublicAjaxController.removeAsFavoriteJobOffer(id, getSecurityToken(), removeAsFavoriteJobOfferFromListDone);
}
function removeAsFavoriteJobOfferFromListDone(results) {
	setSecurityToken( results.securityToken );
	var el1 = document.getElementById('FavoriteJobOfferBox'+results.logicId),
		el2 = document.getElementById('FavoriteJobOfferWaitBox'+results.logicId),
		parentEl = el1.parentNode;
	parentEl.removeChild( el1 );
	parentEl.removeChild( el2 );
}











function requestContactShare(id) {
	document.getElementById('requestContactShareBox1').style.display = 'none';
	document.getElementById('requestContactShareBox3').style.display = 'block';
	PublicAjaxController.requestContactShare(id, getSecurityToken(), getLocalizedString("locale.dojotype"), requestContactShareDone);
}
function requestContactShareDone(results) {
	setSecurityToken( results.securityToken );
	document.getElementById('requestContactShareBox3').style.display = 'none';
	document.getElementById('requestContactShareBox2').style.display = 'block';
}





function setAsFavoriteJobRequestInit(id) {
	document.getElementById('setAsFavoriteJobRequestBox1').style.display = 'none';
	document.getElementById('setAsFavoriteJobRequestBox2').style.display = 'block';
	PublicAjaxController.setAsFavoriteJobRequest(getFavoriteEntity(id, 3, 'user'), getSecurityToken(), setAsFavoriteJobRequestInitDone);
}
function setAsFavoriteJobRequestInitDone(results) {
	setSecurityToken( results.securityToken );
	document.getElementById('setAsFavoriteJobRequestBox2').style.display = 'none';
	document.getElementById('setAsFavoriteJobRequestBox3').style.display = 'block';
}

function setAsFavoriteJobRequest(id,rating) {
	document.getElementById('setAsFavoriteJobRequestBox1_'+id).style.display = 'none';
	document.getElementById('setAsFavoriteJobRequestBox2_'+id).style.display = 'block';
	PublicAjaxController.setAsFavoriteJobRequest(getFavoriteEntity(id, rating, 'user'), getSecurityToken(), setAsFavoriteJobRequestDone);
}
function setAsFavoriteJobRequestDone(results) {
	setSecurityToken( results.securityToken );
	document.getElementById('setAsFavoriteJobRequestBox2_'+results.resultId).style.display = 'none';
	doShowSuccessMsgBox(results.resultId,1000);
}

function removeAsFavoriteJobRequestFromList(id) {
	document.getElementById('FavoriteJobRequestBox'+id).style.display = 'none';
	document.getElementById('FavoriteJobRequestWaitBox'+id).style.display = 'block';
	PublicAjaxController.removeAsFavoriteJobRequest(id, getSecurityToken(), removeAsFavoriteJobRequestFromListDone);
}
function removeAsFavoriteJobRequestFromListDone(results) {
	setSecurityToken( results.securityToken );
	var el1 = document.getElementById('FavoriteJobRequestBox'+results.logicId),
		el2 = document.getElementById('FavoriteJobRequestWaitBox'+results.logicId),
		parentEl = el1.parentNode;
	parentEl.removeChild( el1 );
	parentEl.removeChild( el2 );
}







function displayPoll(poll) {
	if(poll != null) {
		var parentNode = document.getElementById("poll"+poll.logicId),
			newInner, total, i, pollItem, value, scaledWidth;
		
		if( poll.submitted ) {
			newInner = '<div><b>'+poll.subject+'</b></div><br/><table>';
			total = 0;
			for(i = 0; i < poll.pollItems.length; i++) {
				total += poll.pollItems[i].count;
			}
			if(total==0) total = 1;
			for(i = 0; i < poll.pollItems.length; i++) {
				pollItem = poll.pollItems[i];
				value = Math.round(pollItem.count*1000/total);
				scaledWidth = Math.round(0.14*value) + 5;
				newInner += '<tr><td width="170px">'+pollItem.text+' <span class="small_text">('+(value/10)+'%)<span></td><td width="130px"><img class="image_border" src="/image/pollbar.gif" width="'+scaledWidth+'px" height="10px"/></td></tr>';
			}
			newInner += '</table>';
		} else {
			newInner = '<div><b>'+poll.subject+'</b></div><br/>';
			for(i = 0; i < poll.pollItems.length; i++) {
				pollItem = poll.pollItems[i];
				newInner += '<input type="radio" name="pollItems'+poll.id+'" id="pollItem'+pollItem.id+'" value="'+pollItem.id+'" />' + '<label for="pollItem'+pollItem.id+'">'+pollItem.text+'</label><br/>';
			}
			newInner += '<br/><button onclick="return submitPoll('+poll.id+',\''+poll.logicId+'\')" type="submit" class="submit_button">'+getLocalizedString('js.action.submit')+'</button>';
		}
		parentNode.innerHTML = newInner;
	}
}





function showPoll(pollId, logicId, language) {
	PublicAjaxController.showPoll(pollId, logicId, language, showPollDone);
}

function showPollDone(results) {
	if( results==null || !results.id || results.id==null ) {
		return;
	}
	displayPoll(results);
}

function submitPoll(pollId, logicId) {
	var i,
		pollItemId = null,
		items = document.getElementsByName("pollItems"+pollId);
	for(i = 0; i < items.length; i++) {
		if( items[i].checked == true ) {
			pollItemId = items[i].value;
			break;
		}
	}
	if(pollItemId != null) {
		PublicAjaxController.submitPoll(pollId, pollItemId, logicId, submitPollDone);
	}
	return false;
}

function submitPollDone(results) {
	if( results==null || !results.id || results.id==null ) {
		return;
	}
	displayPoll(results);
}





















function closeNotification(id, type) {
	document.getElementById('NotificationBox'+id).style.display = 'none';
	document.getElementById('NotificationWaitBox'+id).style.display = 'block';
	PublicAjaxController.closeNotification(id, type, getSecurityToken(), closeNotificationDone);
}
function closeNotificationDone(results) {
	setSecurityToken( results.securityToken );
	var el1 = document.getElementById('NotificationBox'+results.resultId),
		el2 = document.getElementById('NotificationWaitBox'+results.resultId),
		parentEl = el1.parentNode;
	parentEl.removeChild( el1 );
	parentEl.removeChild( el2 );
}










function selectJobType( selection ) {
	if(selection==null) return;
	for(var i=1; i<=4;i++) {
		document.getElementById('moreInfoJobType'+i).style.display = 'none';
	}
	document.getElementById("moreInfoJobType"+selection).style.display = 'block';
}



function trim(stringToTrim) {
	return stringToTrim.replace(/^\s+|\s+$/g,"");
}
function ltrim(stringToTrim) {
	return stringToTrim.replace(/^\s+/,"");
}
function rtrim(stringToTrim) {
	return stringToTrim.replace(/\s+$/,"");
}



function escapeHTMLEntities(stringToEscape) {
	return stringToEscape.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
}

function unescapeHTMLEntities(stringToEscape) {
	return stringToEscape.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
}




function showAgencyContactForm() {
	document.getElementById("agencycontact1").style.display = 'none';
	document.getElementById("agencycontact2").style.display = 'block';

	document.getElementById("agencycontact_error_email").style.display = 'none';
	document.getElementById("agencycontact_error_name").style.display = 'none';
	document.getElementById("agencycontact_error_text").style.display = 'none';
	document.getElementById("agencycontact_error_captcha").style.display = 'none';
}

function hideAgencyContactForm() {
	document.getElementById("agencycontact3").style.display = 'none';
	document.getElementById("agencycontact2").style.display = 'none';
	document.getElementById("agencycontact1").style.display = 'block';
}


function submitAgencyContactForm(agencyContactId) {
	document.getElementById("agencycontact_submitbutton").style.display = 'none';
	document.getElementById("agencycontact_waiting").style.display = 'block';
	var name = document.getElementById("agencycontact_name").value,
		email = document.getElementById("agencycontact_email").value,
		captcha = document.getElementById("agencycontact_captcha").value,
		text = document.getElementById("agencycontact_text").value;
	PublicAjaxController.submitAgencyContactForm(name, email, text, captcha, agencyContactId, submitAgencyContactFormDone);
}


function submitAgencyContactFormDone(results) {
	document.getElementById("agencycontact_error_email").style.display = 'none';
	document.getElementById("agencycontact_error_name").style.display = 'none';
	document.getElementById("agencycontact_error_text").style.display = 'none';
	document.getElementById("agencycontact_error_captcha").style.display = 'none';
	document.getElementById("agencycontact_captcha").value = '';

	if( results.errors!=null && results.errors.length>0) {
		for (var i = 0; i < results.errors.length; i++){
			document.getElementById(results.errors[i]).style.display = 'inline';
		}
		document.getElementById("agencycontact_captchaimage").src = "/captcha.html?" + (new Date()).getTime();
	} else {
		document.getElementById("agencycontact2").style.display = 'none';
		document.getElementById("agencycontact3").style.display = 'block';

		document.getElementById("agencycontact_name").value = '';
		document.getElementById("agencycontact_email").value = '';
		document.getElementById("agencycontact_text").value = '';
	}
	document.getElementById("agencycontact_waiting").style.display = 'none';
	document.getElementById("agencycontact_submitbutton").style.display = 'block';
}




























function showEditUploadBox() {
	document.getElementById('plain_upload_box').style.display = 'none';
	document.getElementById('edit_upload_box').style.display = 'block';
}
function showPlainUploadBox() {
	document.getElementById('error_edit_upload_box').style.display = 'none';
	document.getElementById('edit_upload_box').style.display = 'none';
	document.getElementById('plain_upload_box').style.display = 'block';
}






function validate_form_fields( widgets, logicId ) {
	var i, widget, isValid, result = true;
	for(i = 0; i < widgets.length; i++) {
		widget = dijit.byId("edit_" + widgets[i] + logicId);
		if( widget && widget.isValid ) {
			isValid = widget.isValid(false);
			if (!isValid) {
				widget.state = "Error";
				widget._setStateClass();
				result = false;
			}
		}
	}
	return result;
}





function showAjaxEditBox( container, logicId ) {
	document.getElementById( "plain_" + container + logicId ).style.display = 'none';
	document.getElementById( "edit_" + container + logicId ).style.display = 'block';
}


function cancelAjaxEditBox( container, logicId ) {
	var fields = dynamicForms[container]['fields'],
		key, plainEl, editEl, i,state, country, dateD, editElD, dateM, editElM, dateY, editElY, value, widget;

	for( key in fields ) {
		if( fields[key] != 'hidden') {

			plainEl = document.getElementById( "plain_" + key + logicId );
			editEl = document.getElementById( "edit_" + key + logicId );
			
			plainData = trim(plainEl.innerHTML);
			
			
			if( fields[key] == 'text' ) {
				editEl.value = unescapeHTMLEntities(plainData.replace(/<br>/g, '').replace(/<br\/>/g, '').replace(/<br \/>/g, ''));
			} else if( fields[key] == 'date' ) {

				dateD = document.getElementById( "plain_" + key + "D" + logicId ).value;
				editElD = document.getElementById( "edit_" + key + "D" + logicId );
				for(i=0; i<editElD.options.length; i++) {
					if(editElD.options[i].value == dateD) {
						editElD.selectedIndex = i;
						break;
					}
				}

				dateM = document.getElementById( "plain_" + key + "M" + logicId ).value;
				editElM = document.getElementById( "edit_" + key + "M" + logicId );
				for(i=0; i<editElM.options.length; i++) {
					if(editElM.options[i].value == dateM) {
						editElM.selectedIndex = i;
						break;
					}
				}

				dateY = document.getElementById( "plain_" + key + "Y" + logicId ).value;
				editElY = document.getElementById( "edit_" + key + "Y" + logicId );
				for(i=0; i<editElY.options.length; i++) {
					if(editElY.options[i].value == dateY) {
						editElY.selectedIndex = i;
						break;
					}
				}

			} else if( fields[key] == 'checkbox' ) {
				editEl.checked = plainEl.checked;
			} else if( fields[key] == 'select' ) {
				widget = dijit.byId( "edit_" + key + logicId );
				if(widget==null) {
					for(i=0; i<editEl.options.length; i++) {
						if(editEl.options[i].text == plainData) {
							editEl.selectedIndex = i;
							break;
						}
					}
				} else {
					for(i=0; i<dijit.byId( "edit_" + key + logicId ).store.root.options.length; i++) {
						if(dijit.byId( "edit_" + key + logicId ).store.root.options[i].text == plainData) {
							value = dijit.byId( "edit_" + key + logicId ).store.root.options[i].value;
							dijit.byId( "edit_" + key + logicId ).setValue(value);
							break;
						}
					}
				}
			} else if( fields[key] == 'statelist' ) {
				state = "edit_" + key + logicId;
				country = state.replace("state", "country");
				setStateList(	dojo.byId(country).value,
								getLocalizedString('locale.type'),
								state,
								plainData,
								false,
								false );
			}
		}
	}
	
	document.getElementById( "edit_" + container + logicId ).style.display = 'none';
	document.getElementById( "plain_" + container + logicId ).style.display = 'block';
	removeErrorsFromAjaxEditBox( container, logicId );
}


function removeErrorsFromAjaxEditBox( container, logicId ) {
	var errorEl = document.getElementById( "error_" + container + logicId ),
		errorcontentEl = document.getElementById( "errorcontent_" + container + logicId ),
		newEl, i, widget, widgets, submitErrorEl;

	errorEl.removeChild( errorcontentEl );
	newEl = document.createElement("div");
	newEl.setAttribute( "id", "errorcontent_" + container + logicId );
	errorEl.appendChild( newEl );
	
	widgets = dynamicForms[container]['widgets'];
	for(i = 0; i < widgets.length; i++) {
		widget = dijit.byId("edit_" + widgets[i] + logicId);
		if( widget && widget.isValid ) {
			widget.state = "";
			widget._setStateClass();
		}
	}
	
	submitErrorEl = document.getElementById( "error_submit_button" + logicId );
	if(submitErrorEl) {
		submitErrorEl.style.display = 'none';
	}
}










function validate_CVRecord_form( container, logicId ) {
	var widgets = dynamicForms[container]['widgets'],
		newWidgets = new Array(),
		validateEndDate = true,
		i;

	if(dynamicForms[container]['fields']['current'] != null) {
		if(dojo.byId( "edit_current" + logicId ).checked) {
			validateEndDate = false;
		}
	}

	if(validateEndDate) {
		return validate_form_fields( widgets, logicId );
	} else {
		for(i = 0; i < widgets.length; i++) {
			if(widgets[i] != "endMonth" && widgets[i] != "endYear") {
				newWidgets.push(widgets[i]);
			}
		}
		return validate_form_fields( newWidgets, logicId );
	}
}






validationCVRecordArray = ["school","apprenticeship","service","studies","internship","job","project","abroad","involvement","list","reference"];
validationSettingsArray = ["CandidateProfileSettings","CandidateProfileAddress","CompanyUserDetails","CompanyInfoContact","CompanyInfoAdditionals","CompanyInfoAddress"];

function do_form_validation(container, logicId){

	if(container=="language") return true;
	
	var i, dateD, dateM, dateY, dateObj, dateResult;

	for (i = 0; i < validationCVRecordArray.length; i++) {
		if (validationCVRecordArray[i]==container) {
			return validate_CVRecord_form( container, logicId );
		}
	}
	for (i = 0; i < validationSettingsArray.length; i++) {
		if (validationSettingsArray[i]==container) {
			return validate_form_fields( dynamicForms[container]['widgets'], logicId );
		}
	}
	
	if(container=="CandidateProfileDetails") {
		// do separate validate for birthday in order to check if date is valid
		document.getElementById( "edit_birthday_error" + logicId ).style.display = 'none';
		dateD = document.getElementById( "edit_birthdayD" + logicId ).value;
		dateM = document.getElementById( "edit_birthdayM" + logicId ).value;
		dateY = document.getElementById( "edit_birthdayY" + logicId ).value;
		dateObj = new Date(dateY, (dateM-1), dateD);
		dateResult = ((dateD==dateObj.getDate()) && ((dateM-1)==dateObj.getMonth()) && (dateY==dateObj.getFullYear()));
		if(!dateResult) {
			document.getElementById( "edit_birthday_error" + logicId ).style.display = 'inline';
		}
		return validate_form_fields( dynamicForms['CandidateProfileDetails']['widgets'], logicId ) && dateResult;
	}
	
	return false;
}









function saveAjaxEditBox(container, type, logicId, parentId) {

	var key, fields, submitErrorEl, editEl, dateD, dateM, dateY, widget,
		form = {};
	
	if( !do_form_validation(container, logicId) ) {
		submitErrorEl = document.getElementById( "error_submit_button" + logicId );
		if(submitErrorEl) {
			submitErrorEl.style.display = 'block';
		}
		return;
	}
	
	form[ 'id' ] = document.getElementById( "edit_" + 'id' + logicId ).value;

	fields = dynamicForms[container]['fields'];
	for( key in fields ) {
		
		editEl = document.getElementById( "edit_" + key + logicId );

		if( fields[key] == 'text' ) {
			form[ key ] = editEl.value;
		} else if( fields[key] == 'date' ) {
			dateD = document.getElementById( "edit_" + key + "D" + logicId ).value;
			dateM = document.getElementById( "edit_" + key + "M" + logicId ).value;
			dateY = document.getElementById( "edit_" + key + "Y" + logicId ).value;
			form[ key ] = new Date(dateY, (dateM-1), dateD);
		} else if( fields[key] == 'checkbox' ) {
			form[ key ] = "" + editEl.checked;
		} else if( fields[key] == 'select' || fields[key] == 'statelist' ) {
			widget = dijit.byId( "edit_" + key + logicId );
			if(widget==null) {
				form[ key ] = editEl.value;
			} else {
				form[ key ] = widget.value;
			}
		} else if( fields[key] == 'hidden' ) {
			form[ key ] = editEl.value;
		}
	}
	
	
	if( container=='list' ) {
		form = getListItemsIntoStore(logicId, form);
	}
	if( container=='language' ) {
		form = getLanguageItemsIntoStore(logicId, form);
	}

	ajaxPreHook( container, logicId );

	
	if(type=="CVRecord") CandidateAjaxController.editCVRecord( logicId, parentId, form, getSecurityToken(), container, finishEditCVRecord );
	else if(type=="CandidateProfileDetails") CandidateAjaxController.candidateProfileDetails( logicId, parentId, form, getSecurityToken(), container, finishEditCandidateProfileDetails );
	else if(type=="CandidateProfileAddress") CandidateAjaxController.candidateProfileAddress( logicId, parentId, form, getSecurityToken(), container, finishEditCandidateProfileAddress );
	else if(type=="CandidateProfileSettings") CandidateAjaxController.candidateProfileSettings( logicId, parentId, form, getSecurityToken(), container, finishEditCandidateProfileSettings );
	else if(type=="CompanyUserDetails") CompanyAjaxController.companyUserDetails( logicId, parentId, form, getSecurityToken(), container, finishEditCompanyUserDetails );
	else if(type=="CompanyInfoContact") CompanyAjaxController.companyInfoContact( logicId, parentId, form, getSecurityToken(), container, finishEditCompanyInfoContact );
	else if(type=="CompanyInfoAdditionals") CompanyAjaxController.companyInfoAdditionals( logicId, parentId, form, getSecurityToken(), container, finishEditCompanyInfoAdditionals );
	else if(type=="CompanyInfoAddress") CompanyAjaxController.companyInfoAddress( logicId, parentId, form, getSecurityToken(), container, finishEditCompanyInfoAddress );
}







function finishAjaxEditBox(results) {
	var res, i, newEl, fields, key, editEl, plainEl, dateD, dateM, dateY, dateObj, widget, errorEl;
	
	removeErrorsFromAjaxEditBox( results.container, results.logicId );
	errorEl = document.getElementById( "errorcontent_" + results.container + results.logicId );
	if( results.errors != null && results.errors.length>0 ) {
		for(i=0; i<results.errors.length; i++ ) {
			newEl = document.createElement("div");
			newEl.appendChild( document.createTextNode( getLocalizedString( results.errors[ i ] ) ) );
			errorEl.appendChild( newEl );
		}
		res = false;
	} else {

		document.getElementById( "edit_" + 'id' + results.logicId ).value = results.resultId;
		
		fields = dynamicForms[results.container]['fields'];
		for( key in fields ) {
			if( fields[key] != 'hidden') {
				
				plainEl = document.getElementById("plain_" + key + results.logicId);
				editEl = document.getElementById("edit_" + key + results.logicId);
				
				if( fields[key] == 'text' ) {
					plainEl.innerHTML = escapeHTMLEntities(editEl.value).replace(/\n/g, '\n<br />');
				} else if( fields[key] == 'date' ) {
					dateD = document.getElementById( "edit_" + key + "D" + results.logicId ).value;
					dateM = document.getElementById( "edit_" + key + "M" + results.logicId ).value;
					dateY = document.getElementById( "edit_" + key + "Y" + results.logicId ).value;
					document.getElementById( "plain_" + key + "D" + results.logicId ).value = dateD;
					document.getElementById( "plain_" + key + "M" + results.logicId ).value = dateM;
					document.getElementById( "plain_" + key + "Y" + results.logicId ).value = dateY;
					dateObj = new Date(dateY, (dateM-1), dateD);
					plainEl.firstChild.data = dateObj.format( getLocalizedString('locale.dateFormat') );
				} else if( fields[key] == 'checkbox' ) {
					plainEl.checked = editEl.checked;
				} else if( fields[key] == 'select' || fields[key] == 'statelist' ) {
					widget = dijit.byId( "edit_" + key + results.logicId );
					if(widget==null) {
						plainEl.innerHTML = editEl.options[ editEl.selectedIndex ].text;
					} else {
						plainEl.innerHTML = widget.item.text;
					}
				}
			}
		}
	
		document.getElementById( "edit_" + results.container + results.logicId ).style.display = 'none';
		document.getElementById( "plain_" + results.container + results.logicId ).style.display = 'block';
		
		res = true;
	}
	
	return res;
}










function ajaxPreHook( container, logicId ) {
	var coords = dojo.coords( dojo.byId(container+'_container') ),
		width = coords.w - 10,
		height = coords.h - 20,
		loading_container = dojo.byId(container+'_container_loading');
	loading_container.style.width = width + "px";
	loading_container.style.height = height + "px";
	loading_container.style.display = 'block';
}

function ajaxPostHook(results,showMsg) {
	setSecurityToken( results.securityToken );
	document.getElementById(results.container+"_container_loading").style.display = 'none';
	if(showMsg) {
		showSuccessMsgBox(results.logicId);
	}
}











function showSuccessMsgBox(logicId) {
	doShowSuccessMsgBox(logicId,2000);
}

function doShowSuccessMsgBox(logicId,duration) {
	var box = document.getElementById("success_msg_box"+logicId);
	box.style.display = 'block';
	box.style.height = 'auto';
    window.setTimeout( function() {hideSuccessMsgBox(logicId);}, duration);
}

function hideSuccessMsgBox(logicId) {
	var wipeArgs = { node: "success_msg_box"+logicId, duration:1000 };
	dojo.fx.wipeOut(wipeArgs).play();
}











function submitWizardPage(widgets, logicId) {
	var submitErrorEl;
	if( validate_form_fields( widgets, logicId ) ) {
		return true;
	} else {
		submitErrorEl = document.getElementById( "error_submit_button" + logicId );
		if(submitErrorEl) {
			submitErrorEl.style.display = 'block';
		}
		return false;
	}
}









function setLanguageList( language, selectBoxId, selectedValue ) {
	dojo.xhrGet({
		url: "/json/language/"+language+".txt",
		handleAs: "json",
		timeout: 3000,
		load: function(response, ioArgs) {
			dwr.util.removeAllOptions(selectBoxId);
			dwr.util.addOptions(selectBoxId, response, 'code', 'label');
			if(selectedValue!=null) {
				dojo.byId(selectBoxId).value = selectedValue;
			}
		},
		error: function(response, ioArgs) {
			//
		}
	});
}


function initLanguageLists( language, selectBoxName ) {
	dojo.xhrGet({
		url: "/json/language/"+language+".txt",
		handleAs: "json",
		timeout: 3000,
		load: function(response, ioArgs) {

			var selectBoxes = document.getElementsByName(selectBoxName),
				oldKey, i;
			
			for(i = 0; i < selectBoxes.length; i++) {
				selectBox = selectBoxes[i];
				selectBox.id = "langrow" + (new Date()).getTime() + i;
				oldKey = selectBox.options[0].value;
				
				dwr.util.removeAllOptions(selectBox.id);
				dwr.util.addOptions(selectBox.id, response, 'code', 'label');
				selectBox.value = oldKey;
			}
		},
		error: function(response, ioArgs) {
			//
		}
	});
}





function highlightCockpit(value){
	if(value) {
		document.getElementById('highlightCockpitBox').style.border = '1px solid #FF0000';
	} else {
		document.getElementById('highlightCockpitBox').style.border = '1px solid #E5E5E5';
	}
}










dynamicForms = new Array();


dynamicForms['CompanyUserDetails'] = new Array();
dynamicForms['CompanyUserDetails']['fields'] = { 'newsletter':'checkbox' };
dynamicForms['CompanyUserDetails']['widgets'] = new Array();

dynamicForms['CompanyInfoContact'] = new Array();
dynamicForms['CompanyInfoContact']['fields'] = { 'contactName':'text', 'phone':'text', 'fax':'text', 'linkWebsite':'text', 'linkRecruiting':'text' };
dynamicForms['CompanyInfoContact']['widgets'] = new Array();

dynamicForms['CompanyInfoAdditionals'] = new Array();
dynamicForms['CompanyInfoAdditionals']['fields'] = { 'descriptionText':'text', 'productsAndServices':'text' };
dynamicForms['CompanyInfoAdditionals']['widgets'] = new Array();

dynamicForms['CompanyInfoAddress'] = new Array();
dynamicForms['CompanyInfoAddress']['fields'] = { 'street':'text', 'city':'text', 'zip':'text', 'country':'select', 'state':'statelist' };
dynamicForms['CompanyInfoAddress']['widgets'] = new Array('street', 'city', 'zip', 'country', 'state');



dynamicForms['school'] = new Array();
dynamicForms['school']['fields'] = { 'cvRecordType':'hidden', 'organizationName':'text', 'addrCity':'text', 'addrCountry':'select', 'description':'text', 'startMonth':'select', 'startYear':'select', 'endMonth':'select', 'endYear':'select', 'current':'checkbox', 'degreeType':'text', 'degreeGrade':'text' };
dynamicForms['school']['widgets'] = new Array( 'organizationName', 'addrCity', 'addrCountry', 'startMonth', 'startYear', 'endMonth', 'endYear' );

dynamicForms['apprenticeship'] = new Array();
dynamicForms['apprenticeship']['fields'] = { 'cvRecordType':'hidden', 'title':'text', 'organizationName':'text', 'addrCity':'text', 'addrCountry':'select', 'description':'text', 'startMonth':'select', 'startYear':'select', 'endMonth':'select', 'endYear':'select', 'current':'checkbox' };
dynamicForms['apprenticeship']['widgets'] = new Array( 'title', 'organizationName', 'addrCity', 'addrCountry', 'startMonth', 'startYear', 'endMonth', 'endYear' );

dynamicForms['service'] = new Array();
dynamicForms['service']['fields'] = { 'cvRecordType':'hidden', 'title':'text', 'organizationName':'text', 'addrCity':'text', 'addrCountry':'select', 'description':'text', 'startMonth':'select', 'startYear':'select', 'endMonth':'select', 'endYear':'select', 'current':'checkbox' };
dynamicForms['service']['widgets'] = new Array( 'title', 'organizationName', 'addrCity', 'addrCountry', 'startMonth', 'startYear', 'endMonth', 'endYear' );

dynamicForms['studies'] = new Array();
dynamicForms['studies']['fields'] = { 'cvRecordType':'hidden', 'title':'text', 'organizationName':'text', 'addrCity':'text', 'addrCountry':'select', 'description':'text', 'startMonth':'select', 'startYear':'select', 'endMonth':'select', 'endYear':'select', 'current':'checkbox', 'degreeType':'text', 'degreeGrade':'text' };
dynamicForms['studies']['widgets'] = new Array( 'title', 'organizationName', 'addrCity', 'addrCountry', 'startMonth', 'startYear', 'endMonth', 'endYear' );

dynamicForms['internship'] = new Array();
dynamicForms['internship']['fields'] = { 'cvRecordType':'hidden', 'title':'text', 'organizationName':'text', 'addrCity':'text', 'addrCountry':'select', 'description':'text', 'startMonth':'select', 'startYear':'select', 'endMonth':'select', 'endYear':'select', 'current':'checkbox' };
dynamicForms['internship']['widgets'] = new Array( 'title', 'organizationName', 'addrCity', 'addrCountry', 'startMonth', 'startYear', 'endMonth', 'endYear' );

dynamicForms['job'] = new Array();
dynamicForms['job']['fields'] = { 'cvRecordType':'hidden', 'title':'text', 'organizationName':'text', 'addrCity':'text', 'addrCountry':'select', 'description':'text', 'startMonth':'select', 'startYear':'select', 'endMonth':'select', 'endYear':'select', 'current':'checkbox' };
dynamicForms['job']['widgets'] = new Array( 'title', 'organizationName', 'addrCity', 'addrCountry', 'startMonth', 'startYear', 'endMonth', 'endYear' );

dynamicForms['project'] = new Array();
dynamicForms['project']['fields'] = { 'cvRecordType':'hidden', 'title':'text', 'organizationName':'text', 'addrCity':'text', 'addrCountry':'select', 'description':'text', 'startMonth':'select', 'startYear':'select', 'endMonth':'select', 'endYear':'select', 'current':'checkbox' };
dynamicForms['project']['widgets'] = new Array( 'title', 'organizationName', 'addrCity', 'addrCountry', 'startMonth', 'startYear', 'endMonth', 'endYear' );

dynamicForms['abroad'] = new Array();
dynamicForms['abroad']['fields'] = { 'cvRecordType':'hidden', 'title':'text', 'addrCity':'text', 'addrCountry':'select', 'description':'text', 'startMonth':'select', 'startYear':'select', 'endMonth':'select', 'endYear':'select', 'current':'checkbox' };
dynamicForms['abroad']['widgets'] = new Array( 'title', 'addrCity', 'addrCountry', 'startMonth', 'startYear', 'endMonth', 'endYear' );

dynamicForms['involvement'] = new Array();
dynamicForms['involvement']['fields'] = { 'cvRecordType':'hidden', 'title':'text', 'addrCity':'text', 'addrCountry':'select', 'description':'text', 'startMonth':'select', 'startYear':'select', 'endMonth':'select', 'endYear':'select', 'current':'checkbox' };
dynamicForms['involvement']['widgets'] = new Array( 'title', 'addrCity', 'addrCountry', 'startMonth', 'startYear', 'endMonth', 'endYear' );

dynamicForms['list'] = new Array();
dynamicForms['list']['fields'] = { 'cvRecordType':'hidden', 'title':'text' };
dynamicForms['list']['widgets'] = new Array( 'title' );

dynamicForms['language'] = new Array();
dynamicForms['language']['fields'] = {};
dynamicForms['language']['widgets'] = new Array();

dynamicForms['reference'] = new Array();
dynamicForms['reference']['fields'] = { 'cvRecordType':'hidden', 'organizationName':'text', 'refName':'text', 'refPosition':'text', 'refEmail':'text', 'refPhone':'text' };
dynamicForms['reference']['widgets'] = new Array( 'organizationName', 'refName', 'refPosition', 'refEmail', 'refPhone' );


dynamicForms['CandidateProfileDetails'] = new Array();
dynamicForms['CandidateProfileDetails']['fields'] = { 'firstName':'text', 'lastName':'text', 'phone':'text', 'birthday':'date', 'candidateStatus':'select', 'gender':'select', 'currentCity':'text', 'currentOrganization':'text', 'currentCountry':'select' };
dynamicForms['CandidateProfileDetails']['widgets'] = new Array('firstName', 'lastName', 'phone', 'birthday', 'candidateStatus', 'gender', 'currentCity', 'currentOrganization', 'currentCountry' );

dynamicForms['CandidateProfileAddress'] = new Array();
dynamicForms['CandidateProfileAddress']['fields'] = { 'street':'text', 'city':'text', 'zip':'text', 'country':'select', 'state':'statelist' };
dynamicForms['CandidateProfileAddress']['widgets'] = new Array('street', 'city', 'zip', 'country', 'state');

dynamicForms['CandidateProfileSettings'] = new Array();
dynamicForms['CandidateProfileSettings']['fields'] = { 'newsletter':'checkbox' };
dynamicForms['CandidateProfileSettings']['widgets'] = new Array();





function finishEditCompanyUserDetails(results) { finishCompanyUserDetailsEditBox(results); ajaxPostHook(results,true); }
function finishEditCompanyInfoContact(results) { finishAjaxEditBox(results); ajaxPostHook(results,true); }
function finishEditCompanyInfoAdditionals(results) { finishCompanyInfoAdditionalsEditBox(results); ajaxPostHook(results,true); }
function finishEditCompanyInfoAddress(results) { finishAjaxEditBox(results); ajaxPostHook(results,true); }



function finishCompanyInfoAdditionalsEditBox(results) {
	finishAjaxEditBox( results );
}

function finishCompanyUserDetailsEditBox(results) {
	finishAjaxEditBox( results );
	
	if(document.getElementById( "edit_newsletter" + results.logicId ).checked) {
		document.getElementById( "plain_newsletter_msg" + results.logicId ).firstChild.data = getLocalizedString('js.domain.user.newsletter.true');
	} else {
		document.getElementById( "plain_newsletter_msg" + results.logicId ).firstChild.data = getLocalizedString('js.domain.user.newsletter.false');
	}
}







function submitWizardPageJobOffer0() {
	var widgets = ['earliestStartDate', 'latestStartDate'];
	return submitWizardPage(widgets, '0');
}
function submitWizardPageJobOffer1() {
	var widgets = ['title'];
	return submitWizardPage(widgets, '0');
}
function submitWizardPageJobOffer2() {
	var widgets = ['contactLastName', 'contactEmail', 'contactPhone', 'contactAddrStreet', 'contactAddrCity', 'contactAddrZip', 'contactAddrState', 'contactAddrCountry'];
	return submitWizardPage(widgets, '0');
}

function submitWizardPageRecruitingEvent0() {
	var widgets = ['title', 'startDate', 'endDate','contactLastName', 'contactEmail'];
	return submitWizardPage(widgets, '0');
}
function submitWizardPageRecruitingEvent1() {
	var widgets = ['addrStreet', 'addrCity', 'addrZip', 'addrState', 'addrCountry'];
	return submitWizardPage(widgets, '0');
}







function updateProfileScore(data) {
	document.getElementById("profileScoreImage").style.width = data+"%";
	document.getElementById("profileScoreNumber").innerHTML = data;
}



function finishEditCVRecord(results) {
	if(results.container=='list') {
		finishCVRecordListEditBox(results);
	} else if(results.container=='language') {
		finishCVRecordLanguageEditBox(results);
	} else {
		finishCVRecordEditBox(results);
	}
	updateProfileScore(results.data);
	ajaxPostHook(results,true);
}

function finishDeleteCVRecord(results) { finishDeleteCVRecordEditBox(results); updateProfileScore(results.data); ajaxPostHook(results,false); }
function finishMoveUpCVRecord(results) { finishMoveUpCVRecordEditBox(results); ajaxPostHook(results,false); }
function finishMoveDownCVRecord(results) { finishMoveDownCVRecordEditBox(results); ajaxPostHook(results,false); }


function finishEditCandidateProfileDetails(results) { finishAjaxEditBox(results); updateProfileScore(results.data); ajaxPostHook(results,true); }
function finishEditCandidateProfileAddress(results) { finishAjaxEditBox(results); updateProfileScore(results.data); ajaxPostHook(results,true); }
function finishEditCandidateProfileSettings(results) { finishCandidateProfileSettingsEditBox(results); ajaxPostHook(results,true); }


function finishCandidateProfileSettingsEditBox(results) {
	finishAjaxEditBox( results );
	
	if(document.getElementById( "edit_newsletter" + results.logicId ).checked) {
		document.getElementById( "plain_newsletter_msg" + results.logicId ).firstChild.data = getLocalizedString('js.domain.user.newsletter.true');
	} else {
		document.getElementById( "plain_newsletter_msg" + results.logicId ).firstChild.data = getLocalizedString('js.domain.user.newsletter.false');
	}
}






function moveCVRecordUp(container, logicId) {
	ajaxPreHook( container, logicId );
	var id = document.getElementById( "edit_" + 'id' + logicId ).value;
	CandidateAjaxController.moveCVRecordUp( logicId, 0, id, getSecurityToken(), container, finishMoveUpCVRecord);
}

function moveCVRecordDown(container, logicId) {
	ajaxPreHook( container, logicId );
	var id = document.getElementById( "edit_" + 'id' + logicId ).value;
	CandidateAjaxController.moveCVRecordDown( logicId, 0, id, getSecurityToken(), container, finishMoveDownCVRecord);
}


function finishMoveUpCVRecordEditBox(results) {
	if( results.errors != null && results.errors.length > 0 ) {
		return;
	}
	var el = document.getElementById( results.container + "_container" ),
		last = null,
		i, child, attr;
	
	for(i = 0; i < el.childNodes.length; i++) {
		child = el.childNodes[ i ];
		if( child.nodeName.toUpperCase() == "DIV" ) {
			attr = child.getAttribute("id");
			if( attr != null && attr.indexOf(results.container + "_record")==0 ) {
				if( attr == (results.container + "_record" + results.logicId) ) {
					if( last != null ) {
						document.getElementById(results.container + "_container").removeChild(child);
						document.getElementById(results.container + "_container").insertBefore(child, last);
					}
					break;
				}
				last = child;
			}
		}
	}
}

function finishMoveDownCVRecordEditBox(results) {
	if( results.errors != null && results.errors.length > 0 ) {
		return;
	}
	var el = document.getElementById( results.container + "_container" ),
		last = null,
		i, child, attr;

	for(i = 0; i < el.childNodes.length; i++) {
		child = el.childNodes[ i ];
		if( child.nodeName.toUpperCase() == "DIV" ) {
			attr = child.getAttribute("id");
			if( attr != null && attr.indexOf(results.container + "_record")==0 ) {
				
				if( attr == (results.container + "_record" + results.logicId) ) {
					last = child;
				} else {
					if( last != null ) {
						document.getElementById(results.container + "_container").removeChild(child);
						document.getElementById(results.container + "_container").insertBefore(child, last);
						break;
					}
				}
				
			}
		}
	}
}







function showAjaxDeleteBox(container, logicId) {
	if( confirm( getLocalizedString('js.confirm.delete') ) ) {
		ajaxPreHook( container, logicId );
		var form = {};
		form[ 'id' ] = document.getElementById( "edit_" + 'id' + logicId ).value;
		CandidateAjaxController.deleteCVRecord( logicId, 0, form, getSecurityToken(), container, finishDeleteCVRecord);
	}
}




function finishDeleteCVRecordEditBox(results) {
	var containerEl = document.getElementById( results.container + "_container" ),
		deleteEl = document.getElementById( results.container + "_record" + results.logicId );
	deleteEl.style.display = "none";
	clearCVRecordData( results.container, results.logicId );
	if(results.container == 'list') {
		clearCVRecordListData( results.container, results.logicId );
	}
	containerEl.removeChild( deleteEl );
	containerEl.appendChild( deleteEl );
	updateNewRecordPanel( results.container );
}

function finishCVRecordEditBox(results) {
	if( finishAjaxEditBox( results ) ) {
		var currentWidget = dojo.byId( "edit_current" + results.logicId );
		if(currentWidget && currentWidget.checked) {
			document.getElementById( "plain_endMonth" + results.logicId ).innerHTML = getLocalizedString('js.domain.cv.record.current');
			document.getElementById( "plain_endYear" + results.logicId ).innerHTML = "";
		}
		onCurrentClick(results.logicId);
	}
	updateNewRecordPanel( results.container );
}


function cancelCVRecordEditBox( container, logicId ) {
	cancelAjaxEditBox( container, logicId );
	
	if(document.getElementById( "plain_endDate" + logicId )!=null) {
		if(document.getElementById( "plain_endMonth" + logicId ).firstChild
		   && document.getElementById( "plain_endMonth" + logicId ).firstChild.data == getLocalizedString('js.domain.cv.record.current')) {
			document.getElementById( "edit_endMonth" + logicId ).value = "";
			document.getElementById( "edit_endYear" + logicId ).value = "";
		}
		onCurrentClick(logicId);
	}
	
	if(container=='list') {
		cancelCVRecordListEditBox( container, logicId );
	}
	if(container=='language') {
		cancelCVRecordLanguageEditBox( container, logicId );
	}
	
	
	if( document.getElementById( "edit_id" + logicId ).value==0 ) {
		document.getElementById( container + "_record" + logicId ).style.display = "none";
		if(container=='list') {
			clearCVRecordListData( container, logicId );
		}
	}
	updateNewRecordPanel(container);
}

function getEmptyCVRecordLogicId( container ) {
	var containerEl = document.getElementById( container + "_container" ),
		elements = containerEl.getElementsByTagName("input"),
		i, attr;
	for(i = 0; i < elements.length; i++) {
		attr = elements[i].getAttribute("id");
		if( attr != null && attr.substring(0, 7)=="edit_id" && elements[i].value==0 ) {
			return attr.substring(7);
		}
	}
	return null;
}

function showCVRecordEditBox( container, logicId ) {
	showAjaxEditBox( container, logicId );
	onCurrentClick(logicId);
}

function showEmptyCVRecord( container ) {
	var logicId = getEmptyCVRecordLogicId( container );
	if( logicId != null ) {
		showCVRecordEditBox( container, logicId );
		document.getElementById( container + "_record" + logicId ).style.display = "block";
		document.getElementById( container + "_new_panel" ).style.display = "none";
	}
}

function showEmptyCVRecordList( container ) {
	var i, items, id = getEmptyCVRecordLogicId( container );
	if( id != null ) {
		showAjaxEditBox( container, id );
		document.getElementById( container + "_record" + id ).style.display = "block";
		document.getElementById( container + "_new_panel" ).style.display = "none";
		items = document.getElementsByName("edit_pairList_values"+id);
		for(i = 0; i < items.length; i++) {
			items[i].parentNode.style.display = 'none';
		}
		document.getElementById("edit_grid"+id).checked = false;
	}
}

function showEmptyCVRecordTable( container ) {
	var i, items, id = getEmptyCVRecordLogicId( container );
	if( id != null ) {
		showAjaxEditBox( container, id );
		document.getElementById( container + "_record" + id ).style.display = "block";
		document.getElementById( container + "_new_panel" ).style.display = "none";
		items = document.getElementsByName("edit_pairList_values"+id);
		for(i = 0; i < items.length; i++) {
			items[i].parentNode.style.display = 'inline';
		}
		document.getElementById("edit_grid"+id).checked = true;
	}
}





function updateNewRecordPanel( container ) {
	var id = getEmptyCVRecordLogicId( container ),
		el = document.getElementById( container + "_new_panel" );
	if(el!=null) {
		if( id == null ) {
			el.style.display = "none";
		} else {
			el.style.display = "block";
		}
	}
}









function clearCVRecordData( container, logicId ) {
	document.getElementById( "edit_" + 'id' + logicId ).value = 0;

	var fields = dynamicForms[container]['fields'],
		i, widget,  key, plainEl, editEl, plainData = "";
	
	for( key in fields ) {
		if( fields[key] != 'hidden') {

			plainEl = document.getElementById( "plain_" + key + logicId );
			editEl = document.getElementById( "edit_" + key + logicId );
			
			if( plainEl.hasChildNodes() == true ) {
				plainEl.firstChild.data = plainData;
			}
			
			if( fields[key] == 'text' ) {
				editEl.value = plainData;
			} else if( fields[key] == 'date' ) {
				editEl.value = plainData;
			} else if( fields[key] == 'checkbox' ) {
				editEl.checked = false;
			} else if( fields[key] == 'select' ) {
				widget = dijit.byId( "edit_" + key + logicId );
				if(widget==null) {
					if(key=='addrCountry') {
						for(i=0; i<editEl.options.length; i++) {
							if(editEl.options[i].value=='DE') {
								editEl.selectedIndex = i;
								break;
							}
						}
					} else {
						editEl.selectedIndex = 0;
					}
				} else {
					dijit.byId( "edit_" + key + logicId ).reset();
				}
			}
		}
	}
	
	onCurrentClick(logicId);
	removeErrorsFromAjaxEditBox(container, logicId);
}







function onCurrentClick(logicId) {
	var el = dojo.byId("edit_current" + logicId);
	if(el!=null) {
		if(el.checked) {
			dojo.byId("edit_endMonth" + logicId).selectedIndex = 0;
			dojo.byId("edit_endYear" + logicId).selectedIndex = 0;
		}
		dojo.byId("edit_endMonth" + logicId).disabled = el.checked;
		dojo.byId("edit_endYear" + logicId).disabled = el.checked;
	}
}







function finishCVRecordListEditBox(results) {
	if( finishAjaxEditBox( results ) ) {
		var isGrid = document.getElementById("edit_grid"+results.logicId).checked,
			parentNode = document.getElementById( "plain_pairList" + results.logicId ),
			childNode, keyItems, valueItems, newIndex, i, newKeyContent, newValueContent, newDiv, innerStyle, innerStyle2;

		while( parentNode.hasChildNodes() ) {
			childNode = parentNode.firstChild;
			parentNode.removeChild(childNode);
		}

		
		keyItems = document.getElementsByName("edit_pairList_keys"+results.logicId);
		valueItems = document.getElementsByName("edit_pairList_values"+results.logicId);
		newIndex = 0;
		for(i = 0; i < keyItems.length; i++) {
			newKeyContent = trim(keyItems[i].value);
			newValueContent = trim(valueItems[i].value);
			if(newKeyContent!="" || newValueContent!="") {
				
				newDiv = document.createElement("div");
				parentNode.appendChild(newDiv);

				innerStyle = '';
				innerStyle2 = '';
				if(!isGrid) {
					innerStyle = 'style="display:none;"';
					innerStyle2 = 'style="width:600px;"';
				}

				newDiv.innerHTML = '<div ' + innerStyle2 + ' id="plain_pairList[' + newIndex + '].key' + results.logicId + '" class="cv_record_list_item_key">' + newKeyContent + '</div>'
									+ '<div ' + innerStyle + ' id="plain_pairList[' + newIndex + '].value' + results.logicId + '" class="cv_record_list_item_value">' + newValueContent + '</div>'
									+ '<div class="clear"></div>';

				newIndex++;
			}

		}
		
		
		cancelCVRecordListEditBox( results.container, results.logicId );
		
	}
	
	updateNewRecordPanel( results.container );
}






function cancelCVRecordListEditBox( container, logicId ) {
	var parentNode = document.getElementById( "edit_pairList" + logicId ),
		newKeyContent = "",
		newValueContent = "",
		i, hasMore, plainKeyEl, plainValueEl;

	while( parentNode.hasChildNodes() ) {
		parentNode.removeChild(parentNode.firstChild);
	}
	
	hasMore = true;
	i = 0;
	while( hasMore ) {
		plainKeyEl = document.getElementById( "plain_pairList["+i+"].key" + logicId );
		plainValueEl = document.getElementById( "plain_pairList["+i+"].value" + logicId );
		if( plainKeyEl != null && plainValueEl != null ) {
			if(plainKeyEl.firstChild != null) {
				newKeyContent = plainKeyEl.firstChild.data;
			}
			if(plainValueEl.firstChild != null) {
				newValueContent = plainValueEl.firstChild.data;
			}
			addListRow( logicId, newKeyContent, newValueContent );
			i++;
		} else {
			hasMore = false;
		}
	}
}




function clearCVRecordListData( container, logicId ) {
	var i, parentNode = document.getElementById( "plain_pairList" + logicId );
	while( parentNode.hasChildNodes() ) {
		parentNode.removeChild(parentNode.firstChild);
	}
	parentNode = document.getElementById( "edit_pairList" + logicId );
	while( parentNode.hasChildNodes() ) {
		parentNode.removeChild(parentNode.firstChild);
	}
	for(i = 0; i < 5; i++) {
		addListRow( logicId, "", "" );
	}
}


function addListRow( logicId, keyContent, valueContent ) {
	var isGrid = document.getElementById("edit_grid"+logicId).checked,
		parentNode = document.getElementById( "edit_pairList" + logicId ),
		newDiv = document.createElement("div"),
		buffer, innerStyle='';

	newDiv.className = "pairListRow";
	parentNode.appendChild(newDiv);	
	
	if(!isGrid) {
		innerStyle = 'style="display:none"';
	}
	buffer = '<div class="cv_record_list_item_value">'
		+'<span style="width:300px"><input type="text" value="'+keyContent+'" name="edit_pairList_keys'+logicId+'"/></span>'
		+'<span '+innerStyle+'><input type="text" value="'+valueContent+'" name="edit_pairList_values'+logicId+'"/></span>'
		+'</div>'
		+'<div class="cv_list_controls">'
		+'<a href="javascript:" onclick="removeListRow(this)"><img src="/image/icons/cross.gif"/></a> '
		+'<a href="javascript:" onclick="moveListRowUp(this)"><img src="/image/icons/arrow_up.gif"/></a> '
		+'<a href="javascript:" onclick="moveListRowDown(this)"><img src="/image/icons/arrow_down.gif"/></a> '
		+'</div>'
		+'<div class="clear"></div>';
	newDiv.innerHTML = buffer;
}





function getParentPairListRow(startNode) {
	var result = null,
		node = startNode,
		searching = true,
		name;
	while( searching ) {
		node = node.parentNode;
		if( node != null) {
			name = node.className;
			if(name!=null && name=="pairListRow") {
				result = node;
				searching = false;
			}
		} else {
			searching = false;
		}
	}
	return result;
}

function removeListRow(removeButton) {
	var row = getParentPairListRow(removeButton);
	if(row!=null) {
		row.parentNode.removeChild(row);
	}
}


function moveListRowUp(moveButton) {
	var row = getParentPairListRow(moveButton),
		sibling, node, searching, name, parent;

	if(row!=null) {
		sibling = null;
		node = row;
		searching = true;
		while(searching) {
			node = node.previousSibling;
			if( node!=null ) {
				if(node.nodeType==1) {
					name = node.className;
					if(name!=null && name=="pairListRow") {
						sibling = node;
						searching = false;
					}
				}
			} else {
				searching = false;
			}
		}
		if(sibling != null) {
			parent = row.parentNode;
			parent.removeChild(row);
			parent.insertBefore(row, sibling);
		}
	}
}



function moveListRowDown(moveButton) {
	var row = getParentPairListRow(moveButton),
		sibling, node, searching, name, parent;
	
	if(row!=null) {
		sibling = null;
		node = row;
		searching = true;
		while(searching) {
			node = node.nextSibling;
			if( node!=null ) {
				if(node.nodeType==1) {
					name = node.className;
					if(name!=null && name=="pairListRow") {
						sibling = node;
						searching = false;
					}
				}
			} else {
				searching = false;
			}
		}
		if(sibling != null) {
			parent = row.parentNode;
			parent.removeChild(sibling);
			parent.insertBefore(sibling, row);
		}
	}
}




function getListItemsIntoStore(logicId, form) {
	form['grid'] = document.getElementById("edit_grid"+logicId).checked;
	form['pairList'] = new Array();
	var keyItems = document.getElementsByName("edit_pairList_keys"+logicId),
		valueItems = document.getElementsByName("edit_pairList_values"+logicId),
		i, pair;
	for(i = 0; i < keyItems.length; i++) {
		pair = {};
		pair.key = keyItems[i].value;
		pair.value = valueItems[i].value;
		form['pairList'].push(pair);
	}
	return form;
}





	



function addLanguageRow( logicId, keyContent, valueContent ) {
	var newRowId = "langrow" + (new Date()).getTime(),
		parentNode = document.getElementById( "edit_pairList" + logicId ),
		newDiv = document.createElement("div"),
		buffer;

	newDiv.className = "pairListRow";
	parentNode.appendChild(newDiv);	
	buffer = '<div class="cv_record_list_item_key">'
		+'<select name="edit_pairList_keys'+logicId+'" id="'+newRowId+'"></select>'
		+'<input type="hidden" name="edit_pairList_values'+logicId+'" value="'+valueContent+'"/>'
		+'</div>'
		+'<div class="cv_record_list_item_value">'
		+'<div dojoType="dijit.form.HorizontalSlider" value="'+valueContent+'" minimum="1" maximum="5" discreteValues="5" intermediateChanges="true" showButtons="true" style="width:250px;" onChange="applyNewLanguageValue(this, \''+logicId+'\', arguments[0]);">'
		+'<ol dojoType="dijit.form.HorizontalRuleLabels" container="topDecoration" style="height:1.5em;font-size:75%;">'
		+'<li>1</li><li>2</li><li>3</li><li>4</li><li>5</li>'
		+'</ol>'
		+'</div>'
		+'</div>'
		+'<div class="cv_list_controls">'
		+'<a href="javascript:" onclick="removeListRow(this)"><img src="/image/icons/cross.gif"/></a> '
		+'<a href="javascript:" onclick="moveListRowUp(this)"><img src="/image/icons/arrow_up.gif"/></a> '
		+'<a href="javascript:" onclick="moveListRowDown(this)"><img src="/image/icons/arrow_down.gif"/></a> '
		+'</div>'
		+'<div class="clear"></div>'
	newDiv.innerHTML = buffer;
	dojo.parser.parse(parentNode);
	setLanguageList(getLocalizedString('locale.type'), newRowId, keyContent );
}


function cancelCVRecordLanguageEditBox( container, logicId ) {
	var parentNode = document.getElementById( "edit_pairList" + logicId ),
		i, hasMore, plainKeyCodeEl, plainValueCodeEl, newKeyContent, newValueContent;

	while( parentNode.hasChildNodes() ) {
		parentNode.removeChild(parentNode.firstChild);
	}
	
	hasMore = true;
	i = 0;
	while( hasMore ) {
		plainKeyCodeEl = document.getElementById( "plain_pairList["+i+"].keycode" + logicId );
		plainValueCodeEl = document.getElementById( "plain_pairList["+i+"].valuecode" + logicId );
		if( plainKeyCodeEl != null && plainValueCodeEl != null ) {
			newKeyContent = plainKeyCodeEl.value;
			newValueContent = plainValueCodeEl.value;
			addLanguageRow( logicId, newKeyContent, newValueContent );
			i++;
		} else {
			hasMore = false;
		}
	}
}







function getLanguageItemsIntoStore(logicId, form) {
	form['cvRecordType'] = 10;
	form['pairList'] = new Array();
	var keyItems = document.getElementsByName("edit_pairList_keys"+logicId),
		valueItems = document.getElementsByName("edit_pairList_values"+logicId),
		i, pair;
	for(i = 0; i < keyItems.length; i++) {
		pair = {};
		pair.key = keyItems[i].value;
		pair.value = valueItems[i].value;
		form['pairList'].push(pair);
	}
	return form;
}







function finishCVRecordLanguageEditBox(results) {
	if( finishAjaxEditBox( results ) ) {
		
		var parentNode = document.getElementById( "plain_pairList" + results.logicId ),
			buffer = '',
			keyItems = document.getElementsByName("edit_pairList_keys"+results.logicId),
			valueItems = document.getElementsByName("edit_pairList_values"+results.logicId),
			newIndex = 0,
			i, newKeyContent, newValueContent, newKeyContentResolved, newValueContentResolved;
		
		for (i = 0; i < keyItems.length; i++) {
			newKeyContent = keyItems[i].value;
			newValueContent = valueItems[i].value;
			if(newKeyContent!="" && newValueContent!="") {
				newKeyContentResolved = getLocalizedString("domain.helper.LANGUAGE."+newKeyContent);
				newValueContentResolved = getLocalizedString("domain.helper.LANGUAGE.level"+newValueContent);
				buffer = buffer + '<div>'
					+'<input type="hidden" id="plain_pairList['+newIndex+'].keycode'+results.logicId+'" value="'+newKeyContent+'" />'
					+'<input type="hidden" id="plain_pairList['+newIndex+'].valuecode'+results.logicId+'" value="'+newValueContent+'" />'
					+'<div id="plain_pairList['+newIndex+'].key'+results.logicId+'" class="cv_record_list_item_key">'+newKeyContentResolved+'</div>'
					+'<div id="plain_pairList['+newIndex+'].value'+results.logicId+'" class="cv_record_list_item_value">'+newValueContentResolved+'</div>'
					+'<div class="clear"></div>'
					+'</div>';
				newIndex++;
			}

		}
		parentNode.innerHTML = buffer;
		cancelCVRecordLanguageEditBox( results.container, results.logicId );
	}
	
}





function applyNewLanguageValue(slider, logicId, newValue) {
	var i, attr,
		row = getParentPairListRow(slider.domNode),
		elements = row.getElementsByTagName("input");

	for(i = 0; i < elements.length; i++) {
		attr = elements[i].getAttribute("name");
		if( attr != null && attr=="edit_pairList_values"+logicId) {
			elements[i].value = newValue;
			return;
		}
	}
}




function submitWizardPageJobRequest0() {
	return submitWizardPage(['earliestStartDate', 'latestStartDate', 'title'], '0');
}




function changeLabelCurrentOrganization(logicId) {
	var selection = document.getElementById("edit_candidateStatus"+logicId).value;
	document.getElementById("edit_label_currentOrganization").innerHTML = getLocalizedString("js.domain.user.currentOrganization."+selection);
	document.getElementById("plain_label_currentOrganization").innerHTML = getLocalizedString("js.domain.user.currentOrganization."+selection);
}


























/*** DWR engine *****/


/*
 * Copyright 2005 Joe Walker
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Declare an object to which we can add real functions.
 */
if (dwr == null) var dwr = {};
if (dwr.engine == null) dwr.engine = {};
if (DWREngine == null) var DWREngine = dwr.engine;

/**
 * Set an alternative error handler from the default alert box.
 * @see getahead.org/dwr/browser/engine/errors
 */
dwr.engine.setErrorHandler = function(handler) {
  dwr.engine._errorHandler = handler;
};

/**
 * Set an alternative warning handler from the default alert box.
 * @see getahead.org/dwr/browser/engine/errors
 */
dwr.engine.setWarningHandler = function(handler) {
  dwr.engine._warningHandler = handler;
};

/**
 * Setter for the text/html handler - what happens if a DWR request gets an HTML
 * reply rather than the expected Javascript. Often due to login timeout
 */
dwr.engine.setTextHtmlHandler = function(handler) {
  dwr.engine._textHtmlHandler = handler;
};

/**
 * Set a default timeout value for all calls. 0 (the default) turns timeouts off.
 * @see getahead.org/dwr/browser/engine/errors
 */
dwr.engine.setTimeout = function(timeout) {
  dwr.engine._timeout = timeout;
};

/**
 * The Pre-Hook is called before any DWR remoting is done.
 * @see getahead.org/dwr/browser/engine/hooks
 */
dwr.engine.setPreHook = function(handler) {
  dwr.engine._preHook = handler;
};

/**
 * The Post-Hook is called after any DWR remoting is done.
 * @see getahead.org/dwr/browser/engine/hooks
 */
dwr.engine.setPostHook = function(handler) {
  dwr.engine._postHook = handler;
};

/**
 * Custom headers for all DWR calls
 * @see getahead.org/dwr/????
 */
dwr.engine.setHeaders = function(headers) {
  dwr.engine._headers = headers;
};

/**
 * Custom parameters for all DWR calls
 * @see getahead.org/dwr/????
 */
dwr.engine.setParameters = function(parameters) {
  dwr.engine._parameters = parameters;
};

/** XHR remoting type constant. See dwr.engine.set[Rpc|Poll]Type() */
dwr.engine.XMLHttpRequest = 1;

/** XHR remoting type constant. See dwr.engine.set[Rpc|Poll]Type() */
dwr.engine.IFrame = 2;

/** XHR remoting type constant. See dwr.engine.setRpcType() */
dwr.engine.ScriptTag = 3;

/**
 * Set the preferred remoting type.
 * @param newType One of dwr.engine.XMLHttpRequest or dwr.engine.IFrame or dwr.engine.ScriptTag
 * @see getahead.org/dwr/browser/engine/options
 */
dwr.engine.setRpcType = function(newType) {
  if (newType != dwr.engine.XMLHttpRequest && newType != dwr.engine.IFrame && newType != dwr.engine.ScriptTag) {
    dwr.engine._handleError(null, { name:"dwr.engine.invalidRpcType", message:"RpcType must be one of dwr.engine.XMLHttpRequest or dwr.engine.IFrame or dwr.engine.ScriptTag" });
    return;
  }
  dwr.engine._rpcType = newType;
};

/**
 * Which HTTP method do we use to send results? Must be one of "GET" or "POST".
 * @see getahead.org/dwr/browser/engine/options
 */
dwr.engine.setHttpMethod = function(httpMethod) {
  if (httpMethod != "GET" && httpMethod != "POST") {
    dwr.engine._handleError(null, { name:"dwr.engine.invalidHttpMethod", message:"Remoting method must be one of GET or POST" });
    return;
  }
  dwr.engine._httpMethod = httpMethod;
};

/**
 * Ensure that remote calls happen in the order in which they were sent? (Default: false)
 * @see getahead.org/dwr/browser/engine/ordering
 */
dwr.engine.setOrdered = function(ordered) {
  dwr.engine._ordered = ordered;
};

/**
 * Do we ask the XHR object to be asynchronous? (Default: true)
 * @see getahead.org/dwr/browser/engine/options
 */
dwr.engine.setAsync = function(async) {
  dwr.engine._async = async;
};

/**
 * Does DWR poll the server for updates? (Default: false)
 * @see getahead.org/dwr/browser/engine/options
 */
dwr.engine.setActiveReverseAjax = function(activeReverseAjax) {
  if (activeReverseAjax) {
    // Bail if we are already started
    if (dwr.engine._activeReverseAjax) return;
    dwr.engine._activeReverseAjax = true;
    dwr.engine._poll();
  }
  else {
    // Can we cancel an existing request?
    if (dwr.engine._activeReverseAjax && dwr.engine._pollReq) dwr.engine._pollReq.abort();
    dwr.engine._activeReverseAjax = false;
  }
  // TODO: in iframe mode, if we start, stop, start then the second start may
  // well kick off a second iframe while the first is still about to return
  // we should cope with this but we don't
};

/**
 * The default message handler.
 * @see getahead.org/dwr/browser/engine/errors
 */
dwr.engine.defaultErrorHandler = function(message, ex) {
  dwr.engine._debug("Error: " + ex.name + ", " + ex.message, true);
  if (message == null || message == "") alert("A server error has occured.");
  // Ignore NS_ERROR_NOT_AVAILABLE if Mozilla is being narky
  else if (message.indexOf("0x80040111") != -1) dwr.engine._debug(message);
  else alert(message);
};

/**
 * The default warning handler.
 * @see getahead.org/dwr/browser/engine/errors
 */
dwr.engine.defaultWarningHandler = function(message, ex) {
  dwr.engine._debug(message);
};

/**
 * For reduced latency you can group several remote calls together using a batch.
 * @see getahead.org/dwr/browser/engine/batch
 */
dwr.engine.beginBatch = function() {
  if (dwr.engine._batch) {
    dwr.engine._handleError(null, { name:"dwr.engine.batchBegun", message:"Batch already begun" });
    return;
  }
  dwr.engine._batch = dwr.engine._createBatch();
};

/**
 * Finished grouping a set of remote calls together. Go and execute them all.
 * @see getahead.org/dwr/browser/engine/batch
 */
dwr.engine.endBatch = function(options) {
  var batch = dwr.engine._batch;
  if (batch == null) {
    dwr.engine._handleError(null, { name:"dwr.engine.batchNotBegun", message:"No batch in progress" });
    return;
  }
  dwr.engine._batch = null;
  if (batch.map.callCount == 0) return;

  // The hooks need to be merged carefully to preserve ordering
  if (options) dwr.engine._mergeBatch(batch, options);

  // In ordered mode, we don't send unless the list of sent items is empty
  if (dwr.engine._ordered && dwr.engine._batchesLength != 0) {
    dwr.engine._batchQueue[dwr.engine._batchQueue.length] = batch;
  }
  else {
    dwr.engine._sendData(batch);
  }
};

/** @deprecated */
dwr.engine.setPollMethod = function(type) { dwr.engine.setPollType(type); };
dwr.engine.setMethod = function(type) { dwr.engine.setRpcType(type); };
dwr.engine.setVerb = function(verb) { dwr.engine.setHttpMethod(verb); };
dwr.engine.setPollType = function() { dwr.engine._debug("Manually setting the Poll Type is not supported"); };

//==============================================================================
// Only private stuff below here
//==============================================================================

/** The original page id sent from the server */
dwr.engine._origScriptSessionId = "26D246C8089A3568128B3AA26F92EEE2";

/** The session cookie name */
dwr.engine._sessionCookieName = "JSESSIONID"; // JSESSIONID

/** Is GET enabled for the benefit of Safari? */
dwr.engine._allowGetForSafariButMakeForgeryEasier = "false";

/** The script prefix to strip in the case of scriptTagProtection. */
dwr.engine._scriptTagProtection = "throw 'allowScriptTagRemoting is false.';";

/** The default path to the DWR servlet */
dwr.engine._defaultPath = "/dwr";

/** Do we use XHR for reverse ajax because we are not streaming? */
dwr.engine._pollWithXhr = "false";

/** The read page id that we calculate */
dwr.engine._scriptSessionId = null;

/** The function that we use to fetch/calculate a session id */
dwr.engine._getScriptSessionId = function() {
  if (dwr.engine._scriptSessionId == null) {
    dwr.engine._scriptSessionId = dwr.engine._origScriptSessionId + Math.floor(Math.random() * 1000);
  }
  return dwr.engine._scriptSessionId;
};

/** A function to call if something fails. */
dwr.engine._errorHandler = dwr.engine.defaultErrorHandler;

/** For debugging when something unexplained happens. */
dwr.engine._warningHandler = dwr.engine.defaultWarningHandler;

/** A function to be called before requests are marshalled. Can be null. */
dwr.engine._preHook = null;

/** A function to be called after replies are received. Can be null. */
dwr.engine._postHook = null;

/** An map of the batches that we have sent and are awaiting a reply on. */
dwr.engine._batches = {};

/** A count of the number of outstanding batches. Should be == to _batches.length unless prototype has messed things up */
dwr.engine._batchesLength = 0;

/** In ordered mode, the array of batches waiting to be sent */
dwr.engine._batchQueue = [];

/** What is the default rpc type */
dwr.engine._rpcType = dwr.engine.XMLHttpRequest;

/** What is the default remoting method (ie GET or POST) */
dwr.engine._httpMethod = "POST";

/** Do we attempt to ensure that calls happen in the order in which they were sent? */
dwr.engine._ordered = false;

/** Do we make the calls async? */
dwr.engine._async = true;

/** The current batch (if we are in batch mode) */
dwr.engine._batch = null;

/** The global timeout */
dwr.engine._timeout = 0;

/** ActiveX objects to use when we want to convert an xml string into a DOM object. */
dwr.engine._DOMDocument = ["Msxml2.DOMDocument.6.0", "Msxml2.DOMDocument.5.0", "Msxml2.DOMDocument.4.0", "Msxml2.DOMDocument.3.0", "MSXML2.DOMDocument", "MSXML.DOMDocument", "Microsoft.XMLDOM"];

/** The ActiveX objects to use when we want to do an XMLHttpRequest call. */
dwr.engine._XMLHTTP = ["Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.5.0", "Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"];

/** Are we doing comet or polling? */
dwr.engine._activeReverseAjax = false;

/** The iframe that we are using to poll */
dwr.engine._outstandingIFrames = [];

/** The xhr object that we are using to poll */
dwr.engine._pollReq = null;

/** How many milliseconds between internal comet polls */
dwr.engine._pollCometInterval = 200;

/** How many times have we re-tried to poll? */
dwr.engine._pollRetries = 0;
dwr.engine._maxPollRetries = 0;

/** Do we do a document.reload if we get a text/html reply? */
dwr.engine._textHtmlHandler = null;

/** If you wish to send custom headers with every request */
dwr.engine._headers = null;

/** If you wish to send extra custom request parameters with each request */
dwr.engine._parameters = null;

/** Undocumented interceptors - do not use */
dwr.engine._postSeperator = "\n";
dwr.engine._defaultInterceptor = function(data) { return data; };
dwr.engine._urlRewriteHandler = dwr.engine._defaultInterceptor;
dwr.engine._contentRewriteHandler = dwr.engine._defaultInterceptor;
dwr.engine._replyRewriteHandler = dwr.engine._defaultInterceptor;

/** Batch ids allow us to know which batch the server is answering */
dwr.engine._nextBatchId = 0;

/** A list of the properties that need merging from calls to a batch */
dwr.engine._propnames = [ "rpcType", "httpMethod", "async", "timeout", "errorHandler", "warningHandler", "textHtmlHandler" ];

/** Do we stream, or can be hacked to do so? */
dwr.engine._partialResponseNo = 0;
dwr.engine._partialResponseYes = 1;
dwr.engine._partialResponseFlush = 2;

/** Is this page in the process of unloading? */
dwr.engine._unloading = false;

/**
 * @private Send a request. Called by the Javascript interface stub
 * @param path part of URL after the host and before the exec bit without leading or trailing /s
 * @param scriptName The class to execute
 * @param methodName The method on said class to execute
 * @param func The callback function to which any returned data should be passed
 *       if this is null, any returned data will be ignored
 * @param vararg_params The parameters to pass to the above class
 */
dwr.engine._execute = function(path, scriptName, methodName, vararg_params) {
  var singleShot = false;
  if (dwr.engine._batch == null) {
    dwr.engine.beginBatch();
    singleShot = true;
  }
  var batch = dwr.engine._batch;
  // To make them easy to manipulate we copy the arguments into an args array
  var args = [];
  for (var i = 0; i < arguments.length - 3; i++) {
    args[i] = arguments[i + 3];
  }
  // All the paths MUST be to the same servlet
  if (batch.path == null) {
    batch.path = path;
  }
  else {
    if (batch.path != path) {
      dwr.engine._handleError(batch, { name:"dwr.engine.multipleServlets", message:"Can't batch requests to multiple DWR Servlets." });
      return;
    }
  }
  // From the other params, work out which is the function (or object with
  // call meta-data) and which is the call parameters
  var callData;
  var lastArg = args[args.length - 1];
  if (typeof lastArg == "function" || lastArg == null) callData = { callback:args.pop() };
  else callData = args.pop();

  // Merge from the callData into the batch
  dwr.engine._mergeBatch(batch, callData);
  batch.handlers[batch.map.callCount] = {
    exceptionHandler:callData.exceptionHandler,
    callback:callData.callback
  };

  // Copy to the map the things that need serializing
  var prefix = "c" + batch.map.callCount + "-";
  batch.map[prefix + "scriptName"] = scriptName;
  batch.map[prefix + "methodName"] = methodName;
  batch.map[prefix + "id"] = batch.map.callCount;
  for (i = 0; i < args.length; i++) {
    dwr.engine._serializeAll(batch, [], args[i], prefix + "param" + i);
  }

  // Now we have finished remembering the call, we incr the call count
  batch.map.callCount++;
  if (singleShot) dwr.engine.endBatch();
};

/** @private Poll the server to see if there is any data waiting */
dwr.engine._poll = function() {
  if (!dwr.engine._activeReverseAjax) return;

  var batch = dwr.engine._createBatch();
  batch.map.id = 0; // TODO: Do we need this??
  batch.map.callCount = 1;
  batch.isPoll = true;
  if (dwr.engine._pollWithXhr == "true") {
    batch.rpcType = dwr.engine.XMLHttpRequest;
    batch.map.partialResponse = dwr.engine._partialResponseNo;
  }
  else {
    if (navigator.userAgent.indexOf("Gecko/") != -1) {
      batch.rpcType = dwr.engine.XMLHttpRequest;
      batch.map.partialResponse = dwr.engine._partialResponseYes;
    }
    else {
      batch.rpcType = dwr.engine.XMLHttpRequest;
      batch.map.partialResponse = dwr.engine._partialResponseNo;
    }
  }
  batch.httpMethod = "POST";
  batch.async = true;
  batch.timeout = 0;
  batch.path = dwr.engine._defaultPath;
  batch.preHooks = [];
  batch.postHooks = [];
  batch.errorHandler = dwr.engine._pollErrorHandler;
  batch.warningHandler = dwr.engine._pollErrorHandler;
  batch.handlers[0] = {
    callback:function(pause) {
      dwr.engine._pollRetries = 0;
      setTimeout(dwr.engine._poll, pause);
    }
  };

  // Send the data
  dwr.engine._sendData(batch);
  if (batch.rpcType == dwr.engine.XMLHttpRequest && batch.map.partialResponse == dwr.engine._partialResponseYes) {
    dwr.engine._checkCometPoll();
  }
};

/** Try to recover from polling errors */
dwr.engine._pollErrorHandler = function(msg, ex) {
  // if anything goes wrong then just silently try again (up to 3x) after 10s
  dwr.engine._pollRetries++;
  dwr.engine._debug("Reverse Ajax poll failed (pollRetries=" + dwr.engine._pollRetries + "): " + ex.name + " : " + ex.message);
  if (dwr.engine._pollRetries < dwr.engine._maxPollRetries) {
    setTimeout(dwr.engine._poll, 10000);
  }
  else {
    dwr.engine._activeReverseAjax = false;
    dwr.engine._debug("Giving up.");
  }
};

/** @private Generate a new standard batch */
dwr.engine._createBatch = function() {
  var batch = {
    map:{
      callCount:0,
      page:window.location.pathname + window.location.search,
      httpSessionId:dwr.engine._getJSessionId(),
      scriptSessionId:dwr.engine._getScriptSessionId()
    },
    charsProcessed:0, paramCount:0,
    parameters:{}, headers:{},
    isPoll:false, handlers:{}, preHooks:[], postHooks:[],
    rpcType:dwr.engine._rpcType,
    httpMethod:dwr.engine._httpMethod,
    async:dwr.engine._async,
    timeout:dwr.engine._timeout,
    errorHandler:dwr.engine._errorHandler,
    warningHandler:dwr.engine._warningHandler,
    textHtmlHandler:dwr.engine._textHtmlHandler
  };
  if (dwr.engine._preHook) batch.preHooks.push(dwr.engine._preHook);
  if (dwr.engine._postHook) batch.postHooks.push(dwr.engine._postHook);
  var propname, data;
  if (dwr.engine._headers) {
    for (propname in dwr.engine._headers) {
      data = dwr.engine._headers[propname];
      if (typeof data != "function") batch.headers[propname] = data;
    }
  }
  if (dwr.engine._parameters) {
    for (propname in dwr.engine._parameters) {
      data = dwr.engine._parameters[propname];
      if (typeof data != "function") batch.parameters[propname] = data;
    }
  }
  return batch;
};

/** @private Take further options and merge them into */
dwr.engine._mergeBatch = function(batch, overrides) {
  var propname, data;
  for (var i = 0; i < dwr.engine._propnames.length; i++) {
    propname = dwr.engine._propnames[i];
    if (overrides[propname] != null) batch[propname] = overrides[propname];
  }
  if (overrides.preHook != null) batch.preHooks.unshift(overrides.preHook);
  if (overrides.postHook != null) batch.postHooks.push(overrides.postHook);
  if (overrides.headers) {
    for (propname in overrides.headers) {
      data = overrides.headers[propname];
      if (typeof data != "function") batch.headers[propname] = data;
    }
  }
  if (overrides.parameters) {
    for (propname in overrides.parameters) {
      data = overrides.parameters[propname];
      if (typeof data != "function") batch.map["p-" + propname] = "" + data;
    }
  }
};

/** @private What is our session id? */
dwr.engine._getJSessionId =  function() {
  var cookies = document.cookie.split(';');
  for (var i = 0; i < cookies.length; i++) {
    var cookie = cookies[i];
    while (cookie.charAt(0) == ' ') cookie = cookie.substring(1, cookie.length);
    if (cookie.indexOf(dwr.engine._sessionCookieName + "=") == 0) {
      return cookie.substring(dwr.engine._sessionCookieName.length + 1, cookie.length);
    }
  }
  return "";
};

/** @private Check for reverse Ajax activity */
dwr.engine._checkCometPoll = function() {
  for (var i = 0; i < dwr.engine._outstandingIFrames.length; i++) {
    var text = "";
    var iframe = dwr.engine._outstandingIFrames[i];
    try {
      text = dwr.engine._getTextFromCometIFrame(iframe);
    }
    catch (ex) {
      dwr.engine._handleWarning(iframe.batch, ex);
    }
    if (text != "") dwr.engine._processCometResponse(text, iframe.batch);
  }
  if (dwr.engine._pollReq) {
    var req = dwr.engine._pollReq;
    var text = req.responseText;
    if (text != null) dwr.engine._processCometResponse(text, req.batch);
  }

  // If the poll resources are still there, come back again
  if (dwr.engine._outstandingIFrames.length > 0 || dwr.engine._pollReq) {
    setTimeout(dwr.engine._checkCometPoll, dwr.engine._pollCometInterval);
  }
};

/** @private Extract the whole (executed an all) text from the current iframe */
dwr.engine._getTextFromCometIFrame = function(frameEle) {
  var body = frameEle.contentWindow.document.body;
  if (body == null) return "";
  var text = body.innerHTML;
  // We need to prevent IE from stripping line feeds
  if (text.indexOf("<PRE>") == 0 || text.indexOf("<pre>") == 0) {
    text = text.substring(5, text.length - 7);
  }
  return text;
};

/** @private Some more text might have come in, test and execute the new stuff */
dwr.engine._processCometResponse = function(response, batch) {
  if (batch.charsProcessed == response.length) return;
  if (response.length == 0) {
    batch.charsProcessed = 0;
    return;
  }

  var firstStartTag = response.indexOf("//#DWR-START#", batch.charsProcessed);
  if (firstStartTag == -1) {
    // dwr.engine._debug("No start tag (search from " + batch.charsProcessed + "). skipping '" + response.substring(batch.charsProcessed) + "'");
    batch.charsProcessed = response.length;
    return;
  }
  // if (firstStartTag > 0) {
  //   dwr.engine._debug("Start tag not at start (search from " + batch.charsProcessed + "). skipping '" + response.substring(batch.charsProcessed, firstStartTag) + "'");
  // }

  var lastEndTag = response.lastIndexOf("//#DWR-END#");
  if (lastEndTag == -1) {
    // dwr.engine._debug("No end tag. unchanged charsProcessed=" + batch.charsProcessed);
    return;
  }

  // Skip the end tag too for next time, remembering CR and LF
  if (response.charCodeAt(lastEndTag + 11) == 13 && response.charCodeAt(lastEndTag + 12) == 10) {
    batch.charsProcessed = lastEndTag + 13;
  }
  else {
    batch.charsProcessed = lastEndTag + 11;
  }

  var exec = response.substring(firstStartTag + 13, lastEndTag);

  dwr.engine._receivedBatch = batch;
  dwr.engine._eval(exec);
  dwr.engine._receivedBatch = null;
};

/** @private Actually send the block of data in the batch object. */
dwr.engine._sendData = function(batch) {
  batch.map.batchId = dwr.engine._nextBatchId;
  dwr.engine._nextBatchId++;
  dwr.engine._batches[batch.map.batchId] = batch;
  dwr.engine._batchesLength++;
  batch.completed = false;

  for (var i = 0; i < batch.preHooks.length; i++) {
    batch.preHooks[i]();
  }
  batch.preHooks = null;
  // Set a timeout
  if (batch.timeout && batch.timeout != 0) {
    batch.timeoutId = setTimeout(function() { dwr.engine._abortRequest(batch); }, batch.timeout);
  }
  // Get setup for XMLHttpRequest if possible
  if (batch.rpcType == dwr.engine.XMLHttpRequest) {
    if (window.XMLHttpRequest) {
      batch.req = new XMLHttpRequest();
    }
    // IE5 for the mac claims to support window.ActiveXObject, but throws an error when it's used
    else if (window.ActiveXObject && !(navigator.userAgent.indexOf("Mac") >= 0 && navigator.userAgent.indexOf("MSIE") >= 0)) {
      batch.req = dwr.engine._newActiveXObject(dwr.engine._XMLHTTP);
    }
  }

  var prop, request;
  if (batch.req) {
    // Proceed using XMLHttpRequest
    if (batch.async) {
      batch.req.onreadystatechange = function() {
        if (typeof dwr != 'undefined') dwr.engine._stateChange(batch);
      };
    }
    // If we're polling, record this for monitoring
    if (batch.isPoll) {
      dwr.engine._pollReq = batch.req;
      // In IE XHR is an ActiveX control so you can't augment it like this
      if (!(document.all && !window.opera)) batch.req.batch = batch;
    }
    // Workaround for Safari 1.x POST bug
    var indexSafari = navigator.userAgent.indexOf("Safari/");
    if (indexSafari >= 0) {
      var version = navigator.userAgent.substring(indexSafari + 7);
      if (parseInt(version, 10) < 400) {
        if (dwr.engine._allowGetForSafariButMakeForgeryEasier == "true") batch.httpMethod = "GET";
        else dwr.engine._handleWarning(batch, { name:"dwr.engine.oldSafari", message:"Safari GET support disabled. See getahead.org/dwr/server/servlet and allowGetForSafariButMakeForgeryEasier." });
      }
    }
    batch.mode = batch.isPoll ? dwr.engine._ModePlainPoll : dwr.engine._ModePlainCall;
    request = dwr.engine._constructRequest(batch);
    try {
      batch.req.open(batch.httpMethod, request.url, batch.async);
      try {
        for (prop in batch.headers) {
          var value = batch.headers[prop];
          if (typeof value == "string") batch.req.setRequestHeader(prop, value);
        }
        if (!batch.headers["Content-Type"]) batch.req.setRequestHeader("Content-Type", "text/plain");
      }
      catch (ex) {
        dwr.engine._handleWarning(batch, ex);
      }
      batch.req.send(request.body);
      if (!batch.async) dwr.engine._stateChange(batch);
    }
    catch (ex) {
      dwr.engine._handleError(batch, ex);
    }
  }
  else if (batch.rpcType != dwr.engine.ScriptTag) {
    var idname = batch.isPoll ? "dwr-if-poll-" + batch.map.batchId : "dwr-if-" + batch.map.batchId;
    // Removed htmlfile implementation. Don't expect it to return before v3
    batch.div = document.createElement("div");
    // Add the div to the document first, otherwise IE 6 will ignore onload handler.
    document.body.appendChild(batch.div);
    batch.div.innerHTML = "<iframe src='javascript:void(0)' frameborder='0' style='width:0px;height:0px;border:0;' id='" + idname + "' name='" + idname + "' onload='dwr.engine._iframeLoadingComplete (" + batch.map.batchId + ");'></iframe>";
    batch.document = document;
    batch.iframe = batch.document.getElementById(idname);
    batch.iframe.batch = batch;
    batch.mode = batch.isPoll ? dwr.engine._ModeHtmlPoll : dwr.engine._ModeHtmlCall;
    if (batch.isPoll) dwr.engine._outstandingIFrames.push(batch.iframe);
    request = dwr.engine._constructRequest(batch);
    if (batch.httpMethod == "GET") {
      batch.iframe.setAttribute("src", request.url);
    }
    else {
      batch.form = batch.document.createElement("form");
      batch.form.setAttribute("id", "dwr-form");
      batch.form.setAttribute("action", request.url);
      batch.form.setAttribute("style", "display:none;");
      batch.form.setAttribute("target", idname);
      batch.form.target = idname;
      batch.form.setAttribute("method", batch.httpMethod);
      for (prop in batch.map) {
        var value = batch.map[prop];
        if (typeof value != "function") {
          var formInput = batch.document.createElement("input");
          formInput.setAttribute("type", "hidden");
          formInput.setAttribute("name", prop);
          formInput.setAttribute("value", value);
          batch.form.appendChild(formInput);
        }
      }
      batch.document.body.appendChild(batch.form);
      batch.form.submit();
    }
  }
  else {
    batch.httpMethod = "GET"; // There's no such thing as ScriptTag using POST
    batch.mode = batch.isPoll ? dwr.engine._ModePlainPoll : dwr.engine._ModePlainCall;
    request = dwr.engine._constructRequest(batch);
    batch.script = document.createElement("script");
    batch.script.id = "dwr-st-" + batch.map["c0-id"];
    batch.script.src = request.url;
    document.body.appendChild(batch.script);
  }
};

dwr.engine._ModePlainCall = "/call/plaincall/";
dwr.engine._ModeHtmlCall = "/call/htmlcall/";
dwr.engine._ModePlainPoll = "/call/plainpoll/";
dwr.engine._ModeHtmlPoll = "/call/htmlpoll/";

/** @private Work out what the URL should look like */
dwr.engine._constructRequest = function(batch) {
  // A quick string to help people that use web log analysers
  var request = { url:batch.path + batch.mode, body:null };
  if (batch.isPoll == true) {
    request.url += "ReverseAjax.dwr";
  }
  else if (batch.map.callCount == 1) {
    request.url += batch.map["c0-scriptName"] + "." + batch.map["c0-methodName"] + ".dwr";
  }
  else {
    request.url += "Multiple." + batch.map.callCount + ".dwr";
  }
  // Play nice with url re-writing
  var sessionMatch = location.href.match(/jsessionid=([^?]+)/);
  if (sessionMatch != null) {
    request.url += ";jsessionid=" + sessionMatch[1];
  }

  var prop;
  if (batch.httpMethod == "GET") {
    // Some browsers (Opera/Safari2) seem to fail to convert the callCount value
    // to a string in the loop below so we do it manually here.
    batch.map.callCount = "" + batch.map.callCount;
    request.url += "?";
    for (prop in batch.map) {
      if (typeof batch.map[prop] != "function") {
        request.url += encodeURIComponent(prop) + "=" + encodeURIComponent(batch.map[prop]) + "&";
      }
    }
    request.url = request.url.substring(0, request.url.length - 1);
  }
  else {
    // PERFORMANCE: for iframe mode this is thrown away.
    request.body = "";
    if (document.all && !window.opera) {
      // Use array joining on IE (fastest)
      var buf = [];
      for (prop in batch.map) {
        if (typeof batch.map[prop] != "function") {
          buf.push(prop + "=" + batch.map[prop] + dwr.engine._postSeperator);
        }
      }
      request.body = buf.join("");
    }
    else {
      // Use string concat on other browsers (fastest)
      for (prop in batch.map) {
        if (typeof batch.map[prop] != "function") {
          request.body += prop + "=" + batch.map[prop] + dwr.engine._postSeperator;
        }
      }
    }
    request.body = dwr.engine._contentRewriteHandler(request.body);
  }
  request.url = dwr.engine._urlRewriteHandler(request.url);
  return request;
};

/** @private Called by XMLHttpRequest to indicate that something has happened */
dwr.engine._stateChange = function(batch) {
  var toEval;

  if (batch.completed) {
    dwr.engine._debug("Error: _stateChange() with batch.completed");
    return;
  }

  var req = batch.req;
  try {
    if (req.readyState != 4) return;
  }
  catch (ex) {
    dwr.engine._handleWarning(batch, ex);
    // It's broken - clear up and forget this call
    dwr.engine._clearUp(batch);
    return;
  }

  if (dwr.engine._unloading) {
    dwr.engine._debug("Ignoring reply from server as page is unloading.");
    return;
  }
  
  try {
    var reply = req.responseText;
    reply = dwr.engine._replyRewriteHandler(reply);
    var status = req.status; // causes Mozilla to except on page moves

    if (reply == null || reply == "") {
      dwr.engine._handleWarning(batch, { name:"dwr.engine.missingData", message:"No data received from server" });
    }
    else if (status != 200) {
      dwr.engine._handleError(batch, { name:"dwr.engine.http." + status, message:req.statusText });
    }
    else {
      var contentType = req.getResponseHeader("Content-Type");
      if (!contentType.match(/^text\/plain/) && !contentType.match(/^text\/javascript/)) {
        if (contentType.match(/^text\/html/) && typeof batch.textHtmlHandler == "function") {
          batch.textHtmlHandler({ status:status, responseText:reply, contentType:contentType });
        }
        else {
          dwr.engine._handleWarning(batch, { name:"dwr.engine.invalidMimeType", message:"Invalid content type: '" + contentType + "'" });
        }
      }
      else {
        // Comet replies might have already partially executed
        if (batch.isPoll && batch.map.partialResponse == dwr.engine._partialResponseYes) {
          dwr.engine._processCometResponse(reply, batch);
        }
        else {
          if (reply.search("//#DWR") == -1) {
            dwr.engine._handleWarning(batch, { name:"dwr.engine.invalidReply", message:"Invalid reply from server" });
          }
          else {
            toEval = reply;
          }
        }
      }
    }
  }
  catch (ex) {
    dwr.engine._handleWarning(batch, ex);
  }

  dwr.engine._callPostHooks(batch);

  // Outside of the try/catch so errors propogate normally:
  dwr.engine._receivedBatch = batch;
  if (toEval != null) toEval = toEval.replace(dwr.engine._scriptTagProtection, "");
  dwr.engine._eval(toEval);
  dwr.engine._receivedBatch = null;
  dwr.engine._validateBatch(batch);
  if (!batch.completed) dwr.engine._clearUp(batch);
};

/**
 * @private This function is invoked when a batch reply is received.
 * It checks that there is a response for every call in the batch. Otherwise,
 * an error will be signaled (a call without a response indicates that the 
 * server failed to send complete batch response). 
 */
dwr.engine._validateBatch = function(batch) {
  // If some call left unreplied, report an error.
  if (!batch.completed) {
    for (var i = 0; i < batch.map.callCount; i++) {
      if (batch.handlers[i] != null) {
        dwr.engine._handleWarning(batch, { name:"dwr.engine.incompleteReply", message:"Incomplete reply from server" });
        break;
      }
    }
  }
}

/** @private Called from iframe onload, check batch using batch-id */
dwr.engine._iframeLoadingComplete = function(batchId) {
  // dwr.engine._checkCometPoll();
  var batch = dwr.engine._batches[batchId];
  if (batch) dwr.engine._validateBatch(batch);
}

/** @private Called by the server: Execute a callback */
dwr.engine._remoteHandleCallback = function(batchId, callId, reply) {
  var batch = dwr.engine._batches[batchId];
  if (batch == null) {
    dwr.engine._debug("Warning: batch == null in remoteHandleCallback for batchId=" + batchId, true);
    return;
  }
  // Error handlers inside here indicate an error that is nothing to do
  // with DWR so we handle them differently.
  try {
    var handlers = batch.handlers[callId];
    batch.handlers[callId] = null;
    if (!handlers) {
      dwr.engine._debug("Warning: Missing handlers. callId=" + callId, true);
    }
    else if (typeof handlers.callback == "function") handlers.callback(reply);
  }
  catch (ex) {
    dwr.engine._handleError(batch, ex);
  }
};

/** @private Called by the server: Handle an exception for a call */
dwr.engine._remoteHandleException = function(batchId, callId, ex) {
  var batch = dwr.engine._batches[batchId];
  if (batch == null) { dwr.engine._debug("Warning: null batch in remoteHandleException", true); return; }
  var handlers = batch.handlers[callId];
  batch.handlers[callId] = null;
  if (handlers == null) { dwr.engine._debug("Warning: null handlers in remoteHandleException", true); return; }
  if (ex.message == undefined) ex.message = "";
  if (typeof handlers.exceptionHandler == "function") handlers.exceptionHandler(ex.message, ex);
  else if (typeof batch.errorHandler == "function") batch.errorHandler(ex.message, ex);
};

/** @private Called by the server: The whole batch is broken */
dwr.engine._remoteHandleBatchException = function(ex, batchId) {
  var searchBatch = (dwr.engine._receivedBatch == null && batchId != null);
  if (searchBatch) {
    dwr.engine._receivedBatch = dwr.engine._batches[batchId];
  }
  if (ex.message == undefined) ex.message = "";
  dwr.engine._handleError(dwr.engine._receivedBatch, ex);
  if (searchBatch) {
    dwr.engine._receivedBatch = null;
    dwr.engine._clearUp(dwr.engine._batches[batchId]);
  }
};

/** @private Called by the server: Reverse ajax should not be used */
dwr.engine._remotePollCometDisabled = function(ex, batchId) {
  dwr.engine.setActiveReverseAjax(false);
  var searchBatch = (dwr.engine._receivedBatch == null && batchId != null);
  if (searchBatch) {
    dwr.engine._receivedBatch = dwr.engine._batches[batchId];
  }
  if (ex.message == undefined) ex.message = "";
  dwr.engine._handleError(dwr.engine._receivedBatch, ex);
  if (searchBatch) {
    dwr.engine._receivedBatch = null;
    dwr.engine._clearUp(dwr.engine._batches[batchId]);
  }
};

/** @private Called by the server: An IFrame reply is about to start */
dwr.engine._remoteBeginIFrameResponse = function(iframe, batchId) {
  if (iframe != null) dwr.engine._receivedBatch = iframe.batch;
  dwr.engine._callPostHooks(dwr.engine._receivedBatch);
};

/** @private Called by the server: An IFrame reply is just completing */
dwr.engine._remoteEndIFrameResponse = function(batchId) {
  dwr.engine._clearUp(dwr.engine._receivedBatch);
  dwr.engine._receivedBatch = null;
};

/** @private This is a hack to make the context be this window */
dwr.engine._eval = function(script) {
  if (script == null) return null;
  if (script == "") { dwr.engine._debug("Warning: blank script", true); return null; }
  // dwr.engine._debug("Exec: [" + script + "]", true);
  return eval(script);
};

/** @private Called as a result of a request timeout */
dwr.engine._abortRequest = function(batch) {
  if (batch && !batch.completed) {
    dwr.engine._clearUp(batch);
    if (batch.req) batch.req.abort();
    dwr.engine._handleError(batch, { name:"dwr.engine.timeout", message:"Timeout" });
  }
};

/** @private call all the post hooks for a batch */
dwr.engine._callPostHooks = function(batch) {
  if (batch.postHooks) {
    for (var i = 0; i < batch.postHooks.length; i++) {
      batch.postHooks[i]();
    }
    batch.postHooks = null;
  }
};

/** @private A call has finished by whatever means and we need to shut it all down. */
dwr.engine._clearUp = function(batch) {
  if (!batch) { dwr.engine._debug("Warning: null batch in dwr.engine._clearUp()", true); return; }
  if (batch.completed) { dwr.engine._debug("Warning: Double complete", true); return; }

  // IFrame tidyup
  if (batch.div) batch.div.parentNode.removeChild(batch.div);
  if (batch.iframe) {
    // If this is a poll frame then stop comet polling
    for (var i = 0; i < dwr.engine._outstandingIFrames.length; i++) {
      if (dwr.engine._outstandingIFrames[i] == batch.iframe) {
        dwr.engine._outstandingIFrames.splice(i, 1);
      }
    }
    batch.iframe.parentNode.removeChild(batch.iframe);
  }
  if (batch.form) batch.form.parentNode.removeChild(batch.form);

  // XHR tidyup: avoid IE handles increase
  if (batch.req) {
    // If this is a poll frame then stop comet polling
    if (batch.req == dwr.engine._pollReq) dwr.engine._pollReq = null;
    delete batch.req;
  }

  // Timeout tidyup
  if (batch.timeoutId) {
    clearTimeout(batch.timeoutId);
    delete batch.timeoutId;
  }

  if (batch.map && (batch.map.batchId || batch.map.batchId == 0)) {
    delete dwr.engine._batches[batch.map.batchId];
    dwr.engine._batchesLength--;
  }

  batch.completed = true;

  // If there is anything on the queue waiting to go out, then send it.
  // We don't need to check for ordered mode, here because when ordered mode
  // gets turned off, we still process *waiting* batches in an ordered way.
  if (dwr.engine._batchQueue.length != 0) {
    var sendbatch = dwr.engine._batchQueue.shift();
    dwr.engine._sendData(sendbatch);
  }
};

/** @private Abort any XHRs in progress at page unload (solves zombie socket problems in IE). */
dwr.engine._unloader = function() {
  dwr.engine._unloading = true;

  // Empty queue of waiting ordered requests
  dwr.engine._batchQueue.length = 0;

  // Abort any ongoing XHRs and clear their batches
  for (var batchId in dwr.engine._batches) {
    var batch = dwr.engine._batches[batchId];
    // Only process objects that look like batches (avoid prototype additions!)
    if (batch && batch.map) {
      if (batch.req) {
        batch.req.abort();
      }
      dwr.engine._clearUp(batch);
    }
  }
};
// Now register the unload handler
if (window.addEventListener) window.addEventListener('unload', dwr.engine._unloader, false);
else if (window.attachEvent) window.attachEvent('onunload', dwr.engine._unloader);

/** @private Generic error handling routing to save having null checks everywhere */
dwr.engine._handleError = function(batch, ex) {
  if (typeof ex == "string") ex = { name:"unknown", message:ex };
  if (ex.message == null) ex.message = "";
  if (ex.name == null) ex.name = "unknown";
  if (batch && typeof batch.errorHandler == "function") batch.errorHandler(ex.message, ex);
  else if (dwr.engine._errorHandler) dwr.engine._errorHandler(ex.message, ex);
  if (batch) dwr.engine._clearUp(batch);
};

/** @private Generic error handling routing to save having null checks everywhere */
dwr.engine._handleWarning = function(batch, ex) {
  if (typeof ex == "string") ex = { name:"unknown", message:ex };
  if (ex.message == null) ex.message = "";
  if (ex.name == null) ex.name = "unknown";
  if (batch && typeof batch.warningHandler == "function") batch.warningHandler(ex.message, ex);
  else if (dwr.engine._warningHandler) dwr.engine._warningHandler(ex.message, ex);
  if (batch) dwr.engine._clearUp(batch);
};

/**
 * @private Marshall a data item
 * @param batch A map of variables to how they have been marshalled
 * @param referto An array of already marshalled variables to prevent recurrsion
 * @param data The data to be marshalled
 * @param name The name of the data being marshalled
 */
dwr.engine._serializeAll = function(batch, referto, data, name) {
  if (data == null) {
    batch.map[name] = "null:null";
    return;
  }

  switch (typeof data) {
  case "boolean":
    batch.map[name] = "boolean:" + data;
    break;
  case "number":
    batch.map[name] = "number:" + data;
    break;
  case "string":
    batch.map[name] = "string:" + encodeURIComponent(data);
    break;
  case "object":
    if (data instanceof String) batch.map[name] = "String:" + encodeURIComponent(data);
    else if (data instanceof Boolean) batch.map[name] = "Boolean:" + data;
    else if (data instanceof Number) batch.map[name] = "Number:" + data;
    else if (data instanceof Date) batch.map[name] = "Date:" + data.getTime();
    else if (data && data.join) batch.map[name] = dwr.engine._serializeArray(batch, referto, data, name);
    else batch.map[name] = dwr.engine._serializeObject(batch, referto, data, name);
    break;
  case "function":
    // We just ignore functions.
    break;
  default:
    dwr.engine._handleWarning(null, { name:"dwr.engine.unexpectedType", message:"Unexpected type: " + typeof data + ", attempting default converter." });
    batch.map[name] = "default:" + data;
    break;
  }
};

/** @private Have we already converted this object? */
dwr.engine._lookup = function(referto, data, name) {
  var lookup;
  // Can't use a map: getahead.org/ajax/javascript-gotchas
  for (var i = 0; i < referto.length; i++) {
    if (referto[i].data == data) {
      lookup = referto[i];
      break;
    }
  }
  if (lookup) return "reference:" + lookup.name;
  referto.push({ data:data, name:name });
  return null;
};

/** @private Marshall an object */
dwr.engine._serializeObject = function(batch, referto, data, name) {
  var ref = dwr.engine._lookup(referto, data, name);
  if (ref) return ref;

  // This check for an HTML is not complete, but is there a better way?
  // Maybe we should add: data.hasChildNodes typeof "function" == true
  if (data.nodeName && data.nodeType) {
    return dwr.engine._serializeXml(batch, referto, data, name);
  }

  // treat objects as an associative arrays
  var reply = "Object_" + dwr.engine._getObjectClassName(data) + ":{";
  var element;
  for (element in data) {
    if (typeof data[element] != "function") {
      batch.paramCount++;
      var childName = "c" + dwr.engine._batch.map.callCount + "-e" + batch.paramCount;
      dwr.engine._serializeAll(batch, referto, data[element], childName);

      reply += encodeURIComponent(element) + ":reference:" + childName + ", ";
    }
  }

  if (reply.substring(reply.length - 2) == ", ") {
    reply = reply.substring(0, reply.length - 2);
  }
  reply += "}";

  return reply;
};

/** @private Returns the classname of supplied argument obj */
dwr.engine._errorClasses = { "Error":Error, "EvalError":EvalError, "RangeError":RangeError, "ReferenceError":ReferenceError, "SyntaxError":SyntaxError, "TypeError":TypeError, "URIError":URIError };
dwr.engine._getObjectClassName = function(obj) {
  // Try to find the classname by stringifying the object's constructor
  // and extract <class> from "function <class>".
  if (obj && obj.constructor && obj.constructor.toString)
  {
    var str = obj.constructor.toString();
    var regexpmatch = str.match(/function\s+(\w+)/);
    if (regexpmatch && regexpmatch.length == 2) {
      return regexpmatch[1];
    }
  }

  // Now manually test against the core Error classes, as these in some 
  // browsers successfully match to the wrong class in the 
  // Object.toString() test we will do later
  if (obj && obj.constructor) {
	for (var errorname in dwr.engine._errorClasses) {
      if (obj.constructor == dwr.engine._errorClasses[errorname]) return errorname;
    }
  }

  // Try to find the classname by calling Object.toString() on the object
  // and extracting <class> from "[object <class>]"
  if (obj) {
    var str = Object.prototype.toString.call(obj);
    var regexpmatch = str.match(/\[object\s+(\w+)/);
    if (regexpmatch && regexpmatch.length==2) {
      return regexpmatch[1];
    }
  }

  // Supplied argument was probably not an object, but what is better?
  return "Object";
};

/** @private Marshall an object */
dwr.engine._serializeXml = function(batch, referto, data, name) {
  var ref = dwr.engine._lookup(referto, data, name);
  if (ref) return ref;

  var output;
  if (window.XMLSerializer) output = new XMLSerializer().serializeToString(data);
  else if (data.toXml) output = data.toXml;
  else output = data.innerHTML;

  return "XML:" + encodeURIComponent(output);
};

/** @private Marshall an array */
dwr.engine._serializeArray = function(batch, referto, data, name) {
  var ref = dwr.engine._lookup(referto, data, name);
  if (ref) return ref;

  if (document.all && !window.opera) {
    // Use array joining on IE (fastest)
    var buf = ["Array:["];
    for (var i = 0; i < data.length; i++) {
      if (i != 0) buf.push(",");
      batch.paramCount++;
      var childName = "c" + dwr.engine._batch.map.callCount + "-e" + batch.paramCount;
      dwr.engine._serializeAll(batch, referto, data[i], childName);
      buf.push("reference:");
      buf.push(childName);
    }
    buf.push("]");
    reply = buf.join("");
  }
  else {
    // Use string concat on other browsers (fastest)
    var reply = "Array:[";
    for (var i = 0; i < data.length; i++) {
      if (i != 0) reply += ",";
      batch.paramCount++;
      var childName = "c" + dwr.engine._batch.map.callCount + "-e" + batch.paramCount;
      dwr.engine._serializeAll(batch, referto, data[i], childName);
      reply += "reference:";
      reply += childName;
    }
    reply += "]";
  }

  return reply;
};

/** @private Convert an XML string into a DOM object. */
dwr.engine._unserializeDocument = function(xml) {
  var dom;
  if (window.DOMParser) {
    var parser = new DOMParser();
    dom = parser.parseFromString(xml, "text/xml");
    if (!dom.documentElement || dom.documentElement.tagName == "parsererror") {
      var message = dom.documentElement.firstChild.data;
      message += "\n" + dom.documentElement.firstChild.nextSibling.firstChild.data;
      throw message;
    }
    return dom;
  }
  else if (window.ActiveXObject) {
    dom = dwr.engine._newActiveXObject(dwr.engine._DOMDocument);
    dom.loadXML(xml); // What happens on parse fail with IE?
    return dom;
  }
  else {
    var div = document.createElement("div");
    div.innerHTML = xml;
    return div;
  }
};

/** @param axarray An array of strings to attempt to create ActiveX objects from */
dwr.engine._newActiveXObject = function(axarray) {
  var returnValue;  
  for (var i = 0; i < axarray.length; i++) {
    try {
      returnValue = new ActiveXObject(axarray[i]);
      break;
    }
    catch (ex) { /* ignore */ }
  }
  return returnValue;
};

/** @private Used internally when some message needs to get to the programmer */
dwr.engine._debug = function(message, stacktrace) {
  var written = false;
  try {
    if (window.console) {
      if (stacktrace && window.console.trace) window.console.trace();
      window.console.log(message);
      written = true;
    }
    else if (window.opera && window.opera.postError) {
      window.opera.postError(message);
      written = true;
    }
  }
  catch (ex) { /* ignore */ }

  if (!written) {
    var debug = document.getElementById("dwr-debug");
    if (debug) {
      var contents = message + "<br/>" + debug.innerHTML;
      if (contents.length > 2048) contents = contents.substring(0, 2048);
      debug.innerHTML = contents;
    }
  }
};




/*** DWR util *****/

/*
 * Copyright 2005 Joe Walker
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Declare an object to which we can add real functions.
 */
if (dwr == null) var dwr = {};
if (dwr.util == null) dwr.util = {};
if (DWRUtil == null) var DWRUtil = dwr.util;

/** @private The flag we use to decide if we should escape html */
dwr.util._escapeHtml = true;

/**
 * Set the global escapeHtml flag
 */
dwr.util.setEscapeHtml = function(escapeHtml) {
  dwr.util._escapeHtml = escapeHtml;
};

/** @private Work out from an options list and global settings if we should be esccaping */
dwr.util._shouldEscapeHtml = function(options) {
  if (options && options.escapeHtml != null) {
    return options.escapeHtml;
  }
  return dwr.util._escapeHtml;
};

/**
 * Return a string with &, < and > replaced with their entities
 * @see TODO
 */
dwr.util.escapeHtml = function(original) {
  return original.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
};

/**
 * Replace common XML entities with characters (see dwr.util.escapeHtml())
 * @see TODO
 */
dwr.util.unescapeHtml = function(original) {
  return original.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
};

/**
 * Replace characters dangerous for XSS reasons with visually similar characters
 * @see TODO
 */
dwr.util.replaceXmlCharacters = function(original) {
  original = original.replace("&", "+");
  original = original.replace("<", "\u2039");
  original = original.replace(">", "\u203A");
  original = original.replace("\'", "\u2018");
  original = original.replace("\"", "\u201C");
  return original;
};

/**
 * Return true iff the input string contains any XSS dangerous characters
 * @see TODO
 */
dwr.util.containsXssRiskyCharacters = function(original) {
  return (original.indexOf('&') != -1
    || original.indexOf('<') != -1
    || original.indexOf('>') != -1
    || original.indexOf('\'') != -1
    || original.indexOf('\"') != -1);
};

/**
 * Enables you to react to return being pressed in an input
 * @see http://getahead.org/dwr/browser/util/selectrange
 */
dwr.util.onReturn = function(event, action) {
  if (!event) event = window.event;
  if (event && event.keyCode && event.keyCode == 13) action();
};

/**
 * Select a specific range in a text box. Useful for 'google suggest' type functions.
 * @see http://getahead.org/dwr/browser/util/selectrange
 */
dwr.util.selectRange = function(ele, start, end) {
  ele = dwr.util._getElementById(ele, "selectRange()");
  if (ele == null) return;
  if (ele.setSelectionRange) {
    ele.setSelectionRange(start, end);
  }
  else if (ele.createTextRange) {
    var range = ele.createTextRange();
    range.moveStart("character", start);
    range.moveEnd("character", end - ele.value.length);
    range.select();
  }
  ele.focus();
};

/**
 * Find the element in the current HTML document with the given id or ids
 * @see http://getahead.org/dwr/browser/util/$
 */
if (document.getElementById) {
  dwr.util.byId = function() {
    var elements = new Array();
    for (var i = 0; i < arguments.length; i++) {
      var element = arguments[i];
      if (typeof element == 'string') {
        element = document.getElementById(element);
      }
      if (arguments.length == 1) {
        return element;
      }
      elements.push(element);
    }
    return elements;
  };
}
else if (document.all) {
  dwr.util.byId = function() {
    var elements = new Array();
    for (var i = 0; i < arguments.length; i++) {
      var element = arguments[i];
      if (typeof element == 'string') {
        element = document.all[element];
      }
      if (arguments.length == 1) {
        return element;
      }
      elements.push(element);
    }
    return elements;
  };
}

/**
 * Alias $ to dwr.util.byId
 * @see http://getahead.org/dwr/browser/util/$
 */
var $;
if (!$) {
  $ = dwr.util.byId;
}

/**
 * This function pretty-prints simple data or whole object graphs, f ex as an aid in debugging.
 * @see http://getahead.org/dwr/browser/util/todescriptivestring
 */
dwr.util.toDescriptiveString = function(data, showLevels, options) {
  if (showLevels === undefined) showLevels = 1;
  var opt = {};
  if (dwr.util._isObject(options)) opt = options;
  var defaultoptions = {
    escapeHtml:false,
    baseIndent: "",
    childIndent: "\u00A0\u00A0",
    lineTerminator: "\n",
    oneLineMaxItems: 5,
    shortStringMaxLength: 13,
    propertyNameMaxLength: 30 
  };
  for (var p in defaultoptions) {
    if (!(p in opt)) {
      opt[p] = defaultoptions[p];
    }
  }

  var skipDomProperties = {
    document:true, ownerDocument:true,
    all:true,
    parentElement:true, parentNode:true, offsetParent:true,
    children:true, firstChild:true, lastChild:true,
    previousSibling:true, nextSibling:true,
    innerHTML:true, outerHTML:true,
    innerText:true, outerText:true, textContent:true,
    attributes:true,
    style:true, currentStyle:true, runtimeStyle:true,
    parentTextEdit:true
  };
  
  function recursive(data, showLevels, indentDepth, options) {
    var reply = "";
    try {
      // string
      if (typeof data == "string") {
        var str = data;
        if (showLevels == 0 && str.length > options.shortStringMaxLength)
          str = str.substring(0, options.shortStringMaxLength-3) + "...";
        if (options.escapeHtml) {
          // Do the escape separately for every line as escapeHtml() on some 
          // browsers (IE) will strip line breaks and we want to preserve them
          var lines = str.split("\n");
          for (var i = 0; i < lines.length; i++) lines[i] = dwr.util.escapeHtml(lines[i]);
          str = lines.join("\n");
        }
        if (showLevels == 0) { // Short format
          str = str.replace(/\n|\r|\t/g, function(ch) {
            switch (ch) {
              case "\n": return "\\n";
              case "\r": return "";
              case "\t": return "\\t";
            }
          });
        }
        else { // Long format
          str = str.replace(/\n|\r|\t/g, function(ch) {
            switch (ch) {
              case "\n": return options.lineTerminator + indent(indentDepth+1, options);
              case "\r": return "";
              case "\t": return "\\t";
            }
          });
        }
        reply = '"' + str + '"';
      }
      
      // function
      else if (typeof data == "function") {
        reply = "function";
      }
    
      // Array
      else if (dwr.util._isArray(data)) {
        if (showLevels == 0) { // Short format (don't show items)
          if (data.length > 0)
            reply = "[...]";
          else
            reply = "[]";
        }
        else { // Long format (show items)
          var strarr = [];
          strarr.push("[");
          var count = 0;
          for (var i = 0; i < data.length; i++) {
            if (! (i in data)) continue;
            var itemvalue = data[i];
            if (count > 0) strarr.push(", ");
            if (showLevels == 1) { // One-line format
              if (count == options.oneLineMaxItems) {
                strarr.push("...");
                break;
              }
            }
            else { // Multi-line format
              strarr.push(options.lineTerminator + indent(indentDepth+1, options));
            }
            if (i != count) {
              strarr.push(i);
              strarr.push(":");
            }
            strarr.push(recursive(itemvalue, showLevels-1, indentDepth+1, options));
            count++;
          }
          if (showLevels > 1) strarr.push(options.lineTerminator + indent(indentDepth, options));
          strarr.push("]");
          reply = strarr.join("");
        }
      }
      
      // Objects except Date
      else if (dwr.util._isObject(data) && !dwr.util._isDate(data)) {
        if (showLevels == 0) { // Short format (don't show properties)
          reply = dwr.util._detailedTypeOf(data);
        }
        else { // Long format (show properties)
          var strarr = [];
          if (dwr.util._detailedTypeOf(data) != "Object") {
            strarr.push(dwr.util._detailedTypeOf(data));
            if (typeof data.valueOf() != "object") {
              strarr.push(":");
              strarr.push(recursive(data.valueOf(), 1, indentDepth, options));
            }
            strarr.push(" ");
          }
          strarr.push("{");
          var isDomObject = dwr.util._isHTMLElement(data); 
          var count = 0;
          for (var prop in data) {
            var propvalue = data[prop];
            if (isDomObject) {
              if (!propvalue) continue;
              if (typeof propvalue == "function") continue;
              if (skipDomProperties[prop]) continue;
              if (prop.toUpperCase() == prop) continue;
            }
            if (count > 0) strarr.push(", ");
            if (showLevels == 1) { // One-line format
              if (count == options.oneLineMaxItems) {
                strarr.push("...");
                break;
              }
            }
            else { // Multi-line format
              strarr.push(options.lineTerminator + indent(indentDepth+1, options));
            }
            strarr.push(prop.length > options.propertyNameMaxLength ? prop.substring(0, options.propertyNameMaxLength-3) + "..." : prop);
            strarr.push(":");
            strarr.push(recursive(propvalue, showLevels-1, indentDepth+1, options));
            count++;
          }
          if (showLevels > 1 && count > 0) strarr.push(options.lineTerminator + indent(indentDepth, options));
          strarr.push("}");
          reply = strarr.join("");
        }
      }
  
      // undefined, null, number, boolean, Date
      else {
        reply = "" + data;
      }
  
      return reply;
    }
    catch(err) {
      return (err.message ? err.message : ""+err);
    }
  }

  function indent(count, options) {
    var strarr = [];
    strarr.push(options.baseIndent);
    for (var i=0; i<count; i++) {
      strarr.push(options.childIndent);
    }
    return strarr.join("");
  };
  
  return recursive(data, showLevels, 0, opt);
};

/**
 * Setup a GMail style loading message.
 * @see http://getahead.org/dwr/browser/util/useloadingmessage
 */
dwr.util.useLoadingMessage = function(message) {
  var loadingMessage;
  if (message) loadingMessage = message;
  else loadingMessage = "Loading";
  dwr.engine.setPreHook(function() {
    var disabledZone = dwr.util.byId('disabledZone');
    if (!disabledZone) {
      disabledZone = document.createElement('div');
      disabledZone.setAttribute('id', 'disabledZone');
      disabledZone.style.position = "absolute";
      disabledZone.style.zIndex = "1000";
      disabledZone.style.left = "0px";
      disabledZone.style.top = "0px";
      disabledZone.style.width = "100%";
      disabledZone.style.height = "100%";
      document.body.appendChild(disabledZone);
      var messageZone = document.createElement('div');
      messageZone.setAttribute('id', 'messageZone');
      messageZone.style.position = "absolute";
      messageZone.style.top = "0px";
      messageZone.style.right = "0px";
      messageZone.style.background = "red";
      messageZone.style.color = "white";
      messageZone.style.fontFamily = "Arial,Helvetica,sans-serif";
      messageZone.style.padding = "4px";
      disabledZone.appendChild(messageZone);
      var text = document.createTextNode(loadingMessage);
      messageZone.appendChild(text);
      dwr.util._disabledZoneUseCount = 1;
    }
    else {
      dwr.util.byId('messageZone').innerHTML = loadingMessage;
      disabledZone.style.visibility = 'visible';
      dwr.util._disabledZoneUseCount++;
    }
  });
  dwr.engine.setPostHook(function() {
    dwr.util._disabledZoneUseCount--;
    if (dwr.util._disabledZoneUseCount == 0) {
      dwr.util.byId('disabledZone').style.visibility = 'hidden';
    }
  });
};

/**
 * Set a global highlight handler
 */
dwr.util.setHighlightHandler = function(handler) {
  dwr.util._highlightHandler = handler;
};

/**
 * An example highlight handler
 */
dwr.util.yellowFadeHighlightHandler = function(ele) {
  dwr.util._yellowFadeProcess(ele, 0);
};
dwr.util._yellowFadeSteps = [ "d0", "b0", "a0", "90", "98", "a0", "a8", "b0", "b8", "c0", "c8", "d0", "d8", "e0", "e8", "f0", "f8" ];
dwr.util._yellowFadeProcess = function(ele, colorIndex) {
  ele = dwr.util.byId(ele);
  if (colorIndex < dwr.util._yellowFadeSteps.length) {
    ele.style.backgroundColor = "#ffff" + dwr.util._yellowFadeSteps[colorIndex];
    setTimeout("dwr.util._yellowFadeProcess('" + ele.id + "'," + (colorIndex + 1) + ")", 200);
  }
  else {
    ele.style.backgroundColor = "transparent";
  }
};

/**
 * An example highlight handler
 */
dwr.util.borderFadeHighlightHandler = function(ele) {
  ele.style.borderWidth = "2px";
  ele.style.borderStyle = "solid";
  dwr.util._borderFadeProcess(ele, 0);
};
dwr.util._borderFadeSteps = [ "d0", "b0", "a0", "90", "98", "a0", "a8", "b0", "b8", "c0", "c8", "d0", "d8", "e0", "e8", "f0", "f8" ];
dwr.util._borderFadeProcess = function(ele, colorIndex) {
  ele = dwr.util.byId(ele);
  if (colorIndex < dwr.util._borderFadeSteps.length) {
    ele.style.borderColor = "#ff" + dwr.util._borderFadeSteps[colorIndex] + dwr.util._borderFadeSteps[colorIndex];
    setTimeout("dwr.util._borderFadeProcess('" + ele.id + "'," + (colorIndex + 1) + ")", 200);
  }
  else {
    ele.style.backgroundColor = "transparent";
  }
};

/**
 * A focus highlight handler
 */
dwr.util.focusHighlightHandler = function(ele) {
  try {
    ele.focus();
  }
  catch (ex) { /* ignore */ }
};

/** @private the current global highlight style */
dwr.util._highlightHandler = null;

/**
 * Highlight that an element has changed
 */
dwr.util.highlight = function(ele, options) {
  if (options && options.highlightHandler) {
    options.highlightHandler(dwr.util.byId(ele));
  }
  else if (dwr.util._highlightHandler != null) {
    dwr.util._highlightHandler(dwr.util.byId(ele));
  }
};

/**
 * Set the value an HTML element to the specified value.
 * @see http://getahead.org/dwr/browser/util/setvalue
 */
dwr.util.setValue = function(ele, val, options) {
  if (val == null) val = "";
  if (options == null) options = {};

  var orig = ele;
  if (typeof ele == "string") {
    ele = dwr.util.byId(ele);
    // We can work with names and need to sometimes for radio buttons, and IE has
    // an annoying bug where getElementById() returns an element based on name if
    // it doesn't find it by id. Here we don't want to do that, so:
    if (ele && ele.id != orig) ele = null;
  }
  var nodes = null;
  if (ele == null) {
    // Now it is time to look by name
    nodes = document.getElementsByName(orig);
    if (nodes.length >= 1) ele = nodes.item(0);
  }

  if (ele == null) {
    dwr.util._debug("setValue() can't find an element with id/name: " + orig + ".");
    return;
  }

  // All paths now lead to some update so we highlight a change
  dwr.util.highlight(ele, options);

  if (dwr.util._isHTMLElement(ele, "select")) {
    if (ele.type == "select-multiple" && dwr.util._isArray(val)) dwr.util._selectListItems(ele, val);
    else dwr.util._selectListItem(ele, val);
    return;
  }

  if (dwr.util._isHTMLElement(ele, "input")) {
    if (ele.type == "radio" || ele.type == "checkbox") {
      if (nodes && nodes.length >= 1) {
        for (var i = 0; i < nodes.length; i++) {
          var node = nodes.item(i);
          if (node.type != ele.type) continue;
          if (dwr.util._isArray(val)) {
            node.checked = false;
            for (var j = 0; j < val.length; j++)
              if (val[j] == node.value) node.checked = true;
          }
          else {
            node.checked = (node.value == val);
          }
        }
      }
      else {
        ele.checked = (val == true);
      }
    }
    else ele.value = val;

    return;
  }

  if (dwr.util._isHTMLElement(ele, "textarea")) {
    ele.value = val;
    return;
  }

  // If the value to be set is a DOM object then we try importing the node
  // rather than serializing it out
  if (val.nodeType) {
    if (val.nodeType == 9 /*Node.DOCUMENT_NODE*/) val = val.documentElement;
    val = dwr.util._importNode(ele.ownerDocument, val, true);
    ele.appendChild(val);
    return;
  }

  // Fall back to innerHTML and friends
  if (dwr.util._shouldEscapeHtml(options) && typeof(val) == "string") {
    if (ele.textContent) ele.textContent = val;
    else if (ele.innerText) ele.innerText = val;
    else ele.innerHTML = dwr.util.escapeHtml(val);
  }
  else {
    ele.innerHTML = val;
  }
};

/**
 * @private Find multiple items in a select list and select them. Used by setValue()
 * @param ele The select list item
 * @param val The array of values to select
 */
dwr.util._selectListItems = function(ele, val) {
  // We deal with select list elements by selecting the matching option
  // Begin by searching through the values
  var found  = false;
  var i;
  var j;
  for (i = 0; i < ele.options.length; i++) {
    ele.options[i].selected = false;
    for (j = 0; j < val.length; j++) {
      if (ele.options[i].value == val[j]) {
        ele.options[i].selected = true;
      }
    }
  }
  // If that fails then try searching through the visible text
  if (found) return;

  for (i = 0; i < ele.options.length; i++) {
    for (j = 0; j < val.length; j++) {
      if (ele.options[i].text == val[j]) {
        ele.options[i].selected = true;
      }
    }
  }
};

/**
 * @private Find an item in a select list and select it. Used by setValue()
 * @param ele The select list item
 * @param val The value to select
 */
dwr.util._selectListItem = function(ele, val) {
  // We deal with select list elements by selecting the matching option
  // Begin by searching through the values
  var found = false;
  var i;
  for (i = 0; i < ele.options.length; i++) {
    if (ele.options[i].value == val) {
      ele.options[i].selected = true;
      found = true;
    }
    else {
      ele.options[i].selected = false;
    }
  }

  // If that fails then try searching through the visible text
  if (found) return;

  for (i = 0; i < ele.options.length; i++) {
    ele.options[i].selected = (ele.options[i].text == val);
  }
};

/**
 * Read the current value for a given HTML element.
 * @see http://getahead.org/dwr/browser/util/getvalue
 */
dwr.util.getValue = function(ele, options) {
  if (options == null) options = {};
  var orig = ele;
  if (typeof ele == "string") {
    ele = dwr.util.byId(ele);
    // We can work with names and need to sometimes for radio buttons, and IE has
    // an annoying bug where getElementById() returns an element based on name if
    // it doesn't find it by id. Here we don't want to do that, so:
    if (ele && ele.id != orig) ele = null;
  }
  var nodes = null;
  if (ele == null) {
    // Now it is time to look by name
    nodes = document.getElementsByName(orig);
    if (nodes.length >= 1) ele = nodes.item(0);
  }
  if (ele == null) {
    dwr.util._debug("getValue() can't find an element with id/name: " + orig + ".");
    return "";
  }

  if (dwr.util._isHTMLElement(ele, "select")) {
    // Using "type" property instead of "multiple" as "type" is an official 
    // client-side property since JS 1.1
    if (ele.type == "select-multiple") {
      var reply = new Array();
      for (var i = 0; i < ele.options.length; i++) {
        var item = ele.options[i];
        if (item.selected) {
          var valueAttr = item.getAttributeNode("value");
          if (valueAttr && valueAttr.specified) {
            reply.push(item.value);
          }
          else {
            reply.push(item.text);
          }
        }
      }
      return reply;
    }
    else {
      var sel = ele.selectedIndex;
      if (sel != -1) {
        var item = ele.options[sel];
        var valueAttr = item.getAttributeNode("value");
        if (valueAttr && valueAttr.specified) {
          return item.value;
        }
        return item.text;
      }
      else {
        return "";
      }
    }
  }

  if (dwr.util._isHTMLElement(ele, "input")) {
    if (ele.type == "radio") {
      if (nodes && nodes.length >= 1) {
        for (var i = 0; i < nodes.length; i++) {
          var node = nodes.item(i);
          if (node.type == ele.type) {
            if (node.checked) return node.value;
          }
        }
      }
      return ele.checked;
    }
    if (ele.type == "checkbox") {
      if (nodes && nodes.length >= 1) {
        var reply = [];
        for (var i = 0; i < nodes.length; i++) {
          var node = nodes.item(i);
          if (node.type == ele.type) {
            if (node.checked) reply.push(node.value);
          }
        }
        return reply;
      }
      return ele.checked;
    }
    return ele.value;
  }

  if (dwr.util._isHTMLElement(ele, "textarea")) {
    return ele.value;
  }

  if (dwr.util._shouldEscapeHtml(options)) {
    if (ele.textContent) return ele.textContent;
    else if (ele.innerText) return ele.innerText;
  }
  return ele.innerHTML;
};

/**
 * getText() is like getValue() except that it reads the text (and not the value) from select elements
 * @see http://getahead.org/dwr/browser/util/gettext
 */
dwr.util.getText = function(ele) {
  ele = dwr.util._getElementById(ele, "getText()");
  if (ele == null) return null;
  if (!dwr.util._isHTMLElement(ele, "select")) {
    dwr.util._debug("getText() can only be used with select elements. Attempt to use: " + dwr.util._detailedTypeOf(ele) + " from  id: " + orig + ".");
    return "";
  }

  // This is a bit of a scam because it assumes single select
  // but I'm not sure how we should treat multi-select.
  var sel = ele.selectedIndex;
  if (sel != -1) {
    return ele.options[sel].text;
  }
  else {
    return "";
  }
};

/**
 * Given a map, or a recursive structure consisting of arrays and maps, call 
 * setValue() for all leaf entries and use intermediate levels to form nested
 * element ids.
 * @see http://getahead.org/dwr/browser/util/setvalues
 */
dwr.util.setValues = function(data, options) {
  var prefix = "";
  if (options && options.prefix) prefix = options.prefix;
  if (options && options.idPrefix) prefix = options.idPrefix;
  dwr.util._setValuesRecursive(data, prefix);
};

/**
 * @private Recursive helper for setValues()
 */
dwr.util._setValuesRecursive = function(data, idpath) {
  // Array containing objects -> add "[n]" to prefix and make recursive call
  // for each item object
  if (dwr.util._isArray(data) && data.length > 0 && dwr.util._isObject(data[0])) {
    for (var i = 0; i < data.length; i++) {
      dwr.util._setValuesRecursive(data[i], idpath+"["+i+"]");
    }
  }
  // Object (not array) -> handle nested object properties
  else if (dwr.util._isObject(data) && !dwr.util._isArray(data)) {
    for (var prop in data) {
      var subidpath = idpath ? idpath+"."+prop : prop;
      // Object (not array), or array containing objects -> call ourselves recursively
      if (dwr.util._isObject(data[prop]) && !dwr.util._isArray(data[prop]) 
          || dwr.util._isArray(data[prop]) && data[prop].length > 0 && dwr.util._isObject(data[prop][0])) {
        dwr.util._setValuesRecursive(data[prop], subidpath);
      }
      // Functions -> skip
      else if (typeof data[prop] == "function") {
        // NOP
      }
      // Only simple values left (or array of simple values, or empty array)
      // -> call setValue()
      else {
        // Are there any elements with that id or name
        if (dwr.util.byId(subidpath) != null || document.getElementsByName(subidpath).length >= 1) {
          dwr.util.setValue(subidpath, data[prop]);
        }
      }
    }
  }
};

/**
 * Given a map, or a recursive structure consisting of arrays and maps, call 
 * getValue() for all leaf entries and use intermediate levels to form nested
 * element ids.
 * Given a string or element that refers to a form, create an object from the 
 * elements of the form.
 * @see http://getahead.org/dwr/browser/util/getvalues
 */
dwr.util.getValues = function(data, options) {
  if (typeof data == "string" || dwr.util._isHTMLElement(data)) {
    return dwr.util.getFormValues(data);
  }
  else {
    var prefix = "";
    if (options != null && options.prefix) prefix = options.prefix;
    if (options != null && options.idPrefix) prefix = options.idPrefix;
    dwr.util._getValuesRecursive(data, prefix);
    return data;
  }
};

/**
 * Given a string or element that refers to a form, create an object from the 
 * elements of the form.
 * @see http://getahead.org/dwr/browser/util/getvalues
 */
dwr.util.getFormValues = function(eleOrNameOrId) {
  var ele = null;
  if (typeof eleOrNameOrId == "string") {
    ele = document.forms[eleOrNameOrId];
    if (ele == null) ele = dwr.util.byId(eleOrNameOrId);
  }
  else if (dwr.util._isHTMLElement(eleOrNameOrId)) {
    ele = eleOrNameOrId;
  }
  if (ele != null) {
    if (ele.elements == null) {
      alert("getFormValues() requires an object or reference to a form element.");
      return null;
    }
    var reply = {};
    var name;
    var value;
    for (var i = 0; i < ele.elements.length; i++) {
      if (ele[i].type in {button:0,submit:0,reset:0,image:0,file:0}) continue;
      if (ele[i].name) {
        name = ele[i].name;
        value = dwr.util.getValue(name);
      }
      else {
        if (ele[i].id) name = ele[i].id;
        else name = "element" + i;
        value = dwr.util.getValue(ele[i]);
      }
      reply[name] = value;
    }
    return reply;
  }
};

/**
 * @private Recursive helper for getValues().
 */
dwr.util._getValuesRecursive = function(data, idpath) {
  // Array containing objects -> add "[n]" to idpath and make recursive call
  // for each item object
  if (dwr.util._isArray(data) && data.length > 0 && dwr.util._isObject(data[0])) {
    for (var i = 0; i < data.length; i++) {
      dwr.util._getValuesRecursive(data[i], idpath+"["+i+"]");
    }
  }
  // Object (not array) -> handle nested object properties
  else if (dwr.util._isObject(data) && !dwr.util._isArray(data)) {
    for (var prop in data) {
      var subidpath = idpath ? idpath+"."+prop : prop;
      // Object, or array containing objects -> call ourselves recursively
      if (dwr.util._isObject(data[prop]) && !dwr.util._isArray(data[prop])
          || dwr.util._isArray(data[prop]) && data[prop].length > 0 && dwr.util._isObject(data[prop][0])) {
        dwr.util._getValuesRecursive(data[prop], subidpath);
      }
      // Functions -> skip
      else if (typeof data[prop] == "function") {
        // NOP
      }
      // Only simple values left (or array of simple values, or empty array)
      // -> call getValue()
      else {
        // Are there any elements with that id or name
        if (dwr.util.byId(subidpath) != null || document.getElementsByName(subidpath).length >= 1) {
          data[prop] = dwr.util.getValue(subidpath);
        }
      }
    }
  }
};

/**
 * Add options to a list from an array or map.
 * @see http://getahead.org/dwr/browser/lists
 */
dwr.util.addOptions = function(ele, data/*, options*/) {
  ele = dwr.util._getElementById(ele, "addOptions()");
  if (ele == null) return;
  var useOptions = dwr.util._isHTMLElement(ele, "select");
  var useLi = dwr.util._isHTMLElement(ele, ["ul", "ol"]);
  if (!useOptions && !useLi) {
    dwr.util._debug("addOptions() can only be used with select/ul/ol elements. Attempt to use: " + dwr.util._detailedTypeOf(ele));
    return;
  }
  if (data == null) return;
  
  var argcount = arguments.length;
  var options = {};
  var lastarg = arguments[argcount - 1]; 
  if (argcount > 2 && dwr.util._isObject(lastarg)) {
    options = lastarg;
    argcount--;
  }
  var arg3 = null; if (argcount >= 3) arg3 = arguments[2];
  var arg4 = null; if (argcount >= 4) arg4 = arguments[3];
  if (!options.optionCreator && useOptions) options.optionCreator = dwr.util._defaultOptionCreator;
  if (!options.optionCreator && useLi) options.optionCreator = dwr.util._defaultListItemCreator;

  var text, value, li;
  if (dwr.util._isArray(data)) {
    // Loop through the data that we do have
    for (var i = 0; i < data.length; i++) {
      options.data = data[i];
      options.text = null;
      options.value = null;
      if (useOptions) {
        if (arg3 != null) {
          if (arg4 != null) {
            options.text = dwr.util._getValueFrom(data[i], arg4);
            options.value = dwr.util._getValueFrom(data[i], arg3);
          }
          else options.text = options.value = dwr.util._getValueFrom(data[i], arg3);
        }
        else options.text = options.value = dwr.util._getValueFrom(data[i]);

        if (options.text != null || options.value) {
          var opt = options.optionCreator(options);
          opt.text = options.text;
          opt.value = options.value;
          ele.options[ele.options.length] = opt;
        }
      }
      else {
        options.value = dwr.util._getValueFrom(data[i], arg3);
        if (options.value != null) {
          li = options.optionCreator(options);
          if (dwr.util._shouldEscapeHtml(options)) {
            options.value = dwr.util.escapeHtml(options.value);
          }
          li.innerHTML = options.value;
          ele.appendChild(li);
        }
      }
    }
  }
  else if (arg4 != null) {
    if (!useOptions) {
      alert("dwr.util.addOptions can only create select lists from objects.");
      return;
    }
    for (var prop in data) {
      options.data = data[prop];
      options.value = dwr.util._getValueFrom(data[prop], arg3);
      options.text = dwr.util._getValueFrom(data[prop], arg4);

      if (options.text != null || options.value) {
        var opt = options.optionCreator(options);
        opt.text = options.text;
        opt.value = options.value;
        ele.options[ele.options.length] = opt;
      }
    }
  }
  else {
    if (!useOptions) {
      dwr.util._debug("dwr.util.addOptions can only create select lists from objects.");
      return;
    }
    for (var prop in data) {
      if (typeof data[prop] == "function") continue;
      options.data = data[prop];
      if (!arg3) {
        options.value = prop;
        options.text = data[prop];
      }
      else {
        options.value = data[prop];
        options.text = prop;
      }
      if (options.text != null || options.value) {
        var opt = options.optionCreator(options);
        opt.text = options.text;
        opt.value = options.value;
        ele.options[ele.options.length] = opt;
      }
    }
  }

  // All error routes through this function result in a return, so highlight now
  dwr.util.highlight(ele, options); 
};

/**
 * @private Get the data from an array function for dwr.util.addOptions
 */
dwr.util._getValueFrom = function(data, method) {
  if (method == null) return data;
  else if (typeof method == 'function') return method(data);
  else return data[method];
};

/**
 * @private Default option creation function
 */
dwr.util._defaultOptionCreator = function(options) {
  return new Option();
};

/**
 * @private Default list item creation function
 */
dwr.util._defaultListItemCreator = function(options) {
  return document.createElement("li");
};

/**
 * Remove all the options from a select list (specified by id)
 * @see http://getahead.org/dwr/browser/lists
 */
dwr.util.removeAllOptions = function(ele) {
  ele = dwr.util._getElementById(ele, "removeAllOptions()");
  if (ele == null) return;
  var useOptions = dwr.util._isHTMLElement(ele, "select");
  var useLi = dwr.util._isHTMLElement(ele, ["ul", "ol"]);
  if (!useOptions && !useLi) {
    dwr.util._debug("removeAllOptions() can only be used with select, ol and ul elements. Attempt to use: " + dwr.util._detailedTypeOf(ele));
    return;
  }
  if (useOptions) {
    ele.options.length = 0;
  }
  else {
    while (ele.childNodes.length > 0) {
      ele.removeChild(ele.firstChild);
    }
  }
};

/**
 * Create rows inside a the table, tbody, thead or tfoot element (given by id).
 * @see http://getahead.org/dwr/browser/tables
 */
dwr.util.addRows = function(ele, data, cellFuncs, options) {
  ele = dwr.util._getElementById(ele, "addRows()");
  if (ele == null) return;
  if (!dwr.util._isHTMLElement(ele, ["table", "tbody", "thead", "tfoot"])) {
    dwr.util._debug("addRows() can only be used with table, tbody, thead and tfoot elements. Attempt to use: " + dwr.util._detailedTypeOf(ele));
    return;
  }
  if (!options) options = {};
  if (!options.rowCreator) options.rowCreator = dwr.util._defaultRowCreator;
  if (!options.cellCreator) options.cellCreator = dwr.util._defaultCellCreator;
  var tr, rowNum;
  if (dwr.util._isArray(data)) {
    for (rowNum = 0; rowNum < data.length; rowNum++) {
      options.rowData = data[rowNum];
      options.rowIndex = rowNum;
      options.rowNum = rowNum;
      options.data = null;
      options.cellNum = -1;
      tr = dwr.util._addRowInner(cellFuncs, options);
      if (tr != null) ele.appendChild(tr);
    }
  }
  else if (typeof data == "object") {
    rowNum = 0;
    for (var rowIndex in data) {
      options.rowData = data[rowIndex];
      options.rowIndex = rowIndex;
      options.rowNum = rowNum;
      options.data = null;
      options.cellNum = -1;
      tr = dwr.util._addRowInner(cellFuncs, options);
      if (tr != null) ele.appendChild(tr);
      rowNum++;
    }
  }

  dwr.util.highlight(ele, options);
};

/**
 * @private Internal function to draw a single row of a table.
 */
dwr.util._addRowInner = function(cellFuncs, options) {
  var tr = options.rowCreator(options);
  if (tr == null) return null;
  for (var cellNum = 0; cellNum < cellFuncs.length; cellNum++) {
    var func = cellFuncs[cellNum];
    if (typeof func == 'function') options.data = func(options.rowData, options);
    else options.data = func || "";
    options.cellNum = cellNum;
    var td = options.cellCreator(options);
    if (td != null) {
      if (options.data != null) {
        if (dwr.util._isHTMLElement(options.data)) td.appendChild(options.data);
        else {
          if (dwr.util._shouldEscapeHtml(options) && typeof(options.data) == "string") {
            td.innerHTML = dwr.util.escapeHtml(options.data);
          }
          else {
            td.innerHTML = options.data;
          }
        }
      }
      tr.appendChild(td);
    }
  }
  return tr;
};

/**
 * @private Default row creation function
 */
dwr.util._defaultRowCreator = function(options) {
  return document.createElement("tr");
};

/**
 * @private Default cell creation function
 */
dwr.util._defaultCellCreator = function(options) {
  return document.createElement("td");
};

/**
 * Remove all the children of a given node.
 * @see http://getahead.org/dwr/browser/tables
 */
dwr.util.removeAllRows = function(ele, options) {
  ele = dwr.util._getElementById(ele, "removeAllRows()");
  if (ele == null) return;
  if (!options) options = {};
  if (!options.filter) options.filter = function() { return true; };
  if (!dwr.util._isHTMLElement(ele, ["table", "tbody", "thead", "tfoot"])) {
    dwr.util._debug("removeAllRows() can only be used with table, tbody, thead and tfoot elements. Attempt to use: " + dwr.util._detailedTypeOf(ele));
    return;
  }
  var child = ele.firstChild;
  var next;
  while (child != null) {
    next = child.nextSibling;
    if (options.filter(child)) {
      ele.removeChild(child);
    }
    child = next;
  }
};

/**
 * dwr.util.byId(ele).className = "X", that we can call from Java easily.
 */
dwr.util.setClassName = function(ele, className) {
  ele = dwr.util._getElementById(ele, "setClassName()");
  if (ele == null) return;
  ele.className = className;
};

/**
 * dwr.util.byId(ele).className += "X", that we can call from Java easily.
 */
dwr.util.addClassName = function(ele, className) {
  ele = dwr.util._getElementById(ele, "addClassName()");
  if (ele == null) return;
  ele.className += " " + className;
};

/**
 * dwr.util.byId(ele).className -= "X", that we can call from Java easily
 * From code originally by Gavin Kistner
 */
dwr.util.removeClassName = function(ele, className) {
  ele = dwr.util._getElementById(ele, "removeClassName()");
  if (ele == null) return;
  var regex = new RegExp("(^|\\s)" + className + "(\\s|$)", 'g');
  ele.className = ele.className.replace(regex, '');
};

/**
 * dwr.util.byId(ele).className |= "X", that we can call from Java easily.
 */
dwr.util.toggleClassName = function(ele, className) {
  ele = dwr.util._getElementById(ele, "toggleClassName()");
  if (ele == null) return;
  var regex = new RegExp("(^|\\s)" + className + "(\\s|$)");
  if (regex.test(ele.className)) {
    ele.className = ele.className.replace(regex, '');
  }
  else {
    ele.className += " " + className;
  }
};

/**
 * Clone a node and insert it into the document just above the 'template' node
 * @see http://getahead.org/dwr/???
 */
dwr.util.cloneNode = function(ele, options) {
  ele = dwr.util._getElementById(ele, "cloneNode()");
  if (ele == null) return null;
  if (options == null) options = {};
  var clone = ele.cloneNode(true);
  if (options.idPrefix || options.idSuffix) {
    dwr.util._updateIds(clone, options);
  }
  else {
    dwr.util._removeIds(clone);
  }
  ele.parentNode.insertBefore(clone, ele);
  return clone;
};

/**
 * @private Update all of the ids in an element tree
 */
dwr.util._updateIds = function(ele, options) {
  if (options == null) options = {};
  if (ele.id) {
    ele.setAttribute("id", (options.idPrefix || "") + ele.id + (options.idSuffix || ""));
  }
  var children = ele.childNodes;
  for (var i = 0; i < children.length; i++) {
    var child = children.item(i);
    if (child.nodeType == 1 /*Node.ELEMENT_NODE*/) {
      dwr.util._updateIds(child, options);
    }
  }
};

/**
 * @private Remove all the Ids from an element
 */
dwr.util._removeIds = function(ele) {
  if (ele.id) ele.removeAttribute("id");
  var children = ele.childNodes;
  for (var i = 0; i < children.length; i++) {
    var child = children.item(i);
    if (child.nodeType == 1 /*Node.ELEMENT_NODE*/) {
      dwr.util._removeIds(child);
    }
  }
};

/**
 * Clone a template node and its embedded template child nodes according to
 * cardinalities (of arrays) in supplied data.  
 */
dwr.util.cloneNodeForValues = function(templateEle, data, options) {
  templateEle = dwr.util._getElementById(templateEle, "cloneNodeForValues()");
  if (templateEle == null) return null;
  if (options == null) options = {};
  var idpath;
  if (options.idPrefix != null)
    idpath = options.idPrefix;
  else
    idpath = templateEle.id || ""; 
  return dwr.util._cloneNodeForValuesRecursive(templateEle, data, idpath, options);
};

/**
 * @private Recursive helper for cloneNodeForValues(). 
 */
dwr.util._cloneNodeForValuesRecursive = function(templateEle, data, idpath, options) {
  // Incoming array -> make an id for each item and call clone of the template 
  // for each of them
  if (dwr.util._isArray(data)) {
    var clones = [];
    for (var i = 0; i < data.length; i++) {
      var item = data[i];
      var clone = dwr.util._cloneNodeForValuesRecursive(templateEle, item, idpath + "[" + i + "]", options);
      clones.push(clone);
    }
    return clones;
  }
  else
  // Incoming object (not array) -> clone the template, add id prefixes, add 
  // clone to DOM, and then recurse into any array properties if they contain 
  // objects and there is a suitable template
  if (dwr.util._isObject(data) && !dwr.util._isArray(data)) {
    var clone = templateEle.cloneNode(true);
    if (options.updateCloneStyle && clone.style) {
      for (var propname in options.updateCloneStyle) {
        clone.style[propname] = options.updateCloneStyle[propname];
      }
    }
    dwr.util._replaceIds(clone, templateEle.id, idpath);
    templateEle.parentNode.insertBefore(clone, templateEle);
    dwr.util._cloneSubArrays(data, idpath, options);
    return clone;
  }

  // It is an error to end up here so we return nothing
  return null;
};

/**
 * @private Substitute a leading idpath fragment with another idpath for all 
 * element ids tree, and remove ids that don't match the idpath. 
 */
dwr.util._replaceIds = function(ele, oldidpath, newidpath) {
  if (ele.id) {
    var newId = null;
    if (ele.id == oldidpath) {
      newId = newidpath;
    }
    else if (ele.id.length > oldidpath.length) {
      if (ele.id.substr(0, oldidpath.length) == oldidpath) {
        var trailingChar = ele.id.charAt(oldidpath.length);
        if (trailingChar == "." || trailingChar == "[") {
          newId = newidpath + ele.id.substr(oldidpath.length);
        }
      }
    }
    if (newId) {
      ele.setAttribute("id", newId);
    }
    else {
      ele.removeAttribute("id");
    }
  }
  var children = ele.childNodes;
  for (var i = 0; i < children.length; i++) {
    var child = children.item(i);
    if (child.nodeType == 1 /*Node.ELEMENT_NODE*/) {
      dwr.util._replaceIds(child, oldidpath, newidpath);
    }
  }
};

/**
 * @private Finds arrays in supplied data and uses any corresponding template 
 * node to make a clone for each item in the array. 
 */
dwr.util._cloneSubArrays = function(data, idpath, options) {
  for (prop in data) {
    var value = data[prop];
    // Look for potential recursive cloning in all array properties
    if (dwr.util._isArray(value)) {
      // Only arrays with objects are interesting for cloning
      if (value.length > 0 && dwr.util._isObject(value[0])) {
        var subTemplateId = idpath + "." + prop;
        var subTemplateEle = dwr.util.byId(subTemplateId);
        if (subTemplateEle != null) {
          dwr.util._cloneNodeForValuesRecursive(subTemplateEle, value, subTemplateId, options);
        }
      }
    }
    // Continue looking for arrays in object properties
    else if (dwr.util._isObject(value)) {
      dwr.util._cloneSubArrays(value, idpath + "." + prop, options);
    }
  }
};

/**
 * @private Helper to turn a string into an element with an error message
 */
dwr.util._getElementById = function(ele, source) {
  var orig = ele;
  ele = dwr.util.byId(ele);
  if (ele == null) {
    dwr.util._debug(source + " can't find an element with id: " + orig + ".");
  }
  return ele;
};

/**
 * @private Is the given node an HTML element (optionally of a given type)?
 * @param ele The element to test
 * @param nodeName eg "input", "textarea" - check for node name (optional)
 *         if nodeName is an array then check all for a match.
 */
dwr.util._isHTMLElement = function(ele, nodeName) {
  if (ele == null || typeof ele != "object" || ele.nodeName == null) {
    return false;
  }
  if (nodeName != null) {
    var test = ele.nodeName.toLowerCase();
    if (typeof nodeName == "string") {
      return test == nodeName.toLowerCase();
    }
    if (dwr.util._isArray(nodeName)) {
      var match = false;
      for (var i = 0; i < nodeName.length && !match; i++) {
        if (test == nodeName[i].toLowerCase()) {
          match =  true;
        }
      }
      return match;
    }
    dwr.util._debug("dwr.util._isHTMLElement was passed test node name that is neither a string or array of strings");
    return false;
  }
  return true;
};

/**
 * @private Like typeOf except that more information for an object is returned other than "object"
 */
dwr.util._detailedTypeOf = function(x) {
  var reply = typeof x;
  if (reply == "object") {
    reply = Object.prototype.toString.apply(x); // Returns "[object class]"
    reply = reply.substring(8, reply.length-1);  // Just get the class bit
  }
  return reply;
};

/**
 * @private Object detector. Excluding null from objects.
 */
dwr.util._isObject = function(data) {
  return (data && typeof data == "object");
};

/**
 * @private Array detector. Note: instanceof doesn't work with multiple frames.
 */
dwr.util._isArray = function(data) {
  return (data && data.join);
};

/**
 * @private Date detector. Note: instanceof doesn't work with multiple frames.
 */
dwr.util._isDate = function(data) {
  return (data && data.toUTCString) ? true : false;
};

/**
 * @private Used by setValue. Gets around the missing functionallity in IE.
 */
dwr.util._importNode = function(doc, importedNode, deep) {
  var newNode;

  if (importedNode.nodeType == 1 /*Node.ELEMENT_NODE*/) {
    newNode = doc.createElement(importedNode.nodeName);

    for (var i = 0; i < importedNode.attributes.length; i++) {
      var attr = importedNode.attributes[i];
      if (attr.nodeValue != null && attr.nodeValue != '') {
        newNode.setAttribute(attr.name, attr.nodeValue);
      }
    }

    if (typeof importedNode.style != "undefined") {
      newNode.style.cssText = importedNode.style.cssText;
    }
  }
  else if (importedNode.nodeType == 3 /*Node.TEXT_NODE*/) {
    newNode = doc.createTextNode(importedNode.nodeValue);
  }

  if (deep && importedNode.hasChildNodes()) {
    for (i = 0; i < importedNode.childNodes.length; i++) {
      newNode.appendChild(dwr.util._importNode(doc, importedNode.childNodes[i], true));
    }
  }

  return newNode;
};

/** @private Used internally when some message needs to get to the programmer */
dwr.util._debug = function(message, stacktrace) {
  var written = false;
  try {
    if (window.console) {
      if (stacktrace && window.console.trace) window.console.trace();
      window.console.log(message);
      written = true;
    }
    else if (window.opera && window.opera.postError) {
      window.opera.postError(message);
      written = true;
    }
  }
  catch (ex) { /* ignore */ }

  if (!written) {
    var debug = document.getElementById("dwr-debug");
    if (debug) {
      var contents = message + "<br/>" + debug.innerHTML;
      if (contents.length > 2048) contents = contents.substring(0, 2048);
      debug.innerHTML = contents;
    }
  }
};







/*** DWR controllers *****/

//Provide a default path to dwr.engine
if (dwr == null) var dwr = {};
if (dwr.engine == null) dwr.engine = {};
if (DWREngine == null) var DWREngine = dwr.engine;

if (PublicAjaxController == null) var PublicAjaxController = {};
PublicAjaxController._path = '/dwr';
PublicAjaxController.closeNotification = function(p1, p2, p3, callback) {
  dwr.engine._execute(PublicAjaxController._path, 'PublicAjaxController', 'closeNotification', false, p1, p2, p3, callback);
}
PublicAjaxController.setAsFavoriteJobOffer = function(p1, p2, callback) {
  dwr.engine._execute(PublicAjaxController._path, 'PublicAjaxController', 'setAsFavoriteJobOffer', false, p1, p2, callback);
}
PublicAjaxController.setAsFavoriteJobRequest = function(p1, p2, callback) {
  dwr.engine._execute(PublicAjaxController._path, 'PublicAjaxController', 'setAsFavoriteJobRequest', false, p1, p2, callback);
}
PublicAjaxController.removeAsFavoriteJobOffer = function(p1, p2, callback) {
  dwr.engine._execute(PublicAjaxController._path, 'PublicAjaxController', 'removeAsFavoriteJobOffer', false, p1, p2, callback);
}
PublicAjaxController.removeAsFavoriteJobRequest = function(p1, p2, callback) {
  dwr.engine._execute(PublicAjaxController._path, 'PublicAjaxController', 'removeAsFavoriteJobRequest', false, p1, p2, callback);
}
PublicAjaxController.fillSpamReport = function(p1, p2, callback) {
  dwr.engine._execute(PublicAjaxController._path, 'PublicAjaxController', 'fillSpamReport', false, p1, p2, callback);
}
PublicAjaxController.showPoll = function(p1, p2, p3, callback) {
  dwr.engine._execute(PublicAjaxController._path, 'PublicAjaxController', 'showPoll', false, p1, p2, p3, callback);
}
PublicAjaxController.submitPoll = function(p2, p3, p4, callback) {
  dwr.engine._execute(PublicAjaxController._path, 'PublicAjaxController', 'submitPoll', false, false, p2, p3, p4, callback);
}
PublicAjaxController.applyForJobOfferSubmit = function(p1, p2, p3, p4, p5, callback) {
  dwr.engine._execute(PublicAjaxController._path, 'PublicAjaxController', 'applyForJobOfferSubmit', false, p1, p2, p3, p4, p5, callback);
}
PublicAjaxController.requestContactShare = function(p1, p2, p3, callback) {
  dwr.engine._execute(PublicAjaxController._path, 'PublicAjaxController', 'requestContactShare', false, p1, p2, p3, callback);
}
PublicAjaxController.submitAgencyContactForm = function(p2, p3, p4, p5, p6, callback) {
  dwr.engine._execute(PublicAjaxController._path, 'PublicAjaxController', 'submitAgencyContactForm', false, false, p2, p3, p4, p5, p6, callback);
}
PublicAjaxController.ratingboxDeleteComment = function(p1, p2, callback) {
	  dwr.engine._execute(PublicAjaxController._path, 'PublicAjaxController', 'ratingboxDeleteComment', false, p1, p2, callback);
}
PublicAjaxController.ratingboxSubmitComment = function(p1, p2, p3, p4, p5, callback) {
	  dwr.engine._execute(PublicAjaxController._path, 'PublicAjaxController', 'ratingboxSubmitComment', false, p1, p2, p3, p4, p5, callback);
}
PublicAjaxController.ratingboxSubmitRating = function(p1, p2, p3, callback) {
	  dwr.engine._execute(PublicAjaxController._path, 'PublicAjaxController', 'ratingboxSubmitRating', false, p1, p2, p3, callback);
}







if (CompanyAjaxController == null) var CompanyAjaxController = {};
CompanyAjaxController._path = '/dwr';
CompanyAjaxController.companyUserDetails = function(p1, p2, p3, p4, p5, callback) {
  dwr.engine._execute(CompanyAjaxController._path, 'CompanyAjaxController', 'companyUserDetails', false, p1, p2, p3, p4, p5, callback);
}
CompanyAjaxController.companyInfoContact = function(p1, p2, p3, p4, p5, callback) {
  dwr.engine._execute(CompanyAjaxController._path, 'CompanyAjaxController', 'companyInfoContact', false, p1, p2, p3, p4, p5, callback);
}
CompanyAjaxController.companyInfoAddress = function(p1, p2, p3, p4, p5, callback) {
  dwr.engine._execute(CompanyAjaxController._path, 'CompanyAjaxController', 'companyInfoAddress', false, p1, p2, p3, p4, p5, callback);
}
CompanyAjaxController.companyInfoAdditionals = function(p1, p2, p3, p4, p5, callback) {
  dwr.engine._execute(CompanyAjaxController._path, 'CompanyAjaxController', 'companyInfoAdditionals', false, p1, p2, p3, p4, p5, callback);
}



if (CandidateAjaxController == null) var CandidateAjaxController = {};
CandidateAjaxController._path = '/dwr';
CandidateAjaxController.moveCVRecordUp = function(p1, p2, p3, p4, p5, callback) {
  dwr.engine._execute(CandidateAjaxController._path, 'CandidateAjaxController', 'moveCVRecordUp', false, p1, p2, p3, p4, p5, callback);
}
CandidateAjaxController.moveCVRecordDown = function(p1, p2, p3, p4, p5, callback) {
  dwr.engine._execute(CandidateAjaxController._path, 'CandidateAjaxController', 'moveCVRecordDown', false, p1, p2, p3, p4, p5, callback);
}
CandidateAjaxController.editCVRecord = function(p1, p2, p3, p4, p5, callback) {
  dwr.engine._execute(CandidateAjaxController._path, 'CandidateAjaxController', 'editCVRecord', false, p1, p2, p3, p4, p5, callback);
}
CandidateAjaxController.deleteCVRecord = function(p1, p2, p3, p4, p5, callback) {
  dwr.engine._execute(CandidateAjaxController._path, 'CandidateAjaxController', 'deleteCVRecord', false, p1, p2, p3, p4, p5, callback);
}
CandidateAjaxController.candidateProfileDetails = function(p1, p2, p3, p4, p5, callback) {
  dwr.engine._execute(CandidateAjaxController._path, 'CandidateAjaxController', 'candidateProfileDetails', false, p1, p2, p3, p4, p5, callback);
}
CandidateAjaxController.candidateProfileAddress = function(p1, p2, p3, p4, p5, callback) {
  dwr.engine._execute(CandidateAjaxController._path, 'CandidateAjaxController', 'candidateProfileAddress', false, p1, p2, p3, p4, p5, callback);
}
CandidateAjaxController.candidateProfileSettings = function(p1, p2, p3, p4, p5, callback) {
  dwr.engine._execute(CandidateAjaxController._path, 'CandidateAjaxController', 'candidateProfileSettings', false, p1, p2, p3, p4, p5, callback);
}














/**** date util*****/


/**
 * Copyright (c)2005-2009 Matt Kruse (javascripttoolbox.com)
 * 
 * Dual licensed under the MIT and GPL licenses. 
 * This basically means you can use this code however you want for
 * free, but don't claim to have written it yourself!
 * Donations always accepted: http://www.JavascriptToolbox.com/donate/
 * 
 * Please do not link to the .js files on javascripttoolbox.com from
 * your site. Copy the files locally to your server instead.
 * 
 */
/*
Date functions

These functions are used to parse, format, and manipulate Date objects.
See documentation and examples at http://www.JavascriptToolbox.com/lib/date/

*/
Date.$VERSION = 1.02;

// Utility function to append a 0 to single-digit numbers
Date.LZ = function(x) {return(x<0||x>9?"":"0")+x};
// Full month names. Change this for local month names
Date.monthNames = new Array('January','February','March','April','May','June','July','August','September','October','November','December');
// Month abbreviations. Change this for local month names
Date.monthAbbreviations = new Array('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
// Full day names. Change this for local month names
Date.dayNames = new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday');
// Day abbreviations. Change this for local month names
Date.dayAbbreviations = new Array('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
// Used for parsing ambiguous dates like 1/2/2000 - default to preferring 'American' format meaning Jan 2.
// Set to false to prefer 'European' format meaning Feb 1
Date.preferAmericanFormat = true;

// If the getFullYear() method is not defined, create it
if (!Date.prototype.getFullYear) { 
	Date.prototype.getFullYear = function() { var yy=this.getYear(); return (yy<1900?yy+1900:yy); } ;
} 

// Parse a string and convert it to a Date object.
// If no format is passed, try a list of common formats.
// If string cannot be parsed, return null.
// Avoids regular expressions to be more portable.
Date.parseString = function(val, format) {
	// If no format is specified, try a few common formats
	if (typeof(format)=="undefined" || format==null || format=="") {
		var generalFormats=new Array('y-M-d','MMM d, y','MMM d,y','y-MMM-d','d-MMM-y','MMM d','MMM-d','d-MMM');
		var monthFirst=new Array('M/d/y','M-d-y','M.d.y','M/d','M-d');
		var dateFirst =new Array('d/M/y','d-M-y','d.M.y','d/M','d-M');
		var checkList=new Array(generalFormats,Date.preferAmericanFormat?monthFirst:dateFirst,Date.preferAmericanFormat?dateFirst:monthFirst);
		for (var i=0; i<checkList.length; i++) {
			var l=checkList[i];
			for (var j=0; j<l.length; j++) {
				var d=Date.parseString(val,l[j]);
				if (d!=null) { 
					return d; 
				}
			}
		}
		return null;
	};

	this.isInteger = function(val) {
		for (var i=0; i < val.length; i++) {
			if ("1234567890".indexOf(val.charAt(i))==-1) { 
				return false; 
			}
		}
		return true;
	};
	this.getInt = function(str,i,minlength,maxlength) {
		for (var x=maxlength; x>=minlength; x--) {
			var token=str.substring(i,i+x);
			if (token.length < minlength) { 
				return null; 
			}
			if (this.isInteger(token)) { 
				return token; 
			}
		}
	return null;
	};
	val=val+"";
	format=format+"";
	var i_val=0;
	var i_format=0;
	var c="";
	var token="";
	var token2="";
	var x,y;
	var year=new Date().getFullYear();
	var month=1;
	var date=1;
	var hh=0;
	var mm=0;
	var ss=0;
	var ampm="";
	while (i_format < format.length) {
		// Get next token from format string
		c=format.charAt(i_format);
		token="";
		while ((format.charAt(i_format)==c) && (i_format < format.length)) {
			token += format.charAt(i_format++);
		}
		// Extract contents of value based on format token
		if (token=="yyyy" || token=="yy" || token=="y") {
			if (token=="yyyy") { 
				x=4;y=4; 
			}
			if (token=="yy") { 
				x=2;y=2; 
			}
			if (token=="y") { 
				x=2;y=4; 
			}
			year=this.getInt(val,i_val,x,y);
			if (year==null) { 
				return null; 
			}
			i_val += year.length;
			if (year.length==2) {
				if (year > 70) { 
					year=1900+(year-0); 
				}
				else { 
					year=2000+(year-0); 
				}
			}
		}
		else if (token=="MMM" || token=="NNN"){
			month=0;
			var names = (token=="MMM"?(Date.monthNames.concat(Date.monthAbbreviations)):Date.monthAbbreviations);
			for (var i=0; i<names.length; i++) {
				var month_name=names[i];
				if (val.substring(i_val,i_val+month_name.length).toLowerCase()==month_name.toLowerCase()) {
					month=(i%12)+1;
					i_val += month_name.length;
					break;
				}
			}
			if ((month < 1)||(month>12)){
				return null;
			}
		}
		else if (token=="EE"||token=="E"){
			var names = (token=="EE"?Date.dayNames:Date.dayAbbreviations);
			for (var i=0; i<names.length; i++) {
				var day_name=names[i];
				if (val.substring(i_val,i_val+day_name.length).toLowerCase()==day_name.toLowerCase()) {
					i_val += day_name.length;
					break;
				}
			}
		}
		else if (token=="MM"||token=="M") {
			month=this.getInt(val,i_val,token.length,2);
			if(month==null||(month<1)||(month>12)){
				return null;
			}
			i_val+=month.length;
		}
		else if (token=="dd"||token=="d") {
			date=this.getInt(val,i_val,token.length,2);
			if(date==null||(date<1)||(date>31)){
				return null;
			}
			i_val+=date.length;
		}
		else if (token=="hh"||token=="h") {
			hh=this.getInt(val,i_val,token.length,2);
			if(hh==null||(hh<1)||(hh>12)){
				return null;
			}
			i_val+=hh.length;
		}
		else if (token=="HH"||token=="H") {
			hh=this.getInt(val,i_val,token.length,2);
			if(hh==null||(hh<0)||(hh>23)){
				return null;
			}
			i_val+=hh.length;
		}
		else if (token=="KK"||token=="K") {
			hh=this.getInt(val,i_val,token.length,2);
			if(hh==null||(hh<0)||(hh>11)){
				return null;
			}
			i_val+=hh.length;
			hh++;
		}
		else if (token=="kk"||token=="k") {
			hh=this.getInt(val,i_val,token.length,2);
			if(hh==null||(hh<1)||(hh>24)){
				return null;
			}
			i_val+=hh.length;
			hh--;
		}
		else if (token=="mm"||token=="m") {
			mm=this.getInt(val,i_val,token.length,2);
			if(mm==null||(mm<0)||(mm>59)){
				return null;
			}
			i_val+=mm.length;
		}
		else if (token=="ss"||token=="s") {
			ss=this.getInt(val,i_val,token.length,2);
			if(ss==null||(ss<0)||(ss>59)){
				return null;
			}
			i_val+=ss.length;
		}
		else if (token=="a") {
			if (val.substring(i_val,i_val+2).toLowerCase()=="am") {
				ampm="AM";
			}
			else if (val.substring(i_val,i_val+2).toLowerCase()=="pm") {
				ampm="PM";
			}
			else {
				return null;
			}
			i_val+=2;
		}
		else {
			if (val.substring(i_val,i_val+token.length)!=token) {
				return null;
			}
			else {
				i_val+=token.length;
			}
		}
	}
	// If there are any trailing characters left in the value, it doesn't match
	if (i_val != val.length) { 
		return null; 
	}
	// Is date valid for month?
	if (month==2) {
		// Check for leap year
		if ( ( (year%4==0)&&(year%100 != 0) ) || (year%400==0) ) { // leap year
			if (date > 29){ 
				return null; 
			}
		}
		else { 
			if (date > 28) { 
				return null; 
			} 
		}
	}
	if ((month==4)||(month==6)||(month==9)||(month==11)) {
		if (date > 30) { 
			return null; 
		}
	}
	// Correct hours value
	if (hh<12 && ampm=="PM") {
		hh=hh-0+12; 
	}
	else if (hh>11 && ampm=="AM") { 
		hh-=12; 
	}
	return new Date(year,month-1,date,hh,mm,ss);
};

// Check if a date string is valid
Date.isValid = function(val,format) {
	return (Date.parseString(val,format) != null);
};

// Check if a date object is before another date object
Date.prototype.isBefore = function(date2) {
	if (date2==null) { 
		return false; 
	}
	return (this.getTime()<date2.getTime());
};

// Check if a date object is after another date object
Date.prototype.isAfter = function(date2) {
	if (date2==null) { 
		return false; 
	}
	return (this.getTime()>date2.getTime());
};

// Check if two date objects have equal dates and times
Date.prototype.equals = function(date2) {
	if (date2==null) { 
		return false; 
	}
	return (this.getTime()==date2.getTime());
};

// Check if two date objects have equal dates, disregarding times
Date.prototype.equalsIgnoreTime = function(date2) {
	if (date2==null) { 
		return false; 
	}
	var d1 = new Date(this.getTime()).clearTime();
	var d2 = new Date(date2.getTime()).clearTime();
	return (d1.getTime()==d2.getTime());
};

// Format a date into a string using a given format string
Date.prototype.format = function(format) {
	format=format+"";
	var result="";
	var i_format=0;
	var c="";
	var token="";
	var y=this.getYear()+"";
	var M=this.getMonth()+1;
	var d=this.getDate();
	var E=this.getDay();
	var H=this.getHours();
	var m=this.getMinutes();
	var s=this.getSeconds();
	var yyyy,yy,MMM,MM,dd,hh,h,mm,ss,ampm,HH,H,KK,K,kk,k;
	// Convert real date parts into formatted versions
	var value=new Object();
	if (y.length < 4) {
		y=""+(+y+1900);
	}
	value["y"]=""+y;
	value["yyyy"]=y;
	value["yy"]=y.substring(2,4);
	value["M"]=M;
	value["MM"]=Date.LZ(M);
	value["MMM"]=Date.monthNames[M-1];
	value["NNN"]=Date.monthAbbreviations[M-1];
	value["d"]=d;
	value["dd"]=Date.LZ(d);
	value["E"]=Date.dayAbbreviations[E];
	value["EE"]=Date.dayNames[E];
	value["H"]=H;
	value["HH"]=Date.LZ(H);
	if (H==0){
		value["h"]=12;
	}
	else if (H>12){
		value["h"]=H-12;
	}
	else {
		value["h"]=H;
	}
	value["hh"]=Date.LZ(value["h"]);
	value["K"]=value["h"]-1;
	value["k"]=value["H"]+1;
	value["KK"]=Date.LZ(value["K"]);
	value["kk"]=Date.LZ(value["k"]);
	if (H > 11) { 
		value["a"]="PM"; 
	}
	else { 
		value["a"]="AM"; 
	}
	value["m"]=m;
	value["mm"]=Date.LZ(m);
	value["s"]=s;
	value["ss"]=Date.LZ(s);
	while (i_format < format.length) {
		c=format.charAt(i_format);
		token="";
		while ((format.charAt(i_format)==c) && (i_format < format.length)) {
			token += format.charAt(i_format++);
		}
		if (typeof(value[token])!="undefined") { 
			result=result + value[token]; 
		}
		else { 
			result=result + token; 
		}
	}
	return result;
};

// Get the full name of the day for a date
Date.prototype.getDayName = function() { 
	return Date.dayNames[this.getDay()];
};

// Get the abbreviation of the day for a date
Date.prototype.getDayAbbreviation = function() { 
	return Date.dayAbbreviations[this.getDay()];
};

// Get the full name of the month for a date
Date.prototype.getMonthName = function() {
	return Date.monthNames[this.getMonth()];
};

// Get the abbreviation of the month for a date
Date.prototype.getMonthAbbreviation = function() { 
	return Date.monthAbbreviations[this.getMonth()];
};

// Clear all time information in a date object
Date.prototype.clearTime = function() {
  this.setHours(0); 
  this.setMinutes(0);
  this.setSeconds(0); 
  this.setMilliseconds(0);
  return this;
};

// Add an amount of time to a date. Negative numbers can be passed to subtract time.
Date.prototype.add = function(interval, number) {
	if (typeof(interval)=="undefined" || interval==null || typeof(number)=="undefined" || number==null) { 
		return this; 
	}
	number = +number;
	if (interval=='y') { // year
		this.setFullYear(this.getFullYear()+number);
	}
	else if (interval=='M') { // Month
		this.setMonth(this.getMonth()+number);
	}
	else if (interval=='d') { // Day
		this.setDate(this.getDate()+number);
	}
	else if (interval=='w') { // Weekday
		var step = (number>0)?1:-1;
		while (number!=0) {
			this.add('d',step);
			while(this.getDay()==0 || this.getDay()==6) { 
				this.add('d',step);
			}
			number -= step;
		}
	}
	else if (interval=='h') { // Hour
		this.setHours(this.getHours() + number);
	}
	else if (interval=='m') { // Minute
		this.setMinutes(this.getMinutes() + number);
	}
	else if (interval=='s') { // Second
		this.setSeconds(this.getSeconds() + number);
	}
	return this;
};















function plugNS()
{
	var b=1;
	var o=0;
	var p=new Array("Shockwave Flash","Shockwave for Director","RealPlayer","QuickTime","VivoActive","LiveAudio","VRML","Dynamic HTML Binding","Windows Media Services");
	var np=navigator.plugins;
	for(var x=0;x<p.length;x++)
	{for(var i=0;i<np.length;i++)
		if(np[i].name.indexOf(p[x])>=0)o|=b;
		b*=2;
 	}
	return o;
}

function plugIE()
{if(!document.body)
	document.write('<body>');
	var db=document.body;
	var o=0;
	var b=1;
	var p=new Array("D27CDB6E-AE6D-11CF-96B8-444553540000","2A202491-F00D-11CF-87CC-0020AFEECF20","23064720-C4F8-11D1-994D-00C04F98BBC9","","","","90A7533D-88FE-11D0-9DBE-0000C0411FC3","9381D8F2-0288-11D0-9501-00AA00B911A5","22D6F312-B0F6-11D0-94AB-0080C74C7E95");
	db.addBehavior("#default#clientcaps");
	for(var i=0;i<p.length;i++)
	{if(p[i])
		if(db.isComponentInstalled("{"+p[i]+"}","componentid"))o|=b;
		b*=2;
	 }
	 return o;
}

function nedstatbasic(id,options)
{var n=navigator;
 var ver=n.appVersion;
 var name=n.appName;
 var d=document;
 var verIE=parseInt(ver.substring(ver.indexOf("MSIE")+5,ver.indexOf("MSIE")+6));
 if(verIE>0)ver=verIE;
 else ver=parseInt(ver);
 var u="http://m1.nedstatbasic.net/n?id="+id;
 var r;
 if(options&1)
 	r=d.referrer;
 else 
 	r=top.document.referrer;
 
 if(!(options&2))
 {var rc=r;
  var i=rc.indexOf('?');
	 if(i >=0)
	 rc=rc.substring(0, i);
	 i=rc.lastIndexOf('/');
	 if(i >=0)
	 	rc=rc.substring(0, i+1);
		var l=''+d.location;
			if(l.indexOf(rc)==0)
			r='';
	}

 if(r&&(r!=d.location))
 	u+="&r="+escape(r);
		if((name=="Netscape"&&ver>=3))
			u+="&p="+plugNS();
			if(verIE>=5&&n.appVersion.indexOf('Win')>=0&&n.userAgent.indexOf('Opera')<0)
				u+="&p="+plugIE();
					if(ver>=4)
						{var s=screen;
						 var w=s.width;
						 var c=s.colorDepth;
						 if(w)u+="&w="+w;
						 if(c)u+="&c="+c;
						}
					d.write('<a target=_blank href="http://v1.nedstatbasic.net/stats?ACMmlQzZ0sazyd31b8ljnTNaDaHA"><img src="http://m1.nedstatbasic.net/n?id=ACNVBwvT75XwdF5THpoMaWQ4SFPQ" border=0 width=1 height=1></a>');
}





function ratingOver(el){
	var selected, i;
	if(!ratingAlreadyDone){
		selected = el.id.replace("ratingstar_", '');
		for(i=1; i<=5; i++){		
			if(i<=selected){
				document.getElementById("ratingstar_"+i).className = "shine";
				ratingSetMsg(el.title);
			}else{
				document.getElementById("ratingstar_"+i).className = "";
			}
		}
	}
}
function ratingOut(){
	var i;
	if(!ratingAlreadyDone){
		for(i=1; i<=5; i++){		
			if(i<=ratingCurrentValue){
				document.getElementById("ratingstar_"+i).className = "shine";
			}else{
				document.getElementById("ratingstar_"+i).className = "";
			}
		}
		ratingSetMsg(document.getElementById("ratingMsgOpen").innerHTML);
	}
}
function ratingClick(el,site){
	if(!ratingAlreadyDone){
		ratingSetMsg(document.getElementById("ratingMsgThanks").innerHTML);
		ratingAlreadyDone = 1;
		ratingSubmitValue(el,site);
	}
}
function ratingSetMsg(content){
	document.getElementById("ratingMsgCurrent").innerHTML = content;
}
function ratingSubmitValue(el,site){
	var num = el.id.replace("ratingstar_", '');
	PublicAjaxController.ratingboxSubmitRating(site, num, getSecurityToken(), ratingSubmitValueDone);
}
function ratingSubmitValueDone(results){
	//setSecurityToken( results.securityToken );
	incRatingStatsValue("ratingboxStatsRated", 1);
}


function ratingSubmitComment(site){
	var elName, elText, elNameValue, elTextValue;
	elName = document.getElementById("ratingboxCommentName");
	elText = document.getElementById("ratingboxCommentText");

	elNameValue = trim(elName.value);
	elTextValue = trim(elText.value);

	if( elNameValue!='' && elTextValue!='' ) {
		elName.disabled = true;
		elText.disabled = true;
		toggleBoxDisplay( null, 'ratingboxCommentShowError');
		toggleBoxDisplay('ratingboxCommentShowWait', 'ratingboxCommentShowButton');
		PublicAjaxController.ratingboxSubmitComment(site, elNameValue, elTextValue, getLocalizedString("locale.dojotype"), getSecurityToken(), ratingSubmitCommentDone);
	} else {
		toggleBoxDisplay('ratingboxCommentShowError', null);
	}
}
function ratingSubmitCommentDone(results){
	var elName, elText, elList;
	//setSecurityToken( results.securityToken );

	elName = document.getElementById("ratingboxCommentName");
	elText = document.getElementById("ratingboxCommentText");
	elList = document.getElementById("ratingboxCommentList");

	elList.innerHTML = '<div id="ratingboxCommentItem' + results.resultId + '" class="ratingbox_comment_item">'
						+ '	<div><b>' + escapeHTMLEntities(elName.value) + '</b>'
						+ ' <span class="ratingbox_comment_date">(' + results.data + ')'
					    + ' <a href="javascript:ratingDeleteComment(\'' + results.resultId + '\')">' + document.getElementById("ratingMsgDeleteComment").innerHTML + '</a>'
					    + ' </span></div>'
						+ ' <div class="ratingbox_comment_text">' + escapeHTMLEntities(elText.value) + '</div>'
						+ ' </div>'
						+ elList.innerHTML;

	elName.value = '';
	elText.value = '';
	elName.disabled = false;
	elText.disabled = false;

	toggleBoxDisplay('ratingboxCommentHide', 'ratingboxCommentShow');
	toggleBoxDisplay('ratingboxCommentShowButton', 'ratingboxCommentShowWait');
	
	incRatingStatsValue("ratingboxStatsCommented", 1);
}

function ratingCloseCommentForm(){
	toggleBoxDisplay( null, 'ratingboxCommentShowError');
	toggleBoxDisplay('ratingboxCommentHide', 'ratingboxCommentShow')
}

function ratingDeleteComment(id){
	if( confirm( getLocalizedString('js.confirm.delete') ) ) {
		PublicAjaxController.ratingboxDeleteComment(id, getSecurityToken(), ratingDeleteCommentDone);
	}
}
function ratingDeleteCommentDone(results){
	//setSecurityToken( results.securityToken );
	toggleBoxDisplay( null, "ratingboxCommentItem" + results.resultId);
	incRatingStatsValue("ratingboxStatsCommented", -1);
}



function incRatingStatsValue( elId, value) {
	var elCount = document.getElementById(elId), s;
	s = elCount.innerHTML;
	elCount.innerHTML = (parseInt(s.substring(0, s.length-1)) + value) + 'x';
	elCount.className = "success"

}




function get_cookie_value( cookie_name ) {
	var all_cookies = document.cookie.split( ';' ), cur_cookie, i;
	for(i = 0; i < all_cookies.length; i++) {
		cur_cookie = all_cookies[i].split( '=' );
		if ( trim(cur_cookie[0]) == cookie_name ) {
			if ( cur_cookie.length > 1 ) {
				return unescape( trim(my_cookie[1]) );
			}
		}
	}
	return null;
}







function slideItByPixel(amt) {
	checkLeftSlideControl(dojo.coords("slide_panel_1").l + amt);
	checkRightSlideControl(dojo.coords("slide_panel_1").l + dojo.coords("slide_panel_1").w + amt);
    var slideArgs = {
        node: "slide_panel_1",
        top: (dojo.coords("slide_panel_1").t).toString(),
        left: (dojo.coords("slide_panel_1").l + amt).toString(),
        unit: "px"
    };
    dojo.fx.slideTo(slideArgs).play();
}

function checkLeftSlideControl(pos) {
  if( pos >= 0 ) {
    document.getElementById("slide_control_left").style.display = 'none';
  } else {
    document.getElementById("slide_control_left").style.display = 'block';
  }
}

function checkRightSlideControl(pos) {
  if( pos < 530 ) {
    document.getElementById("slide_control_right").style.display = 'none';
  } else {
    document.getElementById("slide_control_right").style.display = 'block';
  }
}






