	// Form Builder v2.3 TFA/Freja 2.0 Edition (Apr. 2006) - FormAssembly.com
	// Copyright (c) 2005-2006 Cedric Savarese (4213miles.com)
	// All Rights Reserved - do not reuse without permission.
	// For licensing information visit: http://www.formassembly.com/about-form-builder.php
	
	
	// Error Handler
	window.onerror = errorHandler;
	
	// Freja config
	Freja.AssetManager.HTTP_METHOD_TUNNEL = null;
	Freja.AssetManager.XSLT_SERVICE_URL   = XSLT_SERVICE_URL;
	
	var preferences = { 
		alwaysUpdatePreview: false,
		startTab: 'tabHelp'
	};
	var formId = null;
	
	// Form Builder Resources
	if(typeof DATABASE_SERVICE_URL == 'undefined') {
		alert('Configuration file not loaded.\nPlease make sure to include config/form-builder-config.js in your page.');
	}	
	var view_form_summary            = getView("xsl/builder_2_3_treeview.xsl");
	var view_form_properties         = getView("xsl/builder_2_3_form_properties.xsl");
	var view_field_properties        = getView("xsl/builder_2_3_field_properties.xsl");
	var view_field_adv_properties    = getView("xsl/builder_2_3_field_adv_properties.xsl");
	var view_fieldset_properties     = getView("xsl/builder_2_3_fieldset_properties.xsl");
	var view_fieldset_adv_properties = getView("xsl/builder_2_3_fieldset_adv_properties.xsl");
	var view_form_preview            = getView("xsl/builder_2_3_preview.xsl");
	var form					     = getModel(getFormURL());
	var field_template			     = getModel("xml/tmpl_field.xml");
	var fieldset_template		     = getModel("xml/tmpl_fieldset.xml");
	var fieldchoices_template        = getModel("xml/tmpl_listchoices.xml");
	var ids = new Array(); 			 // List of generated element ids.
	
	
	
	// 3rd party libraries setup
	// ---------------------------------------------------------------------------------------------
	// wHelpers initialization
	helpers = wFORMS.helpers;
					
	// Overwrite wForms default settings & handlers
	wFORMS.helpers.removeEvent(window,'load',wFORMS.onLoadHandler);
	wFORMS.onLoadHandler                = null;  
	wFORMS.functionName_formValidation  = "postBack";
	wFORMS.preserveRadioName            = false;
	wFORMS.runValidationOnPageNext      = false; // (wouldn't be convenient in the preview panel)
	wFORMS.debugLevel = 0;
	
	
	// Main initialization routine
	// ---------------------------------------------------------------------------------------------	
	function init() {
		enableTabs();
		enableToolbar();
		view_form_summary.render(form, 'placeholder_summary');						
		view_form_preview.render(form, 'placeholder_preview');
	}
	function initForm() {
		ids = getIds(form.document); // init ids array
	}
	window.onload = init;
	Freja._aux.connect(form, 'onload', initForm);

	function getFormURL() {
		var querystring = window.location.search;
		if(querystring.indexOf('formId=') != -1) {		
			formId = querystring.split('formId=')[1].split('&')[0];
			var formURL = DATABASE_SERVICE_URL + "?formId=" + formId;
			if(querystring.indexOf('template=') != -1)
				formURL += "&template=" + querystring.split('template=')[1].split('&')[0];
			else
				formURL += "&template=1";
		} else {
			if(querystring.indexOf('demo=') != -1) {	
				var demoId = querystring.split('demo=')[1].split('&')[0];
				var formURL = "xml/tmpl_form_demo"+demoId+".xml"; // Demo form
				preferences.startTab = 'tabPreview';
			} else {
			var formURL = "xml/tmpl_form.xml"; // New Form XML Skeleton
			}
		}
		return formURL;			
	}
	
	
	// ---------------------------------------------------------------------------------------------
	// MAIN TOOLBAR
	// ---------------------------------------------------------------------------------------------
	function enableToolbar() {	
		document.getElementById('addField').onclick        = addField;
		document.getElementById('addFieldset').onclick     = addFieldset;
		document.getElementById('addPredefined').onclick   = addPredefined;
		document.getElementById('form:css').onchange 	   = changeStylesheet;	
		document.getElementById('topToolBarForm').onsubmit = postBack;			
		
	}
		
	// ---------------------------------------------------------------------------------------------
	// TABS & PANELS SWITCHING
	// ---------------------------------------------------------------------------------------------	
	function enableTabs() {
		document.getElementById('tabPreview').onclick       = switchTab;
		document.getElementById('tabProperties').onclick    = switchTab;
		document.getElementById('tabAdvProperties').onclick = switchTab;
		document.getElementById('tabHelp').onclick          = switchTab;
		switchTab(preferences.startTab);	
	}	
	function switchTab(e) {
		
		resetTabs();
		
		if(typeof e == 'string') 
			tab = document.getElementById(e);
		else
			tab = helpers.getSourceElement(e);
		
		if(!helpers.hasClass(tab,'selected')) 
			tab.className = tab.className + ' selected';
	
		switch(tab.id) {
			case "tabPreview":				
				document.getElementById('previewPanel').style.display = 'block';	
				break;
			case "tabProperties":
				document.getElementById('placeholder_properties').style.display = 'block';
				break;
			case "tabAdvProperties":
				document.getElementById('placeholder_advproperties').style.display = 'block';	
				break;
			case "tabHelp":
				document.getElementById('placeholder_help').style.display = 'block';	
				break;				
		}
	}	
	function resetTabs() {
		document.getElementById('previewPanel').style.display = 'none';
		document.getElementById('placeholder_properties').style.display = 'none';
		document.getElementById('placeholder_advproperties').style.display = 'none';
		document.getElementById('placeholder_help').style.display = 'none';
		document.getElementById('tabPreview').className = document.getElementById('tabPreview').className.replace('selected','');
		document.getElementById('tabProperties').className = document.getElementById('tabProperties').className.replace('selected','');
		document.getElementById('tabAdvProperties').className = document.getElementById('tabAdvProperties').className.replace('selected','');
		document.getElementById('tabHelp').className = document.getElementById('tabHelp').className.replace('selected','');
	}
	function enableTab(id) {
		document.getElementById(id).style.display = 'inline';
	}
	function disableTab(id) {
		document.getElementById(id).style.display = 'none';
	}
	// ---------------------------------------------------------------------------------------------	
	// VIEW BEHAVIORS 
	// ---------------------------------------------------------------------------------------------

	// FORM SUMMARY (TREEVIEW) BEHAVIORS 
	view_form_summary.behaviors['editFieldsetLink'] = {
		onclick: function(n) { 			
			treeview.changeSelected(n);			
			editFieldset(extractId(n));
		}
	}
	view_form_summary.behaviors['editFieldLink'] = {
		onclick: function(n) { 					
			treeview.changeSelected(n);	
			editField(extractId(n));
		}
	}
	view_form_summary.behaviors['editFormLink'] = {
		onclick: function(n) { 	
			treeview.clearSelected(n);		
			switchTab('tabProperties');	
			disableTab('tabAdvProperties');					
			view_form_properties.render(form, 'placeholder_properties');	
		}
	}
	
	// FORM PROPERTIES BEHAVIORS 
	function addFormPropertiesBehaviors() {			
		wFORMS.addBehaviors(document.getElementById('placeholder_properties')); 			
	}	
	Freja._aux.connect(view_form_properties, 'onrendercomplete', addFormPropertiesBehaviors);
	
	// FIELD PROPERTIES BEHAVIORS
	view_field_properties.behaviors['duplicateAction'] = {
		onclick: function(n) { 					
			var id = duplicateElement(extractId(n));
			treeview.render(); 	
			updatePreview();		
		}
	}
	function addFieldPropertiesBehaviors() {								

		//var timerStart = (new Date()).getTime();		
		//wFORMS.behaviors['switch'].clear();
		wFORMS.addBehaviors(document.getElementById('placeholder_properties')); 
		//var timerEnd = (new Date()).getTime();
		//var duration = timerEnd - timerStart;
		//wFORMS.debug('behaviors generic method: ' +  duration + 'ms');
		helpers.addEvent(document.getElementById('field:type'), "change", addListChoices);	
		helpers.addEvent(document.getElementById('cancelAction'), "click", cancelEdit);	
		
	}			
	Freja._aux.connect(view_field_properties, 'onrendercomplete', addFieldPropertiesBehaviors);


	// FIELDSET PROPERTIES BEHAVIORS
	view_fieldset_properties.behaviors['duplicateAction'] = {
		onclick: function(n) { 					
			var id = duplicateElement(extractId(n));
			treeview.render(); 		
			updatePreview();	
		}
	}
	function addFieldsetPropertiesBehaviors() {		
		//wFORMS.behaviors['switch'].clear();			
		wFORMS.addBehaviors(document.getElementById('placeholder_properties'));		
		helpers.addEvent(document.getElementById('cancelAction'), "click", cancelEdit);	
	}	
	Freja._aux.connect(view_fieldset_properties, 'onrendercomplete', addFieldsetPropertiesBehaviors);
	
	// ADVANCED PROPERTIES BEHAVIORS
	function addAdvancedPropertiesBehaviors() {		
		//wFORMS.behaviors['switch'].clear();	
		wFORMS.addBehaviors(document.getElementById('placeholder_advproperties'));
	}
	Freja._aux.connect(view_fieldset_adv_properties, 'onrendercomplete', addAdvancedPropertiesBehaviors);
	Freja._aux.connect(view_field_adv_properties, 'onrendercomplete', addAdvancedPropertiesBehaviors);
	


	// ---------------------------------------------------------------------------------------------	
	// TREE VIEW 
	// ---------------------------------------------------------------------------------------------	
	var Treeview = function() {
		var params       = arguments[0] || {};
		this.model       = params.model;
		this.listId      = params.listId;
		this.dragDrop    = new wDrag();
		this.selected    = null;
		this.onsort      = null;
		
		if(params.view) this.addView(params.view, params.placeholder)
		
	}	
	Treeview.prototype.addView = function(view, placeholder) {
		this.view = view;
		this.placeholder = placeholder || this.view.placeholder;
		var self = this;
		
		this.view.behaviors['treeviewExpandLink'] = {
			onclick: function(n) { 		
				self.expand(extractId(n));				
			}
		}
		this.view.behaviors['treeviewCollapseLink'] = {
			onclick: function(n) {
				self.collapse(extractId(n));
			}
		}	
		Freja._aux.connect(this.view, 'onrendercomplete', Freja._aux.bind('addDragDrop',this));
	}
	Treeview.prototype.addDragDrop = function() {
		var self = this;
		this.dragDrop.create(this.listId, { onUpdate: Freja._aux.bind('sort',self)} );		
	}
	Treeview.prototype.expand = function(elementId) {		
		var section = this.model.getElementById(elementId);
		section.setAttribute('treeview','expanded');
		this.render();		
	}
	Treeview.prototype.collapse = function(elementId) {
		var section = this.model.getElementById(elementId);
		section.setAttribute('treeview','collapsed');
		this.render();
	}	
	Treeview.prototype.changeSelected = function(node) {		
		while(node && node.tagName != 'LI')
			node = node.parentNode;
		if(!node) return;					
		this.clearSelected();		
		this.selected = node;
		this.selected.className += ' selected';
	}
	Treeview.prototype.clearSelected = function() {	
		if(this.selected) {
			this.selected.className = this.selected.className.replace('selected','');
		}
	}	
 	Treeview.prototype.sort = function(list,listElement) {
 		//var shouldRender = false;
		var modelElement = this.model.getElementById(extractId(listElement.id));
		var listParent = listElement.parentNode;
		if(listParent.tagName.toLowerCase()=='ul')
			listParent  = listParent.parentNode;
		if(listParent.id == 'dragTrash') {
			if(window.confirm("Are you sure you want to delete this?")) {
				modelElement.parentNode.removeChild(modelElement);
				//shouldRender = true;
			}
		} else {	
			var pn  = null;
			var sn  = null;
			var pId = extractId(listParent.id);
			if(pId)
				var pn = this.model.getElementById(pId);	
			if(pn) {
				if(pn.getAttribute('treeview')== 'collapsed') {
					pn.setAttribute('treeview','expanded');			
					//shouldRender = true;
				}
			}
			else
				pn = this.model.document.documentElement;		
			if(listElement.nextSibling) {
				var nextSiblingId = extractId(listElement.nextSibling.id);			
				sn = this.model.getElementById(nextSiblingId);	
			}
			
			try {
				pn.insertBefore(modelElement, sn);		
			} catch(x) { };
		}
		//if(shouldRender)
			this.render();
		if(this.onsort)
			this.onsort();
	}	
	
	Treeview.prototype.render = function() {
		this.dragDrop.clear(); // clear drag&drop before rendering treeview
		this.view.render(this.model, this.placeholder);		
	}		
	
	var treeview = new Treeview();
	treeview.model  = form;
	treeview.listId = "treeViewList";
	treeview.onsort = updatePreview;
	treeview.addView(view_form_summary,"placeholder_summary");


	// ---------------------------------------------------------------------------------------------	
	// FORM PREVIEW
	// ---------------------------------------------------------------------------------------------
	
	function changeStylesheet(e) {
		var css     = this.options[this.selectedIndex].value;
		var preview = document.getElementById('form_preview');
		if(preview) {
			preview.className = css;
		}
		form.document.documentElement.setAttribute('css',css);
	}	
	function showPreviewUpdatedNotice() {	
		var html = "<p style='text-align:center'>Form Modified.</p>";
		html += "<p style='text-align:center'><input type='button' id='updatePreviewButton' value='Update Preview' />";
		html += "<br/><br/>";
		html += "<input type='checkbox' value='1' id='alwaysUpdatePreviewCbx' "+(preferences.alwaysUpdatePreview?"checked='checked":"")+" style='vertical-align:bottom' />";
		html += "<label for='alwaysUpdatePreviewCbx'>always update the preview</label>";
		document.getElementById('placeholder_preview').innerHTML = html;
		document.getElementById('updatePreviewButton').onclick = function() { 
			updatePreview(true); 
		};
		document.getElementById('alwaysUpdatePreviewCbx').onclick = function() { 			
			preferences.alwaysUpdatePreview = document.getElementById('alwaysUpdatePreviewCbx').checked;
		};
	}
	function updatePreview(force) {
		switchTab('tabPreview');
		if(preferences.alwaysUpdatePreview || force==true) {			
			view_form_preview.render(form, 'placeholder_preview');							
		} else {
			showPreviewUpdatedNotice();
		}
	}
		// FORM PREVIEW BEHAVIORS
	function addFormPreviewBehaviors() {
		//wFORMS.behaviors['switch'].clear();		
		wFORMS.addBehaviors(document.getElementById('placeholder_preview')); 				
		if(!form.document.documentElement.getAttribute('css')) {		
			form.document.documentElement.setAttribute('css', 'antique');
			var preview = document.getElementById('form_preview');
			if(preview) {
				preview.className = 'antique';
			}
		}
	}	
	Freja._aux.connect(view_form_preview, 'onrendercomplete', addFormPreviewBehaviors);
	
	// ---------------------------------------------------------------------------------------------	
	// FORM EDITING
	// ---------------------------------------------------------------------------------------------

	// Create a new field
	function addField(e, newField) { 			
		if(!newField) newField = field_template; // default empty field
		 		
		var lastFormElement = form.document.documentElement.lastChild;
		while(lastFormElement && lastFormElement.nodeType==3) 
			lastFormElement = lastFormElement.previousSibling;
		
		if (lastFormElement.tagName=='fieldset') {
			var insertPoint = lastFormElement;
		} else {
			var insertPoint = form.document.documentElement;
		}		
		if(typeof form.document.importNode != 'undefined') 
			newField = insertPoint.appendChild(form.document.importNode(newField.document.documentElement,true));
		else 
			newField = insertPoint.appendChild((newField.document.documentElement).cloneNode(true));		
		
		var id = helpers.randomId();
 		newField.setAttribute('id',id);
 		
 		// update display
		view_form_summary.render(form, 'placeholder_summary');
		
		editField(id);
		return id;
	} 
	// Edit a field
	function editField(id) {
		view_field_properties.render(form, 'placeholder_properties',  { fieldId : id });
		view_field_adv_properties.render(form, 'placeholder_advproperties',  { fieldId : id });
		switchTab('tabProperties');	
		enableTab('tabAdvProperties');	
	}
	// Create a new fieldset
	function addFieldset(e, newFieldset) { 	
		if(!newFieldset) newFieldset = fieldset_template; // default empty fieldset
		
		var insertPoint = form.document.documentElement;
		
		if(typeof form.document.importNode != 'undefined') 
			newFieldset = insertPoint.appendChild(form.document.importNode(newFieldset.document.documentElement,true));
		else 
			newFieldset = insertPoint.appendChild((newFieldset.document.documentElement).cloneNode(true));		
		var id = helpers.randomId();
 		newFieldset.setAttribute('id',id); 	
 		
 		// check if any childnodes, set the attribute as well. (for predefined sections)
 		var cn = newFieldset.getElementsByTagName('*');
 		for(var i=0;i<cn.length;i++) {
 			if(cn[i].tagName.toUpperCase()=='FIELD' || cn[i].tagName.toUpperCase()=='FIELDSET') {
				var fieldId = cn[i].getAttribute('id'); 
				if(isTempId(fieldId)) {
					// should get the label instead of randomId here.
 					cn[i].setAttribute('id',idify(helpers.randomId())); 	
				}
 			}
 		}
 		
 		// update display
 		view_form_summary.render(form, 'placeholder_summary');

		editFieldset(id);
		return id; 			
	}
	// Edit a fieldset
	function editFieldset(id) {
		switchTab('tabProperties');
		enableTab('tabAdvProperties');				
		view_fieldset_properties.render(form, 'placeholder_properties', {fieldId: id});
		view_fieldset_adv_properties.render(form, 'placeholder_advproperties', {fieldId: id}); 		
	}	
	// addListChoices: Triggered by 'onChange' event on 'field:type' select.
	// Appends 'fieldchoices' model to the field definition if the field type 
	// selected is multi-choices.
	function addListChoices(e) { 			
		
		var field       = helpers.getSourceElement(e);
		var fieldType   = field.options[field.selectedIndex].value;
		var formElement = field.form;
		if(fieldType =='radio' || fieldType == 'checkbox' || fieldType == 'select1' || fieldType == 'select') {
			var fieldId = document.getElementById('nodeId').value;
			var n   = form.getElementById(fieldId);
			var cn  = n.getElementsByTagName("choices")[0];
			if(!cn) {			
				if(typeof form.document.importNode != 'undefined') 
					n.appendChild(form.document.importNode(fieldchoices_template.document.documentElement,true));
				else 
					n.appendChild((fieldchoices_template.document.documentElement).cloneNode(true));
			}
			form.updateFrom(view_field_properties);
			view_field_properties.render(form, 'placeholder_properties',  { fieldId : fieldId });			
		} 
	} 
	// Create a new field or fieldset based on a predefined template
	function addPredefined(e) {
		
		var ps = document.getElementById('predefinedSelect');
		var url = ps.options[ps.selectedIndex].value;		
		if (url!="") {		
			var predefined = null;
			// check if we already have loaded that templated.			
			for (var i=0; i < Freja.AssetManager.models.length; i++) {				
				if (Freja.AssetManager.models[i].url == "xml/predefined/"+url) {
					predefined = Freja.AssetManager.models[i];
					break;
				}
			}	
			if(!predefined) {				
				predefined = getModel("xml/predefined/"+url);
				Freja._aux.connect(predefined, 'onload', function(e) {											
					//TODO: onload not triggered in IE (testing locally )
					if(predefined.document.documentElement.tagName.toUpperCase()=='FIELDSET') {
						addFieldset(null, predefined);
					} else
						addField(null, predefined);
				});
			} else {
				if(predefined.document.documentElement.tagName.toUpperCase()=='FIELDSET')	
					addFieldset(null, predefined);
				else
					addField(null, predefined);			
			}
			
		}
	}
	// Copy the field or fieldset and append it to the form
	function duplicateElement(id) {
		
		var element = form.getElementById(id);		
		var newElement = element.cloneNode(true);
		// idify usually gets the field label, but id should do here.
		id = idify(id.replace('wf_','')) 
		newElement.setAttribute('id',id);
		
		var allElements = newElement.getElementsByTagName('*');
		for (var i=0; i < allElements.length; i++) {
			var cid = allElements[i].getAttribute('id');
			if(cid) {
				allElements[i].setAttribute('id', idify(cid.replace('wf_','')) );
			}
		}
		var insertPoint = element.parentNode;
		insertPoint.insertBefore(newElement, element.nextSibling);
		
		return id;		
	}
	
	function cancelEdit() {
		document.getElementById('placeholder_properties').innerHTML = '';
		document.getElementById('placeholder_advproperties').innerHTML = '';
		switchTab('tabPreview');
		//todo: rollback change on model.
	}
	// ---------------------------------------------------------------------------------------------
	// POST BACK
	// ---------------------------------------------------------------------------------------------

	// postBack
	function postBack(e) {				
		if(wf.formValidation(e)) {	
			var srcElement = helpers.getSourceElement(e);
			
			switch(srcElement.id) {
				case 'edit_properties_form':
					form.updateFrom(view_form_properties);					
					// handle 'cancel button' option
					var secondaryAction = form.document.documentElement.getElementsByTagName("action")[1];
					if(document.getElementById('includeCancelYes').checked) {
						if(secondaryAction) {
							secondaryAction.setAttribute('label',document.getElementById('formSecondaryAction').value);
						} else {
							var secondaryAction = form.document.createElement("action");
							secondaryAction     = form.document.documentElement.appendChild(secondaryAction);
							secondaryAction.setAttribute('level','secondary');
							secondaryAction.setAttribute('type','cancel');
							secondaryAction.setAttribute('label',document.getElementById('formSecondaryAction').value);
						}	
					} 
					else if(secondaryAction) {
						secondaryAction.parentNode.removeChild(secondaryAction);
					}
					break;
								
				case 'edit_properties_field':
					form.updateFrom(view_field_properties);	
					updateListOfChoices();			
					// replaces random id w/ a meaningful one					
					var fieldId = document.getElementById('nodeId').value;										
					if(isTempId(fieldId)) {
						var fieldName = form.get("//field[@id='"+fieldId+"']/label");
						form.set("//field[@id='"+fieldId+"']/@id",idify(fieldName));
					}
					break;

				case 'edit_adv_properties_field':
					form.updateFrom(view_field_adv_properties);
					break;

				case 'edit_properties_fieldset':					
					form.updateFrom(view_fieldset_properties);		
					// replaces random id w/ a meaningful one
					var fieldsetId = document.getElementById('nodeId').value;
					if((fieldsetId)) {
						var fieldsetName = form.get("//fieldset[@id='"+fieldsetId+"']/@name");
						form.set("//fieldset[@id='"+fieldsetId+"']/@id",idify(fieldsetName));					
					}
					break;

				case 'edit_adv_properties_fieldset':
					form.updateFrom(view_fieldset_adv_properties);
					break;
					
				case 'topToolBarForm':		
					//document.getElementById('xmldebug').innerHTML="<br /><textarea rows='10' cols='80'>"+document.getElementById('placeholder_preview').innerHTML+"</textarea>"; // Freja._aux.serializeXML(form.document)															

					var req  = Freja.AssetManager.openXMLHttpRequest("POST", DATABASE_SERVICE_URL);					
					var data = "frmXML="+encodeURIComponent(Freja._aux.serializeXML(form.document));
					data += "&formHTML=na";
					if(formId)
						data += "&formId="+encodeURIComponent(formId);
					try {								
						var comm = Freja._aux.sendXMLHttpRequest(req, data);
						comm.addCallbacks(redirectAfterSave,notifySaveError);
					} catch (ex) {						
						d.errback(ex);
					}										
					return helpers.preventEvent(e); 
					break;
				
				case 'wf_TFA20Registration':  
					if(srcElement['tfa_reg_Password'].value != "" && 
					   srcElement['tfa_reg_Password'].value != srcElement['tfa_reg_ConfirmPassword'].value) {
						wFORMS.showError(srcElement['tfa_reg_ConfirmPassword'],"The passwords don't match");
						return wh.preventEvent(e);	
					} 
					ajaxRegistration(e);
					return helpers.preventEvent(e); 	
					break;
				
				case 'wf_TFA20Login':
					ajaxLogin(e);
					return helpers.preventEvent(e); 	
					break;
			}
			treeview.render();
			updatePreview();
		}	
		return helpers.preventEvent(e); 		
	}
	
	function updateListOfChoices() {
	
		var fieldId = document.getElementById('nodeId').value;
		var fieldElement = form.getElementById(fieldId);	
		var type = fieldElement.getAttribute('type');
		if (type=="radio" || type=="checkbox" || type=="select1" || type=="select") {
			
			// make sure to clean validation rule
			fieldElement.setAttribute('validation','');
			
			var ctr = document.getElementById('choiceRepeat-RC');
			if(ctr) {				
				// Get the <choices> Node in the XML document. Create it if not existant
				var choices = fieldElement.getElementsByTagName("choices")[0];
				if(!choices) { 
					var choices = form.document.createElement("choices");
					choices     = fieldElement.appendChild(choices);
				}
				// Get existing <choice> Nodes in the XML document
				var lChoices    = choices.getElementsByTagName("choice");
				var toBeDeleted = new Array();
				
				// Handling of the wForms Repeat behavior 
				var cnt = parseInt(ctr.value);
				for(var i=1;i<=cnt;i++) {
					if(i==1)
						var suffix = '';
					else
						var suffix = '-'+i;
					// Map 'choice' fields to the <choice> XML node.
					var fLabel = document.getElementById('listItemLabel'+suffix);
					if(fLabel) {
						if(lChoices.length >= i) {
							var choice = lChoices[i-1];
						} else { // ..or create <choice> node
							var choice = form.document.createElement("choice");
							var choice = choices.appendChild(choice);
						}	
						
						// replace random generated id by a more meaningful one.	
						if(isTempId(choice.getAttribute('id'))) {
							var cId = idify(fLabel.value);
							choice.setAttribute('id', cId); 
						}
						// set choice value
						if(fieldElement.getAttribute('type')=='checkbox') 
							var value = 'yes';
						else
							var value = choice.getAttribute('id');
						setElementValue(choice, "value", value);
						// set choice label
						setElementValue(choice, "label", fLabel.value);
						// set choice default attribute
						if (document.getElementById('listItemSelected'+suffix).checked)
							choice.setAttribute('default',"Y");
						else
							choice.setAttribute('default',"");
						// set choice switch attribute (wforms switch behavior)
						choice.setAttribute('switch',document.getElementById('optionSwitchId'+suffix).options[document.getElementById('optionSwitchId'+suffix).selectedIndex].value);

					} else {
						// mark row for deletion.
						if(lChoices.length >= i) {
							toBeDeleted.push(lChoices[i-1]);					
						}
					}
				}
				// remove deleted rows.
				for(var i=0; i < toBeDeleted.length; i++ )
					toBeDeleted[i].parentNode.removeChild(toBeDeleted[i]);
			}
		}
	}
	
	function redirectAfterSave(obj) {
		if(confirm("Your form has been saved. You will now be taken to the \"Display and Processing Options\" page.\n\nIf you wish to keep working on your form, click \"cancel\".")) {
			document.location.href = REDIRECT_ON_SAVE_URL + "?formId=" + obj.responseText;
		} else {
			document.getElementById('placeholder_properties').innerHTML  = "Form Saved.";
			formId = parseInt(obj.responseText);
			form.document.documentElement.setAttribute("dbFormId",formId);
			switchTab('tabProperties');
		}
	}	

	function notifySaveError(obj) {
		switch(obj.status) {
			case 401: 
			case 403:								
				// authentication/not logged in error
				loadHTML(AUTHENTICATION_FORM_URL, function(html) { 
					document.getElementById('placeholder_properties').innerHTML  = "<p>Please login or register first</p>" + html;
					document.getElementById('wf_TFA20Registration').style.display = 'none';
					switchTab('tabProperties');
					wFORMS.addBehaviors('placeholder_properties'); 	
					wFORMS.helpers.addEvent(document.getElementById('registrationLink'), "click", function(){ 
						document.getElementById('wf_TFA20Login').style.display		  = 'none';
						document.getElementById('wf_TFA20Registration').style.display = 'block'; } );
					wFORMS.helpers.addEvent(document.getElementById('loginLink'), "click", function(){ 
						document.getElementById('wf_TFA20Login').style.display		  = 'block';
						document.getElementById('wf_TFA20Registration').style.display = 'none'; } );					
				 });
				break;
			default:
				alert("The following error occured while saving the form:\nError "+ obj.status+ ":  " + obj.responseText);
		}
	}
	
	// ====================================================================================================
	// AUTHENTICATION / REGISTRATION FUNCTIONS
	// ====================================================================================================
	
	function ajaxRegistration(e) {
		// do not let it happen twice
		var b = document.getElementById('submitRegistration');
		if (b.value != ' Wait...') 
			b.value  = ' Wait...';
		else 
			return wFORMS.helpers.preventEvent(e);
		
		// ok, proceed
		document.getElementById('message2PlaceHolder').innerHTML = "";
		var req  = Freja.AssetManager.openXMLHttpRequest("POST", REGISTRAR_SERVICE_URL);	
		var data = "msgformat=html&tfa_reg_Username="+encodeURIComponent(document.getElementById('tfa_reg_Username').value)+"&tfa_reg_Password="+encodeURIComponent(document.getElementById('tfa_reg_Password').value)+"&tfa_reg_ConfirmPassword="+encodeURIComponent(document.getElementById('tfa_reg_ConfirmPassword').value)+"&tfa_reg_Email="+encodeURIComponent(document.getElementById('tfa_reg_Email').value);		
		var comm = Freja._aux.sendXMLHttpRequest(req, data);
		comm.addCallbacks(
			function(xhr) { /* OK */
				REDIRECT_ON_SAVE_URL = "/upgrade-plan.php?new=1&";
				document.getElementById('placeholder_properties').innerHTML = "Thank you! You can now save your form.";
			} ,
			function(xhr) { /* ERROR */
				b.value="Sign Up";
				document.getElementById('tfa_reg_Username').focus();
				document.getElementById('message2PlaceHolder').innerHTML = "<p class='errMsg'>" + xhr.responseText + "</p>";
			} );
	}
	
	function ajaxLogin(e) {
		// do not let it happen twice
		var b = document.getElementById('submitLogin');
		if(b.value != ' Wait...') 
			b.value = ' Wait...';
		else 
			return wh.preventEvent(e);
		
		// ok, proceed
		document.getElementById('messagePlaceHolder').innerHTML = "";
	
		var data = "msgformat=html&tfa_Username="+encodeURIComponent(document.getElementById('tfa_Username').value)+"&tfa_Password="+encodeURIComponent(document.getElementById('tfa_Password').value);
		if(document.getElementById('tfa_AutoLogin').checked)
			data += "&tfa_AutoLogin="+encodeURIComponent(document.getElementById('tfa_AutoLogin').value);
	
		var req  = Freja.AssetManager.openXMLHttpRequest("POST", REGISTRAR_SERVICE_URL);	
		var comm = Freja._aux.sendXMLHttpRequest(req, data);
		comm.addCallbacks(
			function(xhr) { /* OK */
				document.getElementById('placeholder_properties').innerHTML = "Thank you! You can now save your form.";
			} ,
			function(xhr) { /* ERROR */
				b.value=' Login';
				document.getElementById('messagePlaceHolder').innerHTML = "<p class='errMsg'>" + xhr.responseText + "</p>";
			} );
	}
	// ---------------------------------------------------------------------------------------------
	// MISC.
	// ---------------------------------------------------------------------------------------------
	function extractId(obj) {
		// format: 'anystring__id'. Returns the part after the '-'.
		//         or [event object]
		// used to encode a Model element id in a unique html id.
		
		if(!obj) obj=window.event;
		var id = null;
		
		switch(typeof obj) {
			case 'string':
				id = obj;
				break;
			case 'object':					
				if(!obj.id) // should not do that! should find another way to detect is obj is an event.
					obj = helpers.getSourceElement(obj);
				id = obj.id;					
				break;
			case 'undefined':
				return null;
				break;
			default:
				alert('extractId, unhandled object type: ' + typeof obj);
				return null;
				break;
		}				
		id = id.substr(id.lastIndexOf('__')+2);
		
		return id;
	}	
	// function idify(n) : Transform a string in a unique 'id-type' string.
	// prepend 'wf_' to the string. idify should not run twice on the same field to set its id (use isTempId to check before calling idify)
	function idify(n) {
		var reg = new RegExp("[^a-zA-Z0-9\-]","gi");			 // strip illegal characters
		var s   = n.replace(reg,"");	
		s       = 'wf_' + s;									 // make sure first char is not digit	
		if(s.length > 20)
			s   = s.substring(0,20);
	
		var id  = s;  
		for(var i=0; i < ids.length && ids[i].toLowerCase()!=id.toLowerCase(); i++);	 	 // check if already used 
		
		j = 1;
		while(i != ids.length) {								 // already in the list.
			id = s + j.toString();                               // uniquify it
			for(var i=0; i < ids.length && ids[i].toLowerCase()!=id.toLowerCase(); i++);		 
			j++;
		}
		ids[ids.length] = id; 								 	 // store the unique id
		return id;
	}
	function isTempId(id) {
		if(id && id.length > 3 && id.substring(0,3) == 'wf_') return false; // id already idify-ed.
		return true;
	}
	
	function getIds(element) {
		var idArray  = new Array();
		var nodeList = element.getElementsByTagName("*");
		for(var i=0; i < nodeList.length; i++) {
			if (nodeList[i].getAttribute('id')) {
				var id = nodeList[i].getAttribute('id');
				wFORMS.debug('adding id:' + id);
				while(isInArray(idArray, id)) {
					// dupe ...bad!  should not happen
					id = id + '00' + helpers.randomId();
					nodeList[i].setAttribute('id',id);
					wFORMS.debug('fixed duplicate id:' + id + " on " + nodeList[i].nodeName);
				} 
				idArray[idArray.length] = id;
			}
		}
		return idArray;
	}
	
	function isInArray(idArray, id) {
		for(var i=0;i < idArray.length; i++) 
				if(idArray[i]==id) return true;
		return false;
	}
	
	// Set the textnode of an element (as a CDATA section). Creates the element if non existent.
	function setElementValue(parentNode, elementName, value) {
		if(!parentNode) return;
		var n = parentNode.getElementsByTagName(elementName)[0];
		if(!n) {
			var nn = form.document.createElement(elementName);
			n = parentNode.appendChild(nn);
		}
		while(n.firstChild && (n.firstChild.nodeType==3 || n.firstChild.nodeType==4)) 
			n.removeChild(n.firstChild);

		var txtNode = form.document.createCDATASection(value);
		n.appendChild(txtNode);
	}
	
	function loadHTML(url, callback) {
		var req  = Freja.AssetManager.openXMLHttpRequest("GET", url);					
		var comm = Freja._aux.sendXMLHttpRequest(req);
		comm.addCallbacks(
			function(xhr) {
				callback(xhr.responseText, xhr.status, url);
			}, 
			function(xhr) {
				alert("Error " + xhr.status + ": " + url + "\n\n"+ xhr.responseText);
			} );
		return false;
	}
		
	// ---------------------------------------------------------------------------------------------
	// errorHandler
	// ---------------------------------------------------------------------------------------------
	function errorHandler(desc,page,line,chr)  {
		 alert(
			  'Sorry, a JavaScript error occurred! \n'
			 +'\nError description: \t'+desc
			 +'\nPage address:      \t'+page
			 +'\nLine number:       \t'+line
		 )
		 return true
	}
		