Code:
var menuXmlData;
var pageXmlData;
var pageXmlRules;
var xmlFileToEdit;

jQuery(document).ready(function($)
{
	resetPage();
});

function resetPage()
{
	// get our xml file/data
	$.ajax({
		type:'GET',
		async: false,
		url:'../MenuSystem.xml'+'?bc='+Math.floor(Math.random()+9999999),
		success:function(xmlDoc){ menuXmlData = xmlDoc.documentElement; },
		dataType:'xml'
	});
	
	// if there's a GET var telling us which page to edit, edit that page
	// otherwise output a menu of pages to edit
	var editVar = getQueryVar('page');
	if (editVar == '' || editVar == null)
		fillInMenuOfPages();
	else
		startPageEditor(editVar);
}

function getQueryVar(nm)
{
	var results = RegExp('[?|&]'+nm+'=?(.*?)(&|$)').exec(window.location.search);
	return results==null ? null : decodeURIComponent(results[1]);
}

function fillInMenuOfPages()
{
	$('.top-description').text('Choose a page/section below to edit:');
	$('.save-btn').css('display','none');
	var pages = menuXmlData.getElementsByTagName('page'), i, ii = pages.length, nd, isLink, noClick;

	$('#main-editor').append('<div class="page-edit-link"><a href="edit-page-content.php?page=accordion">HOME BANNER</a></div>');

	for (i = 0; i < ii; i++)
	{
		nd = pages[i];
		isLink = nd.getAttribute('isLink');
		noClick = nd.getAttribute('noClick');
		if (isLink == 'true' || noClick == 'true')
			continue;
		
		$('#main-editor').append(
			$('<div class="page-edit-link"><a href="edit-page-content.php?page='+nd.getElementsByTagName('hash')[0].textContent.substr(1)+'">'+
				nd.getElementsByTagName('label')[0].textContent+
			'</a></div>')
		);
	}
	$('#main-editor').append($('<div style="clear:both"></div>'));
	$('.to-top-btn').css('visibility', 'hidden');
	
	$('.to-top-btn').css('visibility', 'visible');
}

var isNoRules = false;
function startPageEditor(editVar)
{
	editVar = '#'+editVar;
	var pages = menuXmlData.getElementsByTagName('page'), i, ii = pages.length, moduleFile;
	var siteUrl = document.URL.substr(0,document.URL.lastIndexOf('/admin')+1);

	//first page, accordion
	var pageHashHtml = '';
	var pageUrlHtml = '';
	//var xmlFileToEdit = 'xml/accordion.xml';
	// moduleFile = 'modules/accordion.swf';
	var noMenu = 'true';

	for (i = 0; i < ii; i++)
	{
		
		if (pages[i].getElementsByTagName('hash')[0].textContent == editVar)
		{
			//xmlFileToEdit = pages[i].getElementsByTagName('xml')[0].textContent;
			moduleFile = pages[i].getElementsByTagName('swf')[0].textContent;
			pageHashHtml = siteUrl+pages[i].getElementsByTagName('hash')[0].textContent;
			pageUrlHtml = siteUrl+pages[i].getElementsByTagName('path')[0].textContent;
			noMenu = 'false';

			if (pageHashHtml == "#fleet" || pageHashHtml == "#fuel" || pageHashHtml == "#service-area" || pageHashHtml == "#automotive" || pageHashHtml == "#home") {
				xmlFileToEdit = 'xml/'+pageHashHtml.replace("#", "")+'.xml';
			} else {
				xmlFileToEdit = pages[i].getElementsByTagName('xml')[0].textContent;
			}
		} else if (editVar == "#accordion") {
			xmlFileToEdit ='xml/accordion.xml';
			moduleFile = 'modules/accordion.swf';
			pageHashHtml = '';
			pageUrlHtml = '';
		}
	}
	
	if (xmlFileToEdit === undefined)
		{ $('.top-description').text("Invalid page specified to edit."); return; }
	
	$.ajax({
		type:'GET',
		async: false,
		url:'../'+xmlFileToEdit+'?bc='+Math.floor(Math.random()+9999999),
		success:function(xmlDoc){ pageXmlData = xmlDoc.documentElement; },
		dataType:'xml'
	});
	
	var slashIndex = moduleFile.lastIndexOf('/');
	var dotIndex = moduleFile.lastIndexOf('.');
	if (dotIndex < 0) dotIndex = moduleFile.length;
	
	// check to see if this page to edit is a SWF scroll modules that load other SWF modules
	if (pageHashHtml == "#fleet" || pageHashHtml == "#fuel" || pageHashHtml == "#service-area" || pageHashHtml == "#automotive" || pageHashHtml == "#home") {
		var rulesFile = 'scripts/xml-editor-rules-'+pageHashHtml.replace("#", "")+'.xml';
	} else {
		var rulesFile = 'scripts/xml-editor-rules-'+moduleFile.substring(slashIndex+1, dotIndex)+'.xml';
	}

	$.ajax({
		type:'GET',
		async: false,
		url:rulesFile+'?bc='+Math.floor(Math.random()+9999999),
		error:function(){ isNoRules = true; },
		success:function(xmlDoc){ pageXmlRules = xmlDoc.documentElement; },
		dataType:'xml'
	});
	
	if (!isNoRules)
	{
		var htmlData = convertXmlToHtml(pageXmlData, 1);
		$('#main-editor').html('<div id="drag-indic"></div>'+htmlData);
		addJavascriptActions();
		
		$(document).unbind('mouseup').bind('mouseup', dragEnd);
		$(document).unbind('mousemove').bind('mousemove', dragHappening);
		
		if (noMenu == 'true') {
			$('#page-info').html('<p class="page-loc">Editing content of page: <a href="../index.php" target="_blank">Home Banner'+rulesFile+'</a></p>');
		} else {
			$('#page-info').html('<p class="page-loc">Editing content of page: <a href="../'+pageUrlHtml+'" target="_blank">'+pageHashHtml+'</a> '+xmlFileToEdit+'</p>');
		}

	}
	else
	{
		var xmlText = '';
		$.ajax({
			type:'GET',
			async: false,
			url:'../'+xmlFileToEdit+'?bc='+Math.floor(Math.random()+9999999),
			success:function(xmlT){ xmlText = xmlT; },
			dataType:'text'
		});
		
		// adding iframe to acceptable tags for html editor
		WYMeditor.XhtmlLexer.prototype.addTokens = function() { this.addEntryPattern("</?iframe", 'Text', 'Text');this.addExitPattern(">", 'Text');this.addCommentTokens('Text');this.addScriptTokens('Text');this.addCssTokens('Text');this.addTagTokens('Text');};
		$('#main-editor').html('<textarea class="wysiwyg-editor">'+xmlText+'</textarea>');
		$('.wysiwyg-editor').wymeditor({
			toolsItems: [
				{'name': 'Bold', 'title':  'Strong', 'css':  'wym_tools_strong'},
				{'name': 'Italic', 'title': 'Emphasis', 'css': 'wym_tools_emphasis'},
				{'name': 'CreateLink', 'title': 'Link', 'css': 'wym_tools_link'},
				{'name': 'Unlink', 'title': 'Unlink', 'css': 'wym_tools_unlink'},
				{'name': 'InsertOrderedList', 'title': 'Ordered_List', 'css': 'wym_tools_ordered_list'},
				{'name': 'InsertUnorderedList', 'title': 'Unordered_List', 'css': 'wym_tools_unordered_list'},
				{'name': 'Paste', 'title': 'Paste_From_Word', 'css': 'wym_tools_paste'},
				{'name': 'Undo', 'title': 'Undo', 'css': 'wym_tools_undo'},
				{'name': 'Redo', 'title': 'Redo', 'css': 'wym_tools_redo'},
				{'name': 'ToggleHtml', 'title': 'HTML', 'css': 'wym_tools_html'}
			]
		});
		$('.wym_containers h2').text('Formatting');
		$('.wym_html_val').keydown(function(e){ // make tab work in html source view
			if (e.keyCode == 9)
				{var myValue = "\t";var startPos = this.selectionStart;var endPos = this.selectionEnd;var scrollTop = this.scrollTop;this.value = this.value.substring(0, startPos) + myValue + this.value.substring(endPos,this.value.length);this.focus();this.selectionStart = startPos + myValue.length;this.selectionEnd = startPos + myValue.length;this.scrollTop = scrollTop;e.preventDefault();}
		});
		$('#main-editor').fadeOut(0).fadeIn(500);
		
		$('#page-info').html('<p class="page-loc">Editing HTML content of page: <a href="../'+pageUrlHtml+'" target="_blank">'+pageUrlHtml+'</a></p>');
		$('#page-info').append($('<p class="page-details">This is a custom swf or blank swf page, so please fill in HTML backup content for mobiles and search engines.</p>'));
	}
	
	$('.to-top-btn').css('visibility', 'visible');
}

function convertXmlToHtml(node, lvl)
{
	//if (isNaN(lvl)) lvl = 1; // now always sends the 1 for first call
	var returnVal = '';
	
	// jquery parsing
	var childNode, childNodeName, isText;
	$(node).children().each(function(){
		childNode = $(this);
		isText = childNode.children().length < 1;
		childNodeName = childNode[0].nodeName;
		
		returnVal += '<div class="node lvl-'+lvl+'"><div class="node-bg"></div><p class="node-label">'+
			childNodeName+
			'</p>'+
				(isText ? '' : '<a class="open-close-btn">open/close</a>') +
			'<span class="node-name">'+
			childNodeName+
			'</span><span class="node-attributes">'+
				getAttributesString(childNode[0]) +
			'</span><span class="node-text">'+
			(isText ? encodeURI(childNode.text()) : '')+
			'</span><span class="editor-rules">'+
			getRulesArray(childNode[0], true).join('')+
			'</span><div class="node-children">'+
				(isText ? '' : convertXmlToHtml(childNode,lvl+1)) +
			'</div></div>';
	});
	
	return returnVal;
}
// in the flash fast parser this is duplicated
function getAttributesString(node)
{
	var returnVal = '';
	var attributes = node.attributes;
	
	if (attributes==undefined || attributes.length==0)
		return '';
	
	var i = 0, ii = attributes.length, attr;
	for (i = 0; i < ii; i++)
	{
		attr = attributes[i];
		returnVal += '<span class="attribute">'+
			'<span class="attribute-name">'+attr.name+'</span>'+
			'<span class="attribute-value">'+attr.value+'</span>'+
		'</span>';
	}
	
	return returnVal;
}
function addJavascriptActions()
{
	$mainEditor = $('#main-editor');
	
	// by default, close all children nodes, start with just the root child nodes showing
	$mainEditor.find('.node-children').css('opacity',0).slideUp(1);
	$mainEditor.find('.open-close-btn').css('opacity', 0.6).bind('click',function(){
		if (!isSlidingNow) // only go if not already sliding something!!!!!
		{
			isSlidingNow = true;
			$(this).toggleClass('open');
			var isOpen = $(this).hasClass('open'), time = 500;
			if (isOpen)
				slideOpen($(this).parent().children('.node-children'));
			else
				slideClose($(this).parent().children('.node-children'));
		}
	}).bind('mouseover', function(){ $(this).css('opacity',1); }).bind('mouseout', function(){ $(this).css('opacity',0.6); });
	
	// open things with the rule to start out opened
	$mainEditor.find('action:contains(begin-open)').each(function(){
		var $par = $(this).parent().parent().parent();
		$par.children('.node-children').css('opacity',1).slideDown(1);
		$par.children('.open-close-btn').addClass('open');
	});
	
	// give custom labels to items with those defined in rules
	$mainEditor.find('rule label').each(function(){
		var $par = $(this).parent().parent().parent();
		$par.children('.node-label').text( $(this).text() );
	});
	
	// give editable input box to nodes with that in rules
	$mainEditor.find('action:contains(show-one-line-editor)').each(function(){
		var $par = $(this).parent().parent().parent();
		var spellcheck = $par.children('.editor-rules').children('rule').children('action:contains(use-spellcheck)').get(0)==undefined ? 'false' : 'true';
		var val = decodeURI($par.children('.node-text').text());
		$input = $('<input class="single-line-xml-editor" type="text" value="'+val+'" placeholder="blank" spellcheck="'+spellcheck+'" />');
		$par.children('.node-label').after($input);
		$input.bind('change', function(){
			$(this).parent().children('.node-text').text( encodeURI($(this).val()) );
			changesNotSaved = true;
		});
	});
	
	// make draggable the items that the rules say should be draggable
	$mainEditor.find('action:contains(allow-dragging)').parent().parent().parent().bind('mousedown', dragStart);
	
	// add in help buttons
	$mainEditor.find('help').each(function(){
		var $par = $(this).parent().parent().parent();
		$par.children('.node-children').before($('<div class="help-btn" style="top:-41px;margin-right:10px;"><p>'+$(this).text()+'</p></div>'));
	});
	
	// add attribute button to nodes needing ability to edit attributes
	$mainEditor.find('action:contains(allow-attribute-editing)').each(function(){
		var $par = $(this).parent().parent().parent();
		var $newElem = $('<p class="node-action-link"><a title="Edit this node\'s attributes." href="javascript:;">attributes</a></p>');
		$par.children('.node-children').before($newElem);
		$newElem.children('a').bind('click', function(){
			var $par = $(this).parent().parent();
			openAttributeEditor( $par.children('.node-attributes') );
		});
	});
	
	// add duplication button to nodes needing ability to duplicate
	$mainEditor.find('action:contains(allow-duplication)').each(function(){
		var $par = $(this).parent().parent().parent();
		var $newElem = $('<p class="node-action-link"><a title="Create and add a copy of this node." href="javascript:;">duplicate</a></p>');
		$par.children('.node-children').before($newElem);
		$newElem.children('a').bind('click', function(){
			var $fake = $('<div style="height:0px;"></div>');
			var $orig  = $(this).parent().parent();
			var $clone = $orig.clone(true,true);
			$orig.before($fake);
			$fake.animate({height:53}, {complete:function(){
				$fake.remove();
				$orig.before($clone);
				$clone.css({top:'50px',opacity:.1}).animate({top:0,opacity:1});
			}});
			changesNotSaved = true;
		});
	});
	
	// add deletion button to nodes needing ability to delete
	$mainEditor.find('action:contains(allow-deletion)').each(function(){
		var $par = $(this).parent().parent().parent();
		var $newElem = $('<p class="node-action-link"><a title="Delete this entire node." href="javascript:;">delete</a></p>');
		$par.children('.node-children').before($newElem);
		$newElem.children('a').bind('click', function(){
			var $orig  = $(this).parent().parent();
			var nodeName = $orig.children('.node-name').text();
			if ($orig.parent().children('.node').children('.node-name:contains('+nodeName+')').length <= 1)
				{ alert("You cannot delete the last node of a set, please edit it to your needs rather than delete it!"); return; }
			var $fake = $('<div style="height:'+($orig.height()+9)+'px;"></div>');
			$orig.fadeOut('normal', function(){
				$orig.before($fake);
				$orig.remove();
				$fake.animate({height:0}, {complete:function(){
					$fake.remove();
				}});
			});
			changesNotSaved = true;
		});
	});
	
	// add ability to select a file from the file manager
	$mainEditor.find('action:contains(allow-file-selection)').each(function(){
		var $par = $(this).parent().parent().parent();
		var $newElem = $('<p class="node-action-link"><a title="Upload or select a file from the file manager." href="javascript:;">upload/select new</a></p>');
		$par.children('.node-children').before($newElem);
		$newElem.children('a').bind('click', function(){
			var $par = $(this).parent().parent();
			var $textNode = $par.children('.node-text');
			openFileManager($textNode.text(), function(newFNm){
				$textNode.text(newFNm);
				$par.children('.single-line-xml-editor').val(newFNm);
			}, true);
		});
	});
	
	// add large text editor button to nodes needing ability to edit larger text content
	$mainEditor.find('action:contains(show-text-editor)').each(function(){
		var $par = $(this).parent().parent().parent();
		var $newElem = $('<p class="node-text-edit-link"><a title="Open the text editor to edit this content." href="javascript:;">edit</a></p>');
		$par.children('.node-children').before($newElem);
		$newElem.children('a').bind('click', function(){
			var $par  = $(this).parent().parent();
			var $textNode = $par.children('.node-text');
			openTextEditor($textNode);
		});
	});
}

function getRulesArray(n, asStr)
{
	// if no rules, give empty array
	if (pageXmlRules == undefined) return [];
	
	// figure out the appropriate path string for this node
	var path = n.nodeName, nodeP = n;
	while(true)
	{
		nodeP = nodeP.parentNode;
		
		if (String(nodeP.parentNode) == '[object Document]' // webkit check for if at root
			|| (nodeP.parentNode && nodeP.parentNode.nodeName == '#document') // ff check for if at root
			|| nodeP == undefined // generic check
		)
			{ path = 'root.'+path; break; }
		path = nodeP.nodeName + '.' + path;
	}
	
	// jquery way
	var rulesArr = [];
	$(pageXmlRules).children('rule[pathMatch="'+path+'"]').each(function(){
		rulesArr.push(asStr ? getXmlString($(this).get(0)) : $(this).get(0));
	});
	
	return rulesArr;
}

function convertHtmlToXml($par, lvl)
{
	if (isNaN(lvl)) lvl = 1;
	var returnVal = '';
	
	var $this, nodeName, txtContent, doCdata, tabStr, childContent;
	$par.children('.node').each(function(){
		$this = $(this);
		nodeName = $this.children('.node-name').text();
		tabStr = tabBy(lvl);
		txtContent = $.trim(decodeURI($this.children('.node-text').text()));
		doCdata = $this.children('.editor-rules').children('rule').children('action:contains(save-cdata)').length > 0;
		if (txtContent != '' && doCdata) txtContent = '<![CDATA[' + txtContent + ']]>';
		childContent = convertHtmlToXml($this.children('.node-children'),lvl+1);
		returnVal += '\n'+tabStr+'<'+nodeName+attributesToString($this)+'>'+
			txtContent +
			childContent +
		(txtContent != '' || $.trim(childContent) == '' ? '' : '\n'+tabStr)+'</'+nodeName+'>';
	});
	
	return returnVal;
}
function attributesToString($node)
{
	var retVal = ''
	var $attr = $node.children('.node-attributes');
	$attr.children('.attribute').each(function(){
		retVal += ' ' + $(this).children('.attribute-name').text() + '="' + $(this).children('.attribute-value').text().split('"').join('&quot;').split('&').join('&amp;') + '"';
	});
	return retVal;
}
function tabBy(n)
{
	var retVal = '';
	var i, ii = n;
	for (i=0; i<ii; i++)
		retVal += '\t';
	return retVal;
}

function saveXml()
{
	var xmlStr = '';
	if (!isNoRules)
	{
		var rootNodeName = pageXmlData.nodeName;
		xmlStr = '<?xml version="1.0" encoding="utf-8"?>\n<'+rootNodeName+'>'+convertHtmlToXml($('#main-editor'))+'\n</'+rootNodeName+'>';
		// xmlStr = vkbeautify.xml(xmlStr); // vkbeautify handles the cdata like crap, gonna have to make it pretty in the convertHtmlToXml function
	}
	else
	{
		var index = $('.wysiwyg-editor').data('wym_index');
		xmlStr = $.wymeditors(index).xhtml();
	}
	
	// clear the page while resaving
	$('#main-editor').html('<div class="page-waiting-busy"></div>');
	$('.to-top-btn').css('visibility', 'hidden');
	
	$.post('scripts/save-page-edit-xml.php', {data:xmlStr, fname:xmlFileToEdit}, function(status)
	{
		if (status == 'auth-failure')
			alert('Your log-in credentials have expired, please refresh the page and log-in again.');
		else if (status != 'success') 
			alert('Save failed. Please check that your file permissions are set to allow writing and that your host allows basic PHP read/write functions.\n\nThe following is a php error messages for debug purposes, ignore it:\n'+status);
		else
			setTimeout(function(){$('.save-btn').removeClass('working');$('.save-indic').fadeIn(150).delay(1200).fadeOut(300);}, 1000);
		
		resetPage();
		changesNotSaved = false;
	},
	'text');
}