/*
 *
 * Ephox EditLive! Express Edit Javascript Library
 * Copyright (c) 1999-2007 Ephox Corp. All rights reserved.
 * This software is provided "AS IS," without a warranty of any kind.
 *
 */
 
var ephox_cookieChecked = false;
var ephox_overwriteExpressEdit = false;
var isFlashSupported = false;
var flashCallbackOccured = false;



// process for detecting if flash cookies can be used (requires Flash v6 or greater).
EditLiveCommonStatic_detectBrowser();

if (navigator.mimeTypes && navigator.mimeTypes["application/x-shockwave-flash"]) {
	var flashPluginRef = navigator.plugins["Shockwave Flash"];
	
	if (flashPluginRef) {
		var words = navigator.plugins["Shockwave Flash"].description;
		var flashVer = words.charAt(words.indexOf('.') - 1);
		isFlashSupported = flashVer >= 6;	
	} else {
		isFlashSupported = false;
	}
} else if (IsWindows && IsMSIE) {
	var VBFlashDetect = '<SCR' + 'IPT LANGUAGE=VBScript\> \n';
	VBFlashDetect += 'on error resume next \n';
	VBFlashDetect += 'isFlashSupported = (IsObject(CreateObject("ShockwaveFlash.ShockwaveFlash." & 6)))\n';
	VBFlashDetect += '</SCR' + 'IPT\> \n';
	
	writeToDocument(VBFlashDetect);
}

var currentWindowOnload = window.onload;
window.onload = function() {
	// iterate through each form in the document
	for (formsIndex = 0; formsIndex < document.forms.length; formsIndex++){
		
		// overwriting onsubmit routine
		var myForm = document.forms[formsIndex];		
		myForm.originalonsubmit = myForm.onsubmit;
		
		myForm.onsubmit = function() {
			setFCKEditorsToReturnFragments();
		
			if (this.originalonsubmit) {
				return this.originalonsubmit.apply(this);
			}
		}
	}

	if (currentWindowOnload) {
		currentWindowOnload.apply(window);
	}
};


var ephox_fckEditorInstances = new Array();

function FCKeditor_OnComplete(editorInstance) {
	var myForm = editorInstance.LinkedField.form;	
	ephox_fckEditorInstances[ephox_fckEditorInstances.length] = editorInstance;
	
	for(var i = 0; i < ephox_expressEditorInstances.length; i++) {		
		var elj = ephox_expressEditorInstances[i];
		if (elj.name == editorInstance.Name) {
			var callback = elj.getParam("setPreload");	
			if (callback != "") {
				setTimeout(callback + "()", 5);
			}
		}
	}
}

function setFCKEditorsToReturnFragments() {
	for(var i = 0; i < ephox_fckEditorInstances.length; i++) {
		var fckEditor = ephox_fckEditorInstances[i];
		if (fckEditor != undefined) {
			fckEditor.Config["FullPage"] = false;
		}
	}
}

// Toolbar items supported in Express Edit
var expressToolbarMap = new Array();
expressToolbarMap["cut"] = "Cut";
expressToolbarMap["copy"] = "Copy";
expressToolbarMap["paste"] = "Paste";
expressToolbarMap["face"] = "FontName";
expressToolbarMap["style"] = "FontFormat";
expressToolbarMap["size"] = "FontSize";
expressToolbarMap["bold"] = "Bold";
expressToolbarMap["italic"] = "Italic";
expressToolbarMap["underline"] = "Underline";
expressToolbarMap["find"] = "Find";
expressToolbarMap["undo"] = "Undo";
expressToolbarMap["redo"] = "Redo";
expressToolbarMap["orderedlist"] = "OrderedList";
expressToolbarMap["unorderedlist"] = "UnorderedList";
expressToolbarMap["alignleft"] = "JustifyLeft";
expressToolbarMap["alignright"] = "JustifyRight";
expressToolbarMap["aligncenter"] = "JustifyCenter";
expressToolbarMap["hlink"] = "Link";
expressToolbarMap["imageserver"] = "Image";
expressToolbarMap["increaseindent"] = "Indent";
expressToolbarMap["decreaseindent"] = "Outdent";
expressToolbarMap["highlightcolor"] = "BGColor";
expressToolbarMap["color"] = "TextColor";

expressToolbarMap["instablewizard"] = "Table";
expressToolbarMap["instable"] = "Table";

// Toolbar items supported in EditLive! only
expressToolbarMap["print"] = "EphoxPrint";
expressToolbarMap["new"] = "EphoxNew";
expressToolbarMap["open"] = "EphoxOpen";
expressToolbarMap["save"] = "EphoxSave";
expressToolbarMap["paragraphmarker"] = "EphoxParagraphMarker";
expressToolbarMap["popout"] = "EphoxPopout";
expressToolbarMap["hrule"] = "EphoxHRule";
expressToolbarMap["symbol"] = "EphoxSymbol";
expressToolbarMap["bookmark"] = "EphoxBookmark";
expressToolbarMap["insertcomment"] = "EphoxInsertComment";
expressToolbarMap["datetime"] = "EphoxDateTime";
expressToolbarMap["strike"] = "EphoxStrike";
expressToolbarMap["formatpainter"] = "EphoxFormatPainter";
expressToolbarMap["removeformatting"] = "EphoxRemoveFormatting";
expressToolbarMap["spelling"] = "EphoxSpelling";
expressToolbarMap["backgroundspellchecking"] = "EphoxBackgroundSpellChecking";
expressToolbarMap["wordcount"] = "EphoxWordCount";
expressToolbarMap["accessibility"] = "EphoxAccessibility";
expressToolbarMap["gridlines"] = "EphoxGridlines";
expressToolbarMap["showhelp"] = "EphoxShowHelp";
expressToolbarMap["eljaboutelj"] = "EphoxAboutELJ";
expressToolbarMap["enabletrackchanges"] = "EphoxEnableTrackChanges";
expressToolbarMap["enablechangerendering"] = "EphoxEnableChangeRendering";
expressToolbarMap["acceptchange"] = "EphoxAcceptChange";
expressToolbarMap["rejectchange"] = "EphoxRejectChange";
expressToolbarMap["nextchange"] = "EphoxNextChange";
expressToolbarMap["previouschange"] = "EphoxPreviousChange";
expressToolbarMap["removehyperlink"] = "EphoxRemoveHyperlink";
expressToolbarMap["insertequation"] = "EphoxInsertEquation";
expressToolbarMap["superscript"] = "EphoxSuperscript";
expressToolbarMap["subscript"] = "EphoxSubscript";

//functions

function ephoxExpressEdit_DoFSCommand(command, args) {
	if (command == "read") {
		if (args == "true") {
			// for any instances of EditLive! that have not yet been defined,
			// ensure they will always appear as EditLive! and not the javascript editor
			ephox_overwriteExpressEdit = true;
		}
		
		// set flag for other thread running to detect if the callback has occured
		// and ephox_overwriteExpressEdit has not been set to true
		flashCallbackOccured = true;
		
		for(var i = 0; i < ephox_expressEditorInstances.length; i++) {		
			var elj = ephox_expressEditorInstances[i];
			replaceExistingDivWithEditor(elj);
		}
	}
}

function replaceExistingDivWithEditor(eljInstance) {
	if (eljInstance.expressEdit == "always") {	
		return;
	}

	var newHTML = eljInstance.getExpressEditHTML();
	var newDiv = document.createElement("div");
	newDiv.innerHTML = newHTML;

	var jsEditorDiv = document.getElementById(eljInstance.name + "_expressEditDiv");
	replaceNode(jsEditorDiv, newDiv);
			
	//bit of a hack, might fix later
	hiddenName = eljInstance.name;
	EditLiveCommonStatic_getOnSubmit();
}

ephox_expressEditorInstances = new Array();
EditLiveJava.prototype.expressEdit = false;

EditLiveJava.prototype.setExpressEdit = function(expressEditOption) {
	if (IsMac || window.location.toString().indexOf("file:/") > -1) {
		this.expressEdit = false;
		return;
	}

	reassignMethods(this);

	expressEditOption = expressEditOption.toString().toLowerCase();
	this.expressEdit = expressEditOption;

	if (expressEditOption == "true") {
		this.setAutoSubmit(false);
		// if the cookie has returned that all express edit instances are to become EditLive!,
		// instantly set expressEdit to false to implement.
		if (ephox_overwriteExpressEdit) {		
			this.expressEdit = false;
		} else {
			ephoxQuickStart(this.downloadDirectory);
			
			// ensure check for cookie only occurs once
			if (!ephox_cookieChecked) {
				var cookieResult = getCookieForUsingEditLive(this.downloadDirectory);

				// javascript cookie returned true, replace javascript editors with EditLive!s
				if(cookieResult) {
					ephox_overwriteExpressEdit = true;	
					this.expressEdit = false;
				}
				
				ephox_cookieChecked = true;
			}
		}
	}
}

EditLiveJava.prototype.loadExpressEditor = function() {
	
	
	if (ephox_overwriteExpressEdit && this.expressEdit != "always") {
		this.expressEdit = false;
		return false;
	}
	
	ephox_expressEditorInstances[ephox_expressEditorInstances.length] = this;
	if (this.expressEdit == "always") {
		writeToDocument(this.getExpressEditHTML());
		return true;
	}
	
	if (isFlashSupported) {
		writeToDocument("<div style='border: 1px solid; width:" + this.width + "; height:" + this.height + "' id='" + this.name + "_expressEditDiv'>Please wait, reading editor preference...</div>");
	} else {
		writeToDocument(this.getExpressEditHTML());
	}
	
	// flash callback has been hit before this method can finish.
	if(!ephox_overwriteExpressEdit && flashCallbackOccured) {
		replaceExistingDivWithEditor(this);
		
		this.started = true;
	}	
	
	return true;
}

EditLiveJava.prototype.getExpressEditHTML = function() {
	if (ephox_overwriteExpressEdit && this.expressEdit != "always") {
		this.started = true;
		
		// create hidden form field for EditLive!. We create the hidden form field here
		// instead of EditLiveCommon_show, otherwise FCKEditor instances will attempt to append
		// their content to this field instead of overwriting the field.
		return this.getHiddenFieldString() + this.getAppletHTML(true);
	}
	
	this.parseConfig();	
	var completeStyles = this.getCompleteStyles();	
	var styleString="";
	if (completeStyles!=""){
	    styleString = "<style type=\"text/css\">"+ completeStyles + "</style>";
	}
	
	var editorHTML = "";
	var editorBody = this.getParam("Body");	
	var document = this.getParam("Document");
	
	if (editorBody != "") {
		editorBody = decodeHTMLContent(editorBody);
		editorBody = "<html><head>" + styleString + "</head><body>" + editorBody + "</body></html>";
	} else if (document != "") {
		editorBody = decodeHTMLContent(document);
		
		if (styleString != "") {				
			// parse document, looking for pre-specified styles
			var styleInsertionPoint = editorBody.indexOf("</head>");
			
			if (styleInsertionPoint < 0) {
				styleInsertionPoint = editorBody.indexOf("<body");
			
				// no head element exists, need to create one
				styleString = "<head>" + styleString + "</head>";				
			}
			
			var preStylesContent = editorBody.substring(0, styleInsertionPoint);
			var postStylesContent = editorBody.substring(styleInsertionPoint, editorBody.length);
			
			editorBody = preStylesContent + styleString + postStylesContent;				
		}		
	} else {
		editorBody = "<html><head>" + styleString + "</head><body></body></html>";
	}

	var oFCKeditor = new FCKeditor(this.name);
	oFCKeditor.BasePath = this.downloadDirectory + "expressEdit/fckeditor/";
	oFCKeditor.Width = this.width;
	oFCKeditor.Height = this.height;
	oFCKeditor.Value = editorBody;
	oFCKeditor.ToolbarSet = 'ephoxToolbar';
	oFCKeditor.Config["FullPage"] = true;	
	
	editorHTML = oFCKeditor.CreateHtml();
	editorHTML = "<div id='" + this.name + "_fckDiv'>" + editorHTML + "</div>";
	
	this.expressEditor = oFCKeditor;

	return editorHTML;
}

EditLiveJava.prototype.getCompleteStyles = function() {
	var editorDocument = this.getParam("Document");
	var documentLinkedStlyes = "";
	var documentEmbeddedStyles = "";
	
	if(editorDocument != "") {
		documentLinkedStlyes = this.parseLinkElements(decodeHTMLContent(editorDocument));	
		documentEmbeddedStyles = this.parseEmbeddedStyles(decodeHTMLContent(editorDocument));
	}

	var parsedEmbeddedStyles = "";
	if (this.parsedEmbeddedStyles != "") {
		parsedEmbeddedStyles = this.parsedEmbeddedStyles;
	} else if (documentEmbeddedStyles != "") {
		parsedEmbeddedStyles = documentEmbeddedStyles;
	} else {
		parsedEmbeddedStyles = decodeHTMLContent(this.getParam("Styles"));
	}
	
	return documentLinkedStlyes + this.parsedLinkStyles + parsedEmbeddedStyles;
}

EditLiveJava.prototype.parseConfig = function() {
	// parse EditLive! config file to define FCKEditor properties
	var xml = decodeHTMLContent(this.getParam("setXML"));
	
	xml = this.removeComments(xml);

	this.parseTabs(xml);
	this.parseComboBoxes(xml);
	this.parseToolbars(xml);
	this.parsedLinkStyles = this.parseLinkElements(xml);	
	this.parsedEmbeddedStyles = this.parseEmbeddedStyles(xml);
}

EditLiveJava.prototype.removeComments = function(xml) {
	var startIndex = xml.indexOf("<!--");
	var endIndex = xml.indexOf("-->");
	
	while (startIndex > -1 && endIndex > -1) {
		var firstXml = xml.substring(0, startIndex);
		var secondXml = xml.substring(endIndex + 3); 
		xml = firstXml + secondXml;

		var startIndex = xml.indexOf("<!--");
		var endIndex = xml.indexOf("-->");		
	}
	
	return xml;
}

EditLiveJava.prototype.parseTabs = function(xml) {
	var regex = new RegExp("<wysiwygEditor[^>]*tabPlacement[ ]*=[ ]*[\"']([^\"']*)[\"']", "gim");
	var match = regex.exec(xml);
	if (match) {
		this.tabPlacement = match[1];
	} else {
		this.tabPlacement = "";
	}
}

EditLiveJava.prototype.parseComboBoxes = function(xml) {
	var start = 0;
	var end = 0;
	while(start > -1) {
		start = xml.indexOf("<toolbarComboBox", end);
		end = xml.indexOf("</toolbarComboBox>", start);

		if (start > -1) {
			var combo = xml.substring(start, end);
			var regex = new RegExp("<comboBoxItem[^>]*name[ ]*=[ ]*[\"']([^\"']*)[\"'][^>]*>", "gim");
	
			if (combo.toLowerCase().indexOf("size") > -1) {
				this.parseSizeComboBox(combo, regex);
			} else if (combo.toLowerCase().indexOf("face") > -1) {
				this.parseFaceComboBox(combo, regex);
			} else if (combo.toLowerCase().indexOf("style") > -1) {
				this.parseStyleComboBox(combo, regex);
			}
		}	
	}
}

EditLiveJava.prototype.parseSizeComboBox = function(combo, regex) {
	var match = regex.exec(combo);
	var sizeList = "";
	while(match) {
		if (!isNaN(match[1])) {
			var textRegex = new RegExp("text[ ]*=[ ]*[\"']([^\"']*)[\"']");
			var textMatch = textRegex.exec(match[0]);
			sizeList += match[1] + "/" + textMatch[1] + ";";
		}
		match = regex.exec(combo);
	}
	if (sizeList.length > 0) {
		this.fontSizes = sizeList.substring(0, sizeList.length - 1);
	}
}

EditLiveJava.prototype.parseFaceComboBox = function(combo, regex) {
	var match = regex.exec(combo);
	var faceList = "";
	while(match) {
		faceList += match[1] + ";";
		match = regex.exec(combo);
	}
	if (faceList.length > 0) {
		this.fontFaces = faceList.substring(0, faceList.length - 1);
	}
}

EditLiveJava.prototype.parseStyleComboBox = function(combo, regex) {
	var match = regex.exec(combo);
	var styleList = "";
	while(match) {
		styleList += match[1] + ";";
		match = regex.exec(combo);
	}
	if (styleList.length > 0) {
		this.fontStyles = styleList.toLowerCase().substring(0, styleList.length - 1);
	}
}

EditLiveJava.prototype.parseToolbars = function(xml) {
	this.customToolbarDefinitions =  new Array();

	var start = 0;
	var end = 0;
	start = xml.indexOf("<toolbars", end);
	end = xml.indexOf("</toolbars>", start);
	if (end == -1 || start == -1) {
		//invalid xml
		return;
	}
	var toolbars = xml.substring(start + "<toolbars".length, end); 

	start = 0;
	end = 0;
	var toolbarList = new Array();
	while(start > -1) {
		start = toolbars.indexOf("<toolbar", end);
		end = toolbars.indexOf("</toolbar>", start);

		if (start > -1) {
			if (toolbarList.length > 0) {
				//new toolbar, add a new toolbar marker
				toolbarList[toolbarList.length] = '/';
			}
			
			var buttonGroup = new Array();
			var toolbar = toolbars.substring(start, end);
			var regex = new RegExp("<\\w*toolbar\\w[^>]*>", "gim");
			var match = regex.exec(toolbar);

			while(match) {
				if (match[0].toLowerCase().indexOf("separator") > -1) {
					toolbarList[toolbarList.length] = buttonGroup;
					buttonGroup = new Array();
				} else {
					this.parseToolbarButton(match, buttonGroup);
				}
				match = regex.exec(toolbar);
			}
			
			if (buttonGroup.length > 0) {
				toolbarList[toolbarList.length] = buttonGroup;
			}
		}
	}
	if (toolbarList.length > 0) {
		this.toolbarArrays = toolbarList;
	}
}

EditLiveJava.prototype.parseToolbarButton = function (match, buttonGroup) {
	if (match[0].toLowerCase().indexOf("customtoolbarbutton") > -1) {
		this.storeCustomButtonDefinition(match, buttonGroup);
	}
	var nameRegex = new RegExp("name[ ]*=[ ]*[\"']([^\"']*)[\"']", "i");
	var nameMatch = nameRegex.exec(match[0]);

	if (nameMatch) {
		var buttonName = nameMatch[1].toLowerCase();
		var fckEditorToolbarName = expressToolbarMap[buttonName];
		if (fckEditorToolbarName) {
			buttonGroup[buttonGroup.length] = fckEditorToolbarName;
		} else {
			//code reworked from elj
			if (buttonName == "align") {
				buttonGroup[buttonGroup.length] = expressToolbarMap["alignleft"];
				buttonGroup[buttonGroup.length] = expressToolbarMap["aligncenter"];
				buttonGroup[buttonGroup.length] = expressToolbarMap["alignright"];
			} else if (buttonName == "list") {
				buttonGroup[buttonGroup.length] = expressToolbarMap["unorderedlist"];
				buttonGroup[buttonGroup.length] = expressToolbarMap["orderedlist"];
			} else if (buttonName == "script") {
				buttonGroup[buttonGroup.length] = expressToolbarMap["superscript"];
				buttonGroup[buttonGroup.length] = expressToolbarMap["subscript"];
			}
		}
	}
}

EditLiveJava.prototype.storeCustomButtonDefinition = function (match, buttonGroup) {
	var customButtonDefinition = new Array();
	
	var nameAtt = getCustomButtonAttribute("name", match);
	customButtonDefinition["name"] = nameAtt;
	var iconAtt = getCustomButtonAttribute("imageurl", match);
	iconAtt = combineDownloadURL(iconAtt);
	customButtonDefinition["imageurl"] = iconAtt;
	var textAtt = getCustomButtonAttribute("text", match);
	customButtonDefinition["text"] = textAtt;		
	var valueAtt = getCustomButtonAttribute("value", match);
	customButtonDefinition["value"] = valueAtt;	
	var actionAtt = getCustomButtonAttribute("action", match);
	customButtonDefinition["action"] = actionAtt;		
	
	if (nameAtt) {
		buttonGroup[buttonGroup.length] = nameAtt;
		
		this.customToolbarDefinitions[this.customToolbarDefinitions.length] = customButtonDefinition;		
	}	
}

EditLiveJava.prototype.parseLinkElements = function (xml) {	
	var regex = new RegExp("<link.*rel=[\"']stylesheet[\"'].*>", "gim");	
	var match = regex.exec(xml);

	var stylesString = "";

	while(match) {	
		if (match[0].toLowerCase().indexOf("href") > -1) {
			var hrefRegex = new RegExp("href[ ]*=[ ]*[\"']([^\"']*)[\"']", "i");
			var hrefMatch = hrefRegex.exec(match[0]);
			
			if (hrefMatch) {				
				var linkHref = combineDownloadURL(hrefMatch[1]);							
				stylesString += getData(linkHref);
			}	
		}		
		match = regex.exec(xml);
	}
	
	return stylesString;
}

EditLiveJava.prototype.parseEmbeddedStyles = function (xml) {	
	var regex = new RegExp("<style.*type=[\"']text/css[\"'].*>([^<]*)</style>", "gim");		
	var match = regex.exec(xml);
	
	var embeddedStyles = "";
	
	if (match) {
		embeddedStyles = match[1];
	}
	
	return embeddedStyles;
}

function getCustomButtonAttribute(attName, match) {
	var nameRegex = new RegExp(attName + "[ ]*=[ ]*[\"']([^\"']*)[\"']", "i");
	var nameMatch = nameRegex.exec(match[0]);
	
	if (nameMatch) {
		return nameMatch[1];
	} else {
		return "";
	}
}

function createExpressEditorApplet(downloadDir) {
	// create applet element (2 x 2 pixels)
	var classpath = downloadDir;
	
	var params = new Array();
	var paramValues = new Array();
	var expressEditAppletHTML = EditLiveCommonStatic_generateAppletTag(2, 2, "expressEdit", classpath, new Array(), "ExpressEditApplet", params, paramValues, null, false);

	insertExpressEditDiv(expressEditAppletHTML);
}

function insertExpressEditDiv(expressEditAppletHTML) {
	// append applet in a div as child to body
	var appletDiv = document.createElement("div");
	appletDiv.setAttribute("id", "expressEditApplet");
	appletDiv.style.display = "inline";
	appletDiv.innerHTML = expressEditAppletHTML;
	appendChild(document.body, appletDiv);

}

function getFCKEditorContents(editorName) {
	var fckEditor = FCKeditorAPI.GetInstance(editorName);
	return fckEditor.GetHTML();
}

function setFocusForFCKEditor(editorName) {
	var fckEditor = FCKeditorAPI.GetInstance(editorName);
	return fckEditor.Focus();
}

function switchEditors() {
	// set this flag in order for the run-time methods of EditLive!
	// to detect if EditLive! 
	ephox_overwriteExpressEdit = "true";

	// iterate through list of EditLive! applet names, replacing javascript editors with EditLive! instances
	for(var i = 0; i < ephox_expressEditorInstances.length; i++) {
		var elj = ephox_expressEditorInstances[i];
				
		//skip if it's false or always
		if (elj.expressEdit.toString().toLowerCase() != "true") {
			continue;
		}
		
		// disable the onInitComplete callback so it doesn't run again
		elj.setOnInitComplete("");
		
		// give current FCKEditor instance focus. This overcomes IE security issues
		// which cause some JRE versions to trigger Java errors which break form submission.
		setFocusForFCKEditor(elj.name);
		
		var jsEditorDiv = document.getElementById(elj.name + "_fckDiv");	
		
		if (elj.getParam("Body") != "") {
			elj.setBody(encodeURIComponent(getFCKEditorContents(elj.name)));		
		} else {
			elj.setDocument(encodeURIComponent(getFCKEditorContents(elj.name)));
		}
		
		var appletDiv = document.createElement("div");
		appletDiv.setAttribute("id", elj.name + "_appletDiv");
		appletDiv.style.display = "inline";
		
		// add hidden form field. When we replace the FCKEditor instance, we'll also
		// be replacing it's hidden field for submitting content.		
		appletDiv.innerHTML = elj.getHiddenFieldString() + elj.getAppletHTML(false);		

		replaceNode(jsEditorDiv, appletDiv);
		
		elj.started = true;
	}	
	createCookieForUsingEditLive(ephox_expressEditorInstances[0].downloadDirectory);
}

function getCookieForUsingEditLive(downloadDirectory) {
	if (isFlashSupported) {
		// create a cookie using flash
		var flashObjectString = getFlashObject(downloadDirectory, "read");
		var div = document.createElement("div");
		div.style.display = "inline";
		div.innerHTML = flashObjectString;
		insertBefore(document.body.lastChild, div);
		return false;
	} else {
		return (document.cookie.indexOf("ephoxExpressEditCookie=true") > -1);	
	}
}

function createCookieForUsingEditLive(downloadDirectory) {
	if (isFlashSupported) {
		// create a cookie using flash
		var flashObjectString = getFlashObject(downloadDirectory, "write");

		// Cannot write to document directly because that will delete the page, so use a new div element
		var div = document.createElement("div");
		div.style.display = "inline";
		div.innerHTML = flashObjectString;
		appendChild(document.body, div);
	} else {
		//set a 10 year cookie
		var exdate=new Date();
		exdate.setDate(exdate.getDate() + 3650);
		document.cookie = "ephoxExpressEditCookie=true;expires=" + exdate.toGMTString();	
	}
}

function getFlashObject(downloadDirectory, cookieType) {
	downloadDirectory += "expressEdit/";
	var flashReference = downloadDirectory + "expressEdit.swf";
	var flashObjectString = "\n<OBJECT ID='ephoxExpressEdit' CLASSID='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000' CODEBASE='http://active.macromedia.com/flash2/cabs/swflash.cab#version=2,0,0,0' WIDTH='0' HEIGHT='0'>";
	flashObjectString += "<PARAM NAME='Movie' VALUE='" + flashReference + "'>";
	flashObjectString += "<PARAM NAME='swLiveConnect' VALUE='true'>";
	flashObjectString += "<PARAM NAME='FlashVars' VALUE='cookieType=" + cookieType + "'>";	
	flashObjectString += "<EMBED NAME='ephoxExpressEdit' mayscript='mayscript' SRC='" + flashReference + "' FlashVars='cookieType=" + cookieType + "' swLiveConnect='true' WIDTH='0' HEIGHT='0' pluginspage='http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash2'>";
	flashObjectString += "</EMBED>";
	flashObjectString += "</OBJECT>";
	flashObjectString += "<scr" + "ipt event=FSCommand(command,args) for='ephoxExpressEdit'>\n";
	flashObjectString += "ephoxExpressEdit_DoFSCommand(command, args) ";
	flashObjectString += "</scr" + "ipt>";

	return flashObjectString;
}

EditLiveJava.prototype.isExpressEditor = function() {
	if (ephox_overwriteExpressEdit && this.expressEdit != "always") {
		return false;
	} else {
		return true;
	}
}

// redefine runtime APIs for EditLive!
function reassignMethods(eljInstance) {
	// InsertHTMLAtCursor
	eljInstance.ephox_InsertHTMLAtCursorRef = eljInstance.InsertHTMLAtCursor;
	eljInstance.InsertHTMLAtCursor = function(htmlString) {
		if (eljInstance.isExpressEditor()) {
			htmlString = decodeHTMLContent(htmlString);
			InsertHtmlForFCKEditor(eljInstance.name, htmlString)
		} else {
			eljInstance.ephox_InsertHTMLAtCursorRef(htmlString);
		}
	}	
	
	// GetBody
	eljInstance.ephox_GetBodyRef = eljInstance.GetBody;
	eljInstance.GetBody = function(javascriptCallback, uploadImages) {
		if (eljInstance.isExpressEditor()) {
			var bodyHtml = GetBodyForFCKEditor(eljInstance.name);
			var bodyFunction = eval(javascriptCallback);
			bodyFunction(bodyHtml);
		} else {
			eljInstance.ephox_GetBodyRef(javascriptCallback, uploadImages);
		}
	}
	
	// GetSelectedText
	eljInstance.ephox_GetSelectedTextRef = eljInstance.GetSelectedText;
	eljInstance.GetSelectedText = function(javascriptCallback) {
		if (eljInstance.isExpressEditor()) {	
			var selectedText = GetSelectedTextForFCKEditor(eljInstance.name);
			var selFunction = eval(javascriptCallback);
			selFunction(selectedText);
		} else {
			eljInstance.ephox_GetSelectedTextRef(javascriptCallback);
		}
	}		
	
	// InsertHyperlinkAtCursor
	eljInstance.ephox_InsertHyperlinkAtCursor = eljInstance.InsertHyperlinkAtCursor;
	eljInstance.InsertHyperlinkAtCursor = function() {
		if (eljInstance.isExpressEditor()) {
			var hyperlinkString = "<a ";
			
			for (var i = 0; i < arguments.length; i++) {
				if (i == 0) {
					hyperlinkString += "href='" + arguments[i] + "'";
				} else {		
					var newAttValuePair = "";
					
					// wrap the value section of attribute-value pairs
					// in quotes
					var equalsIndex = arguments[i].indexOf("=");
					
					if (equalsIndex != -1) {
						var argumentString1 = arguments[i].substring(0, equalsIndex + 1);
						var argumentString2 = arguments[i].substring(equalsIndex + 1, arguments[i].length);
						
						newAttValuePair = argumentString1 + "'" + argumentString2 + "'";
						
						// add to hyperlink string
						hyperlinkString += " " + newAttValuePair;
					}
				}			
			}
			
			hyperlinkString += ">";			
			// get selected text from FCKEditor
			hyperlinkString += GetSelectedTextForFCKEditor(eljInstance.name);
			hyperlinkString += "</a>";

			InsertHtmlForFCKEditor(eljInstance.name, hyperlinkString);
		} else {			
			this.ephox_InsertHyperlinkAtCursor.apply(this, arguments);
		}
	}
	
	// SetBody
	eljInstance.ephox_SetBodyRef = eljInstance.SetBody;
	eljInstance.SetBody = function(bodyHtml) {
		if (eljInstance.isExpressEditor()) {
			bodyHtml = decodeHTMLContent(bodyHtml); 
			SetBodyForFCKEditor(eljInstance.name, bodyHtml);
		} else {
			eljInstance.ephox_SetBodyRef(bodyHtml);
		}
	}
	
	// GetDocument
	eljInstance.ephox_GetDocumentRef = eljInstance.GetDocument;
	eljInstance.GetDocument = function(javascriptCallback, uploadImages) {
		if (eljInstance.isExpressEditor()) {
			var documentHtml = GetDocumentForFCKEditor(eljInstance.name);
			var getDocumentFunction = eval(javascriptCallback);
			getDocumentFunction(documentHtml);
		} else {
			eljInstance.ephox_GetDocumentRef(javascriptCallback, uploadImages);
		}
	}	
	
	// SetDocument
	eljInstance.ephox_SetDocumentyRef = eljInstance.SetDocument;
	eljInstance.SetDocument = function(documentHtml) {
		if (eljInstance.isExpressEditor()) {
			documentHtml = decodeHTMLContent(documentHtml);
			SetDocumentForFCKEditor(eljInstance.name, documentHtml);
		} else {
			eljInstance.ephox_SetDocumentyRef(documentHtml);
		}
	}	
}

function InsertHtmlForFCKEditor(editorName, htmlString) {
	var fckEditor = FCKeditorAPI.GetInstance(editorName);
	fckEditor.InsertHtml(htmlString);
}

function GetBodyForFCKEditor(editorName) {
	var fckEditor = FCKeditorAPI.GetInstance(editorName);

	fckEditor.Config["FullPage"] = false;
	var fckEditorBody = fckEditor.GetHTML();
	fckEditor.Config["FullPage"] = true;
	
	return fckEditorBody;
}

function GetSelectedTextForFCKEditor(editorName) {
	var fckEditor = FCKeditorAPI.GetInstance(editorName);
			
	if (fckEditor.EditorWindow.getSelection) {
		return fckEditor.EditorWindow.getSelection();
	} else if (fckEditor.EditorDocument.getSelection) {
		return fckEditor.EditorDocument.getSelection();
	} else if (fckEditor.EditorDocument.selection) {
		return fckEditor.EditorDocument.selection.createRange().htmlText;
	}
}

function SetBodyForFCKEditor(editorName, htmlString) {
	var fckEditor = FCKeditorAPI.GetInstance(editorName);
	var fckEditorDocument = fckEditor.GetHTML();
	
	var preBodyIndex = fckEditorDocument.indexOf("<body");
	var postBodyIndex = fckEditorDocument.indexOf("</body");
	var preBodyString = fckEditorDocument.substring(0, preBodyIndex);
	var postBodyString = fckEditorDocument.substring(postBodyIndex, fckEditorDocument.length);
	
	fckEditor.SetHTML(preBodyString + "<body>" + htmlString + postBodyString);
}

function GetDocumentForFCKEditor(editorName) {
	var fckEditor = FCKeditorAPI.GetInstance(editorName);	
	var fckEditorDocument = fckEditor.GetHTML();
	
	return fckEditorDocument;
}

function SetDocumentForFCKEditor(editorName, htmlString) {
	var fckEditor = FCKeditorAPI.GetInstance(editorName);	
	fckEditor.SetHTML(htmlString);	
}

var oldSetXML = EditLiveCommon_setXMLURL;

EditLiveCommon_setXMLURL = function(strXMLURL) {
	if (strXMLURL.toString().indexOf("file:/") > -1) {
		oldSetXML.apply(this, [strXMLURL]);
		return;
	}
	var xmlData = getData(strXMLURL);
	this.setXML(encodeURIComponent(xmlData));
}

function getData(url) {
	var ua = navigator.userAgent.toLowerCase();
	if (!window.ActiveXObject) {
		request = new XMLHttpRequest();
	} else if (ua.indexOf('msie 5') == -1) {
		request = new ActiveXObject("Msxml2.XMLHTTP");
	} else {
		request = new ActiveXObject("Microsoft.XMLHTTP");
	}
 
	try {
 		request.open("GET", url, false);
 		request.send("");
	} catch (err) {	
		// due to security reasons or other errors, the URL connection failed.
		return "";
	}
 
	if (request.status == 200) {
		return request.responseText;
	} else {
		return "";
	}
}

function decodeHTMLContent(html) {
	html = html.replace(/\+/g, ' ');
	return decodeURIComponent(html);
}

// create link to express editor scripts
document.write("<scr" + "ipt language='Javascript' src='" + getScriptBase('expressEdit.js') + "fckeditor/fckeditor.js'></scr" + "ipt>"); 
