function insertBtns()
{
	var i, div, root = document.getElementById( "lxPageDiv" ), s;
	var btnAddManAbove, btnAddHtmlAbove;

	// lxSections has been set with some simple information earlier in initPage
	// has to copy the childNodes first before doing insertBefore, otherwise FF crashes
	for ( i=(mode=="edit0"?1:0); i<lxSections.length; i++ )
		insertBtn(i);
	enableOpBtns();
	
	div = document.createElement( "div" );
	div.style.backgroundColor = "#99ffff";
	root.appendChild( div );
	btnAddManAbove = '<input type="button" class="operationBtn" value="Add Manipulative Above" onclick="addManAbove(null)" />&nbsp;';
	btnAddHtmlAbove = '<input type="button" class="operationBtn" value="Add HTML Above" onclick="addHtmlAbove(null)" />&nbsp;';
	s = '<table cellpadding="0" cellspacing="0" border="0" width="100%"><tr><td style="text-align:left">' 
			+ '</td><td style="text-align:right">' 
			+ btnAddManAbove + btnAddHtmlAbove 
			+ '</td></tr></table>';
	div.className = "opBtnsDiv";
	div.innerHTML = s;
}

function insertBtn( i )
{
	var t, div, root = document.getElementById( "lxPageDiv" ), s;
	var btnEdit, btnMoveUp, btnMoveDown, btnAddManAbove, btnAddHtmlAbove;
	var manName, manId;

	t = lxSections[i];
		
	t.div.style.backgroundColor = "#ffffff";
//	t.div.style.border = "2px solid #99ffff";
	t.div.style.border = "1px solid blue";
	div = document.createElement( "div" );
	div.className = "opBtnsDiv"
	div.style.backgroundColor = "#99ffff";
	root.insertBefore( div, t.div );

	if ( t.isMan )
	{
		manName = t.manName;
		if ( manName == "" )	// for addManAbove
			manId = "";
		else
			manId = lxEditors[t.manName].absId; //ManInfo.arr[lxEditors[t.manName].absId].relId;
                                                // relId is not available yet before the manipulative data is loaded
		btnEdit = '<table cellpadding="0"><tr><td>Address Id:</td><td><input id="' + t.randomId + 'NewAddress" size="25" value="' + manId + '" /></td><td><input type="button" class="operationBtn" value="Set" onclick="changeManId(\'' + t.randomId + '\')" /></td></tr>'
					+ '<tr><td>Name in this page:</td><td><input id="' + t.randomId + 'NewManName" size="25" value="' + manName + '" /></td><td><input type="button" class="operationBtn" value="Set" onclick="changeManName(\'' + t.randomId + '\')" /></td></tr></table>';
		btnDelete = '<input type="button" class="operationBtn" value="Delete" onclick="deleteMan(\'' + t.randomId + '\')" />&nbsp;';
	}
	else
	{
		btnEdit = '<input type="button" class="operationBtn" value="Edit" onclick="editHtml(\'' + t.randomId + '\')" />&nbsp;';
		btnDelete = '<input type="button" class="operationBtn" value="Delete" onclick="deleteHtml(\'' + t.randomId + '\')" />&nbsp;';
	}			
	btnMoveUp = '<input type="button" class="operationBtn" value="Move Up" onclick="moveUp(\'' + t.randomId + '\')" />&nbsp;';
	btnAddManAbove = '<input type="button" class="operationBtn" value="Add Manipulative Above" onclick="addManAbove(\'' + t.randomId + '\')" />&nbsp;';
	btnAddHtmlAbove = '<input type="button" class="operationBtn" value="Add HTML Above" onclick="addHtmlAbove(\'' + t.randomId + '\')" />&nbsp;';
	btnMoveDown = '<input type="button" class="operationBtn" value="Move Down" onclick="moveDown(\'' + t.randomId + '\')" />&nbsp;';
	
	s = '<table cellpadding="0" cellspacing="0" border="0" width="100%"><tr><td style="text-align:left">' 
		+ btnEdit
		+ '</td><td style="vertical-align:bottom;text-align:right">' 
		+ btnDelete + btnAddManAbove + btnAddHtmlAbove + btnMoveUp + btnMoveDown 
		+ '</td></tr></table>';
	div.innerHTML = s;
	var inputs = div.getElementsByTagName( "input" );
	for ( i=0; i<inputs.length; i++ )
	{
		if ( inputs[i].value == "Move Up" )
			t.btnMoveUp = inputs[i];
		if ( inputs[i].value == "Move Down" )
			t.btnMoveDown = inputs[i];
	}
}

function enableOpBtns()
{
	var base = mode=="edit0"?1:0, i;
	if ( lxSections.length <= base )
		return;

	lxSections[base].btnMoveUp.disabled = true;
	for ( i=base+1; i<lxSections.length; i++ )
		lxSections[i].btnMoveUp.disabled = false;
	lxSections[lxSections.length-1].btnMoveDown.disabled = true;
	for ( i=base; i<lxSections.length-1; i++ )
		lxSections[i].btnMoveDown.disabled = false;
}


var grid;

function initLayout()
{
	var reader = new Ext.data.JsonReader( {
				root: 'rows',
			   	fields: [
			   	   {name: 'section'},
			   	   {name: 'itemType'},
			   	   {name: 'valType'},
			   	   {name: 'expression'},
				   {name: 'name',
				   	sortType: function(x){
				   		return x.toLowerCase();
		           }}
		        ]
		      } );	
	var store = new Ext.data.GroupingStore({
				groupField: 'section',
				sortInfo: {field: 'name',direction: 'ASC'},
				reader: reader
				
         	});
		        
	grid = new Ext.grid.GridPanel({
				store: store,
				columns: [		           
				    //{header: "<br/>Section", width: 80, sortable: true, dataIndex: 'section'},
				    {header: "<br/>Name", width: 80, sortable: true, dataIndex: 'name'},
				    {header: "Item<br/>Type", width: 50, sortable: true, dataIndex: 'itemType'},
				    {header: "Value<br/>Type", width: 50, sortable: true, dataIndex: 'valType'},
				    {id: 'expression', header: "<br/>Expression", width: 440, sortable: true, dataIndex: 'expression'}
				],
				sm: new Ext.grid.RowSelectionModel( {singleSelect:true} ),
				stripeRows: true,
				//width:600,
				height:250,
				//autoHeight: true,		// hor scrollbar missing; need the patch
				autoExpandColumn: 'expression'
		    });	
	
	grid.on( 'rowclick', function( grid, idx ) {
			var record = grid.store.getAt(idx),
				name = record.get('name'),
				obj = lxObjects2[name];
				
			objToSet = obj;

			updSettingPanel();
		});
	
	var border = new Ext.Panel( {
		id: 'border-panel',
		height: 800,
		autoWidth: true,
		layout: 'border',
		items:
			[{
				region: 'center',
				split: true,
				layout: 'fit',
				autoScroll:true, 
				contentEl: 'lxPageDiv'
			},
			{
				region: 'east',
				title: 'Definitions',
				split: true,
				minSize: 100,
				maxSize: 1000,
				width: 400,
				collapsible: true,
				layout: 'border',
				items:
					[{
						region: 'north',
						height: 260,
						items: [grid]
					},
					{
						id: 'settingPanel',
						region: 'center',
						title: 'Calculator',
						split: true,
						//collapsible: true,
						contentEl: 'settingDiv'
					}]
			}]	
		} );
		
	border.render( "container" );
}

function updGrid() {	
	var i, j, item, data = {rows:[]}, s;
	//for ( i=0; i<lxSections.length; i++ ) {
	//	s = lxSections[i];
		for ( j=0; j<lxObjects.length; j++ ) {	
			item = lxObjects[j];
//alert(j + " " + item.section + " "+ item.name );
	//		if ( item.section != s )
	//			continue;
				
			if ( item.isUnnamed )
				continue;

			data.rows.push( {
							//section: s.fiedName ? s.fieldName : s.manName,
							name: item.name, 
							itemType: item.getType(), 
							valType: '', 
							expression: item.getExpression() 
						} ); 	
		}
	//}
	
	grid.store.loadData( data );
	
}

var objToSet;


function updSettingPanel() {
	var obj = objToSet, 
		calDiv = document.getElementById("calculatorDiv"),
		scriptDiv = document.getElementById("scriptDiv");
	if ( obj.type == "Button" ) {
		Ext.getCmp('settingPanel').setTitle("Script");
		calDiv.style.visibility = 'hidden';
		scriptDiv.style.display = '';
		updScriptTA( obj );
	}
	else {
		Ext.getCmp('settingPanel').setTitle("Calculator");
		calDiv.style.visibility = 'visible';
		scriptDiv.style.display = 'none';
		updCalculator( obj );	// wantType
	}
}

function updScriptTA( obj ) {
	document.getElementById("scriptTA").value = obj.script.replace(/;/g,";\n");
}
function updScript() {
	var obj = objToSet;
	var v = obj.setScript( document.getElementById("scriptTA").value.replace(/\n/g,"") );
	if ( !v ) {
        alert("Syntax error in script");
    }
}
function updCalculator( refObj, wantType )
{
	var t, op, i, calSel;
		
	calSel = document.getElementById( "values" );
	while ( calSel.length > 1 )
	 	calSel.remove( calSel.length-1 );

	lxgUtil.getAllDescendents( [refObj], 0, 0, true );

	var a = [];
	for ( i=0; i<nLxObjects; i++ )
	{
		t = lxObjects[i];
		if ( t.c == "white" && !t.isUnnamed )
		{
			if ( t.type == "ManField" && !t.existsWhenLoaded )
				continue;

			if ( wantType && t.type != wantType )
				continue;
			
			a.push( t.name );
		}
	}
	
	a.sort();
	for ( i=0; i<a.length; i++ ) {
		t = a[i];
		op = document.createElement( "option" );
		op.value = t;
		op.appendChild( document.createTextNode( t ) );
		calSel.appendChild( op );
	}

	calSel.selectedIndex = 0;
	foo.init( refObj.getExpression(), false );
}
/*
function updCalculator( refObj, wantType )
{
	var i, calSel;
		
	calSel = document.getElementById( "values" );
	while ( calSel.length > 1 )
	 	calSel.remove( calSel.length-1 );

//	if ( refObj )
//	{
		lxgUtil.getAllDescendents( [refObj], 0, 0, true );
//	}
//	else 	
//	{
//		for ( i=0; i<nLxObjects; i++ )
//			lxObjects[i].c = "white";
//	}
	for ( i=0; i<nLxObjects; i++ )
	{
		obj2 = lxObjects[i];
		if ( obj2.canBeTrigger && obj2.c == "white" && !obj2.isUnnamed )
		{
			if ( obj2.type == "ManField" && !obj2.existsWhenLoaded )
				continue;
			
			if ( wantType && obj2.type != wantType )
				continue;

			op = document.createElement( "option" );
			op.value = obj2.name;
			op.appendChild( document.createTextNode( obj2.name ) );
			calSel.appendChild( op );
		}
	}
	
	foo.init( refObj.getExpression(), false );
}
*/
function updExpression()
{
	if ( !foo.valid )
	{
		alert( "Expression is invalid." );
		return;
	}

	var obj = objToSet;
	
	if ( obj.type == "Expr" ) {
		obj.expression = foo.internalExpr;
	}
	else {
		if ( obj.type == "ManField" )
		{
			var t = obj.triggerType;
			if ( lxgEP.result.unit.unitType != t.type ) //|| lxgEP.result.order != t.order )	// not deal with order
			{
				alert( "Expected result type: " + (t.name + (t.order>0?(" of order "+t.order):"")) );
				return false;
			}
			obj.hasExpr = foo.internalExpr && foo.internalExpr != "";
		}
		obj.exprObj.expression = foo.internalExpr;
	}
	lxRefresh();	
}










































var sectionBeingEdited = null, lxOperation = null, lxDialog = null;
function lxOpLock( op )
{
	if ( lxOperation )
	{
		if ( lxOperation == "editHtml" && lxDialog && lxDialog.closed )
		{}
		else
		{
            var t = "Please wait until last operation finishes!";
			alert( t );
			throw t;
		}
	}
	lxOperation = op;
}
function lxOpUnlock()
{
	lxOperation = null;
}
function newMan( randomId )
{
	lxOpLock( "newMan" );
	var newName = document.getElementById( randomId+"NewManName" ).value,
		newId = document.getElementById( randomId+"NewAddress" ).value,
		i;
	
	if ( newName == "" )
	{
		alert( "Please give the manipulative a name for referring in the page!" );
		lxOpUnlock();
		return;
	}
	if ( newId == "" )
	{
		alert( "Please give address id of the manipulative!" );
		lxOpUnlock();
		return;
	}
	if ( lxEditors[newName] || lxObjects2[newName] )
	{
		alert( "Name \"" + newName + "\" has been used!" );
		lxOpUnlock();
		return;
	}
	sectionBeingEdited = findSectionByRandomId( randomId );
	sectionBeingEdited.manName = newName;

	for ( i in ManInfo.arr )
	{
		manInfo = ManInfo.arr[i];
		if ( manInfo.absId == newId || manInfo.relId == newId )
		{
			newMan2( manInfo );
			return;
		}
	}

	ManInfo.requestManData( [newId], 		// can be relative id
							function( ids ) {		// return absolute id
								if ( ids.length == 0 ) {
									lxOpUnlock();
									return;
								}
								var manInfo = ManInfo.getManInfo(ids[0]);
								if ( manInfo.data )
									newMan2( manInfo );
								else
									lxOpUnlock();
						} );
}

function newManReqHandler()
{	
	if ( request.readyState == XMLHTTPREQUEST_READY_STATE_COMPLETED )
  	{
		try
  		{
    		var t, res= request.responseText, manInfo;
    		t = eval( "("+res+")" );
   			var manInfo = ManInfo.arr[t.absId];
    		if ( !manInfo )
    		{
    			manInfo = new ManInfo();
    			ManInfo.arr[manInfo.absId]= manInfo;
    		}
			manInfo.absId = t.absId;
			manInfo.relId = t.relId;
			manInfo.author = t.author;
    		manInfo.data = t.data;
			newMan2( manInfo );
  		}
  		catch (e)
  		{
 			//alert(e.message)
			lxOpUnlock();
  		}
  	}	
}
function newMan2( manInfo )
{
	var lxEditor = { 'loaded': true, 'ids': null, 'idsListened': [], 'absId': manInfo.absId, 
						'section': sectionBeingEdited, 'instanceName': sectionBeingEdited.randomId+'Instance' };
	lxEditors[sectionBeingEdited.manName] = lxEditor;
	var div, editor;
	
	div = document.getElementById( lxEditor.instanceName );
	manInfo.containers.push( div );
	manInfo.containerIds.push( div.id );
	
	if ( !manInfo.data.tool )
		manInfo.data.tool = "GeometryEditor";
	
	lxEM.loadConstructor( manInfo.data.tool, function(toolName) {
				var cname = toolName.split(".").pop();
				var em = new window[cname]( {instanceName: lxEditor.instanceName} );

				lxEditor.editor = em; // closure
				em.create( { renderTo: lxEditor.instanceName,
						dom: true,
						callback: GeometryEditor_OnCreateDone,
						data: manInfo.data
				} );
				document.getElementById( sectionBeingEdited.randomId+"manName" ).firstChild.nodeValue = sectionBeingEdited.manName;
//				updateManInfo( manInfo, lxEditor.section.randomId );
				sectionBeingEdited.toSave = true;
			}
		);
}
function addManAbove( randomId )
{
	lxOpLock( "addManAbove" );
	var i, j, div = document.createElement( "div" ), root = document.getElementById( "lxPageDiv" ), sec, len;
	div.className = "lxSection";

	for ( i=0; i<lxSections.length; i++ )
		if ( lxSections[i].randomId == randomId )
			break;
	if ( i == lxSections.length )
		root.insertBefore( div, root.lastChild );
	else
		root.insertBefore( div, lxSections[i].div.previousSibling );
	len = lxSections.length;
	for ( j=len; j>i; j-- )
		lxSections[j] = lxSections[j-1];
	sec = { "isMan": true, "manName": "", "div": div, "randomId": lxRandomString(), "toSave": false };
	lxSections[i] = sec;
	
	var tblSpan, lxEditor;
	tblSpan = document.createElement( "span" );
	div.appendChild( tblSpan );
	tblSpan.innerHTML = createManHTML( sec.randomId, "name" );	// manName not available yet
	
	insertBtn(i);	
	enableOpBtns();
	lxOpUnlock();
}
function deleteMan( randomId )
{
	lxOpLock( "deleteMan" );
try{
	var i, j, objs={}, obj, root = document.getElementById( "lxPageDiv" );

	sectionBeingEdited = findSectionByRandomId( randomId );
	
	root.removeChild( sectionBeingEdited.div.previousSibling );
	root.removeChild( sectionBeingEdited.div );

	for ( i=0; i<lxSections.length; i++ )
		if ( lxSections[i] == sectionBeingEdited )
		{
			for ( j=i; j<lxSections.length-1; j++ )
				lxSections[j] = lxSections[j+1];
			lxSections.pop();
			break;
		}
	enableOpBtns();

	if ( !sectionBeingEdited.toSave )
	{
		lxOpUnlock();
		return;
	}

	for ( i=0; i<nLxObjects; )
    {
    	obj = lxObjects[i];
    	if ( obj.section == sectionBeingEdited )
    	{
    		obj.destroy();
			lxDeregister( obj );
		}
		else
			i++;
	}

	// update lxEditors before init of ManField	
	lxEditors[sectionBeingEdited.manName] = null;
	delete lxEditors[sectionBeingEdited.manName];

	lxRefresh();
	
}catch(e)
{pageError(e,"deleteMan()");}
	lxOpUnlock();
}

function changeManId( randomId )
{
	lxOpLock( "changeManId" );
try{
	var i, newId, manInfo;
	sectionBeingEdited = findSectionByRandomId( randomId );

	if ( !sectionBeingEdited.toSave )
	{
		lxOpUnlock();
		return newMan( randomId );
	}

	manInfo = ManInfo.arr[lxEditors[sectionBeingEdited.manName].absId];

	newId = document.getElementById( randomId + "NewAddress" ).value;

	if ( newId == "" )
	{
		lxOpUnlock();
		return;
	}
	if ( manInfo && (newId == manInfo.absId || newId == manInfo.relId) )
	{
		lxOpUnlock();
		return;
	}
	for ( i in ManInfo.arr )
	{
		manInfo = ManInfo.arr[i];
		if ( manInfo.absId == newId || manInfo.relId == newId )
		{
			replaceMan( manInfo );
			return;
		}
	}
	ManInfo.requestManData( [newId], function( ids ) {		// return absolute id
								if ( ids.length == 0 ) {
									lxOpUnlock();
									return;
								}
								var manInfo = ManInfo.getManInfo(ids[0]);
								if ( manInfo.data )
									replaceMan( manInfo );
								else
									lxOpUnlock();
						} );
}catch(e)
{pageError(e,"changeManId()");}
}

function replaceManReqHandler()
{
	if ( request.readyState == XMLHTTPREQUEST_READY_STATE_COMPLETED )
  	{
		try
  		{
    		var t, res= request.responseText, manInfo;
    		t = eval( "("+res+")" );
    		var manInfo = ManInfo.arr[t.absId];
    		if ( !manInfo )
    		{
    			manInfo = new ManInfo();
    			ManInfo.arr[manInfo.absId]= manInfo;
    		}
			manInfo.absId = t.absId;
			manInfo.relId = t.relId;
			manInfo.author = t.author;
    		manInfo.data = t.data;
			replaceMan( manInfo );
  		}
  		catch (e)
  		{
 			//alert(e.message)
			lxOpUnlock();
  		}
  	}
}
function replaceMan( manInfo )
{
	var lxEditor = lxEditors[sectionBeingEdited.manName], em = lxEM.ems[lxEditor.instanceName];
	// update absId
	lxEditor.absId = manInfo.absId;

	em.update( {data: manInfo.data, callback: GeometryEditor_OnUpdateDone } );
//	updateManInfo( manInfo, lxEditor.section.randomId );
}
function GeometryEditor_OnFFReloadDone( editorInstance )
{
	var flag=true, i
	for ( i in lxEditors )
	{
		if ( lxEditors[i].instanceName == editorInstance.instanceName )
			lxEditors[i].loaded = true;
		else if ( !lxEditors[i].loaded )
			flag = false;
	}
	if ( !flag )
		return;
	for ( i in lxEditors )
		lxEditors[i].loaded = false;		// reset to reuse them for FFReload
	lxRefresh();
};
function GeometryEditor_OnUpdateDone( editorInstance )
{
try{
	var lxEditor = lxEditors[sectionBeingEdited.manName];
	var editor = lxEditor.editor;

	for ( i=0; i<nLxObjects; i++ )
    {
    	obj = lxObjects[i];
    	if ( obj.section == sectionBeingEdited )
    	{
    		obj.destroy();
			lxDeregister( obj );
/*
			for ( j=0; j<obj.nC; j++ )
			{
// seems no need: init will remove all parents
//				obj.cs[j].removeAllParents();
				obj.cs[j].valid = false;
			}
*/
		}
	}
	
	var i, j, obj, name;
	
	// update ids for replacing a man
	lxEditor.ids = editor.getIds();

	// create all ManField
	for ( j in lxEditor.ids )
	{
		name = sectionBeingEdited.manName+"{"+j+"}";
		obj = new lxManField( name );
		obj.settable = lxEditor.ids[j];
		lxRegister( obj );
		obj.initByData();
		obj.section = sectionBeingEdited;
//		obj.valid = false;
	}
//alert("mm " + obj.hasExpr)	
	lxRefresh( true );	//set_mcs
}catch(e)
{pageError(e,"GeometryEditor_OnUpdateDone()");}
	lxOpUnlock();
}
	
function changeManName( randomId )
{
	lxOpLock( "changeManName" );
try{
	// need to change lxEditors[manName] and ManFields	
	var i, j, objs={}, obj, arr = [], editor, newName;
	sectionBeingEdited = findSectionByRandomId( randomId );
	newName = document.getElementById( randomId + "NewManName" ).value;
	// check duplicate name
	
	if ( !sectionBeingEdited.toSave )
	{
		lxOpUnlock();
		return newMan( randomId );
	}
	
	editor = lxEditors[sectionBeingEdited.manName];

	if ( newName == "" || newName == sectionBeingEdited.manName )
	{
		lxOpUnlock();
		return;
	}
	// if a manipulative takes a name in the dummies, then no expression can take that name
	// it's up to the author to fix it
	if ( lxEditors[newName] || lxObjects2[newName] )
	{
		alert( "Name \"" + newName + "\" has been used!" );
		lxOpUnlock();
		return;
	}
	for ( i=0; i<nLxObjects; i++ )
    {
    	obj = lxObjects[i];
    	if ( obj.section == sectionBeingEdited )
    		arr.push( obj );
    }
    for ( i=0; i<arr.length; i++ );
   	{
   		obj = arr[i];
		lxDeregister( obj );
		obj.manName = newName;
		obj.name = newName+"{"+obj.fieldName+"}";
		lxRegister( obj );
	}

	// need to update lxEditors before init of ManField	
	lxEditors[sectionBeingEdited.manName] = null;
	delete lxEditors[sectionBeingEdited.manName];
	lxEditors[newName] = editor;
	sectionBeingEdited.manName = newName;
	document.getElementById( randomId + "manName" ).firstChild.nodeValue = newName;

	if ( arr.length>0 )
		lxRefresh();	// no need to set_mcs because mcs/mps points to objects instead of names
}catch(e)
{pageError(e,"changeManName()");}
	lxOpUnlock();
}
function addHtmlAbove( randomId )
{
	lxOpLock( "addHtmlAbove" );
	var i, j, div = document.createElement( "div" ), root = document.getElementById( "lxPageDiv" ), sec, len;
	div.className = "lxSection";
	div.appendChild( document.createTextNode( "Sample text here" ) );	

	for ( i=0; i<lxSections.length; i++ )
		if ( lxSections[i].randomId == randomId )
			break;
	if ( i == lxSections.length )
		root.insertBefore( div, root.lastChild );
	else
		root.insertBefore( div, lxSections[i].div.previousSibling );
	len = lxSections.length;
	for ( j=len; j>i; j-- )
		lxSections[j] = lxSections[j-1];
	sec = { "isMan": false, "manName": null, "div": div, "randomId": lxRandomString(), "toSave": true };
	lxSections[i] = sec;

	insertBtn(i);
	enableOpBtns();
	lxOpUnlock();
}
function moveUp( randomId )
{
	lxOpLock( "moveUp" );
	var i, j, inputs, sec, prevSec, opDiv, root = document.getElementById( "lxPageDiv" ), prevOpDiv;
	for ( i=0; i<lxSections.length; i++ )
		if ( lxSections[i].randomId == randomId )
			break;
	if ( i == 0 || i == lxSections.length )
	{
		lxOpUnlock();
		return;
	}
	sec = lxSections[i];
	opDiv = sec.div.previousSibling;
	prevSec = lxSections[i-1];
	prevOpDiv = prevSec.div.previousSibling;
	
	root.insertBefore( root.removeChild( opDiv ), prevOpDiv );
	root.insertBefore( root.removeChild( sec.div ), prevOpDiv );

	lxSections[i-1] = sec;
	lxSections[i] = prevSec;
	enableOpBtns();
	lxOpUnlock();
}
function moveDown( randomId )
{
	lxOpLock( "moveDown" );
	var i, j, inputs, sec, prevSec, opDiv, root = document.getElementById( "lxPageDiv" ), prevOpDiv;
	for ( i=0; i<lxSections.length; i++ )
		if ( lxSections[i].randomId == randomId )
			break;
	if ( i >= lxSections.length-1 )
	{
		lxOpUnlock();
		return;
	}
	sec = lxSections[i+1];
	opDiv = sec.div.previousSibling;
	prevSec = lxSections[i];		// the selected section
	prevOpDiv = prevSec.div.previousSibling;
	
	root.insertBefore( root.removeChild( opDiv ), prevOpDiv );
	root.insertBefore( root.removeChild( sec.div ), prevOpDiv );

	lxSections[i+1] = prevSec;
	lxSections[i] = sec;
	enableOpBtns();
	lxOpUnlock();
}
function editHtml( randomId )
{
	lxOpLock( "editHtml" );
	sectionBeingEdited = findSectionByRandomId( randomId );
	lxDialog = window.open( "dialog/edithtml.html", "", "modal, resizable, scrollbars, top=100, left=100, width=700, height=540" );	
	if ( window.addEventListener )
	{
		window.addEventListener( 'mousedown', lxCheckFocus, true ) ;
		window.addEventListener( 'mouseup', lxCheckFocus, true ) ;
		window.addEventListener( 'click', lxCheckFocus, true ) ;
		//window.addEventListener( 'focus', lxCheckFocus, true ) ;
	}
	else
	{
		window.document.attachEvent( "onmousedown", lxCheckFocus );
		window.document.attachEvent( "onmouseup", lxCheckFocus );
		window.document.attachEvent( "onclick", lxCheckFocus );
		//window.attachEvent( "onfocus", lxCheckFocus );
	}
}
function lxCheckFocus()
{
	if ( lxDialog && !lxDialog.closed )
		lxDialog.focus();
	else
	{
		if ( window.removeEventListener )
		{
			window.removeEventListener( 'mousedown', lxCheckFocus, true ) ;
			window.removeEventListener( 'mouseup', lxCheckFocus, true ) ;
			window.removeEventListener( 'click', lxCheckFocus, true ) ;
			//window.removeEventListener( 'focus', lxCheckFocus, true ) ;	
		}
		else
		{
			window.document.detachEvent( "onmousedown", lxCheckFocus );
			window.document.detachEvent( "onmouseup", lxCheckFocus );
			window.document.detachEvent( "onclick", lxCheckFocus );
			//window.detachEvent( "onfocus", lxCheckFocus );
		}
	}		
}
function deleteHtml( randomId )
{
	lxOpLock( "deleteHtml" );
	var i, objs={}, obj, flag=false, root;
	sectionBeingEdited = findSectionByRandomId( randomId );
 	for ( i=0; i<nLxObjects; )
    {
    	obj = lxObjects[i];
//alert( obj.name + " " + (obj.section == sectionBeingEdited) );
    	if ( obj.section == sectionBeingEdited )
    	{
    		flag = true;
			obj.destroy();
			lxDeregister( obj );
  		}
  		else
			i++;
    }
    if ( flag )
		lxRefresh();

	for ( i=0; i<lxSections.length; i++ )
		if ( sectionBeingEdited == lxSections[i] )
		{
			for ( j=i; j<lxSections.length-1; j++ )
				lxSections[j] = lxSections[j+1];
			lxSections.pop();
			break;
		}
	root = document.getElementById( "lxPageDiv" );
	root.removeChild( sectionBeingEdited.div.previousSibling );
	root.removeChild( sectionBeingEdited.div );
	enableOpBtns();
	lxOpUnlock();
}
function setXHTML( xhtml )
{
	if ( xhtml == null )
	{
		lxOpUnlock();
		return;
	}
try{
	var i, objs={}, obj, root, spans, inputs, els={}, el, flag;
	for ( i=0; i<nLxObjects; i++ )
    {
    	obj = lxObjects[i];
    	if ( obj.section == sectionBeingEdited )
    		objs[obj.name] = obj;
    }
    sectionBeingEdited.toSave = true;
    root = sectionBeingEdited.div;
    root.innerHTML = xhtml;
    spans = root.getElementsByTagName( "span" );
	inputs = root.getElementsByTagName( "input" );
	for ( i=0; i<spans.length; i++ )
	{
		el = spans[i];
//alert( el.firstChild.nodeValue );
		if ( el.className.substr(0,2) == "lx" )
			els[el.title] = el;
	}
	for ( i=0; i<inputs.length; i++ )
	{
		el = inputs[i];
		if ( el.className.substr(0,2) == "lx" )
			els[el.title] = el;
	}
	
	flag = false;
	for ( i in objs )
	{
		obj = objs[i];
		if ( els[i] && ("lx"+obj.type == els[i].className) )
		{
			obj.el = els[i];
			// work around to remove yellow
//			if ( obj.type == "HtmlField" )
//				obj.el.style.backgroundColor = "#ffffff";
			els[i] = null;
		}
		else
		{
			flag = true;
			obj.destroy();
			lxDeregister( obj );
		}
	}
	for ( i in els )
	{
		el = els[i];
		if ( el )
		{
			flag = true;
			obj = eval( "new " + el.className + "('" + el.title + "')" );
			obj.section = sectionBeingEdited;
			lxRegister( obj );
			obj.initByData();
			obj.el = el;
			//obj.valid = false;
		}
	}
	lxRefresh();
}catch(e)
{pageError(e,"setXHTML()");}
	lxOpUnlock();
}




function lxAskName( msg, name, refObj )
{
	var newName, t; // = prompt( msg, name );
	t = name;
	while ( true )
	{
		newName = prompt( msg, t );
		if ( newName == ""  )
		{}
		else if ( !newName || newName == name )
			return null;
		else if ( lxObjects2[newName] || lxEditors[newName] )
			alert( "Name \"" + newName + "\" has been used." );
		else if ( !isNameLegal( newName ) )
		{}
		else if ( dummies[newName] )
		{
			if ( dummies[newName].isAction && !refObj.isAction )
				alert( "The new name has been reserved for a manipulative field or a Html field or an action" );
			else if ( dummies[newName].canBeTrigger && !refObj.canBeTrigger )
				alert( "The new name has been reserved for a manipulative field or a Html field or an expression" );
			else
				break;
		}
		else
			break;
		t = newName;
	}
	return newName;
}


function addExpr()
{
	var newName, obj;

	newName = lxAskName( "Please enter the name for the new expression", "", { "isAction":false, "canBeTrigger":true } );

	if ( newName == null )
		return;

	obj = new lxExpr( newName );
	lxRegister( obj );

	obj.expression = "";
	this.selectedName = newName;

	lxRefresh();
}


 
 
 
 
 
