/*
	JanYii Editor Version 1.1 	
	
    Copyright (c) 2010 JanYii Ltd (contact via http://www.janyii.com/)
	
	This editor is distributed  under the terms of the Creative Commons 
	Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)  
	License available at http://creativecommons.org/licenses/by-sa/3.0/.
*/  
  

/***************************************************************************
						JanYiiEditorFactory Class

Creates instances of the editor for each content editable field, and provide 
services to them. 						
***************************************************************************/


//Contructor
function JanYiiEditorFactory (baseUrlIn, paramsUrlIn){
	this.siteUrl = baseUrlIn;				//Site's base URL	
	this.paramsUrl = paramsUrlIn;			//URL to obtain the editor's parameters via Ajax 
	this.editorObjArray =  new Array();     //Array of editor objects 
	this.siteUrlTag = ''; 					//Tag used to replace the site URL in data before saving to server
	this.userImagesPath = '';				//Path on server to the user's images 
	this.userImageInfoUrl = '';	     		//URL for Ajax request get list of the user's images
	this.userDownloadInfoUrl  = '';			//URL for Ajax request get list of the user's download files
	this.userDownloadLinkPath = '';			//URL path for download links
	this.helpUrl  = '';						//Relative URL to help file
	this.userImageNameArray = new Array(); 	//Array of user image file names.  
	this.downloadObj = null;				//Object acting as associative array id => title
	this.functionsArray =  new Array(); 	//Array of functions
	this.colorsArray =  new Array(); 		//Array of color names
	this.colorCodesArray =  new Array(); 	//Array of color codes
	this.editorImagePath =  ''; 			//URL for editor's button images 
	this.numericCtrlStr = '';				//String to store HTML for a numeric drop downn list
	this.messageObj = null;					//Object acting as associative array  label => message text	
	this.pagesArray =  new Array(); 		//Array of page names
	this.pageRoutesArray =  new Array(); 	//Array of page routes
	this.fontsArray  =  new Array();		//Array of fonts
	
	//Initialize font array = may be overridden from server
	this.fontsArray = ['Arial', 'Comic Sans MS', 'Courier New', 'Tahoma', 'Times New Roman', 'Verdana'];
	
	//Return if no content editable elements
	var len = $(".contenteditable").length; 
	if(len  == 0){ 	
		return;
	}
	
	//Make the string once here for efficiency 
	this.numericCtrlStr = this.makeNumSelectCtrl(26,5);
	
	this.editorImagePath  = this.getPathToSelf().replace('janyii.editor.js','images/' );
	
	//Request parameter info from server.
	//If this is successful it results in a chain of actions to create an editor
	//for each content editable element.
	this.fetchParams();	
}

//Obtain parameter info using Ajax 
JanYiiEditorFactory.prototype.fetchParams = function (){
	var thisInstance = this;
	$.post(
     	this.paramsUrl,
     	{Data: ''}, 
     	function(){thisInstance.fetchParamsCallback.call(thisInstance,arguments[0]);}
     );
}

//On callback saves param info and issues request for user image data  
JanYiiEditorFactory.prototype.fetchParamsCallback = function(xml) {
	try{    
    	var status = $("Status", xml).text();
    	if(status){
    		alert(status);
    	}
    	else{
    		this.siteUrlTag = $("SiteUrlTag", xml).text();
    		this.userImagesPath = $("UserImagesPath", xml).text();
    		this.userImageInfoUrl = $("UserImageInfoUrl", xml).text();
    		this.userDownloadInfoUrl = $("UserDownloadInfoUrl", xml).text();
    		this.userDownloadLinkPath = $("UserDownloadLinkPath", xml).text();
    		this.helpUrl =  this.siteUrl + $("HelpFile", xml).text();
    		var str = $("JsonMessageStr", xml).text();
    		if(str != '[]')
    			this.messageObj =  this.messageObj = jQuery.parseJSON(str);
    		
    		var str = $("Functions", xml).text();    		
    		this.functionsArray = str.split(',');
    		for(var i = 0; i < this.functionsArray.length ; i++)
    			this.functionsArray[i] = jQuery.trim(this.functionsArray[i]);	
    		
    		var str = $("Colors", xml).text();
    		this.colorsArray = str.split(',');
    		for(var i = 0; i < this.colorsArray.length ; i++)
    			this.colorsArray[i] = jQuery.trim(this.colorsArray[i]);	
    		
    		var str = $("ColorCodes", xml).text();
    		this.colorCodesArray = str.split(',');
    		for(var i = 0; i < this.colorCodesArray.length ; i++)
    			this.colorCodesArray[i] = jQuery.trim(this.colorCodesArray[i]);
    			
    		if(this.colorsArray.length != this.colorCodesArray.length)
    			throw new Error("Color => Color Code mismatch.");		
    			
    		var str = $("Pages", xml).text();
    		this.pagesArray = str.split(',');
    		for(var i = 0; i < this.pagesArray.length ; i++)
    			this.pagesArray[i] = jQuery.trim(this.pagesArray[i]);	
    		
    		var str = $("PageRoutes", xml).text();
    		this.pageRoutesArray = str.split(',');
    		for(var i = 0; i < this.pageRoutesArray.length ; i++)
    			this.pageRoutesArray[i] = jQuery.trim(this.pageRoutesArray[i]);	
    			
    		if(this.pageRoutesArray.length != this.pagesArray.length)
    			throw new Error("Page => Page Route mismatch.");	
    			
    		var str = $("Fonts", xml).text();
    		str = jQuery.trim(str);
    		if(str){
    			this.fontsArray = str.split(',');
    			for(var i = 0; i < this.fontsArray.length ; i++)
    				this.fontsArray[i] = jQuery.trim(this.fontsArray[i]);	
   			}
   			
    		this.fetchUserImageData();    			
    	}
    }	
    catch(error){
    	alert( "ERROR_FETCHING_SERVER_PARAMETERS " + error);
    }	
}


//Obtain user image info using Ajax
JanYiiEditorFactory.prototype.fetchUserImageData = function(){	
	var thisInstance = this; 	
	$.post(
     	this.userImageInfoUrl,
     	{Data: ''}, 
     	function(){thisInstance.fetchUserImageDataCallback.call(thisInstance,arguments[0]);}
    ); 
}

//On callback save the image info,then request the downloaf file info
JanYiiEditorFactory.prototype.fetchUserImageDataCallback = function(xml){	
	var errorFlag = false;	
	try{ 	
		var str =  $("Images", xml).text();
    	var status = $("Status", xml).text();
    	this.userImageNameArray = str.split(',');
    	if(status){
    		alert(status);
    	}
    }
    catch(error){
    	alert(this.messageObj.ERROR_FETCHING_IMAGES + error);
    	errorFlag = true;
    }	
    if (! errorFlag){
    	this.fetchUserDownloadData();
    }	
}

//Obtain user download file info using Ajax
JanYiiEditorFactory.prototype.fetchUserDownloadData = function(){	
	var thisInstance = this;
	$.post(
     	this.userDownloadInfoUrl,
     	{Data: ''}, 
     	function(){thisInstance.fetchUserDownloadDataCallback.call(thisInstance,arguments[0]);}
    ); 
}

//On callback save the download file info, then issue request to activate editors 
JanYiiEditorFactory.prototype.fetchUserDownloadDataCallback = function(xml){	
	var errorFlag = false;	
	try{ 	
		var str =  $("JsonDownloadInfo", xml).text();
    	var status = $("Status", xml).text();
    	if(str != '[]')
    		this.downloadObj = jQuery.parseJSON(str);
    	if(status){
    		alert(status);
    	}
    }
    catch(error){
    	alert(this.messageObj.ERROR_FETCHING_DOWNLOADS + error);
    	errorFlag = true;
    }	
    if (! errorFlag){
    	this.activateEditors();
    }	
}


//Iterate over each content editable item calling the createEditor method 
//using 'this' as its context.
JanYiiEditorFactory.prototype.activateEditors = function(){	
	var thisInstance = this;
	$('.contenteditable').each(
		function(){thisInstance.createEditor.call(thisInstance,  $(this).attr('id'));}
	); 	
}

//Create an editor for the specified element. 
JanYiiEditorFactory.prototype.createEditor = function(elementId){
	editorObj = new JanYiiEditor(this,elementId); 
	this.editorObjArray.push(editorObj);
}

//Create a numeric drop down list control 
JanYiiEditorFactory.prototype.makeNumSelectCtrl = function(count, selectedValue){
	if(count < 1){
		return;
	}
	var html = '<select class="imagecontrol" >'; 
	for(i=0; i < count; i++){
		if(i == selectedValue){
			html = html + '<option value="' + i + '" selected>' + i + '</option>';
		}
		else{		
			html = html + '<option value="' + i + '" >' + i + '</option>';
		}	 
	}
	html = html + '</select>';
	return html;
}

//Get path to script 
//From http://snipplr.com/view/6741/get-url-to-external-script/
//Returns values of the form: /yiiDevelopment/js/jyeditor/janyii.editor.js
JanYiiEditorFactory.prototype.getPathToSelf = function() {
	var myName = /(^|[\/\\])janyii\.editor\.js(\?|$)/;
    var scripts = document.getElementsByTagName("script");
    for (var i = 0; i < scripts.length; i++) {
		var src;
      	if (src = scripts[i].getAttribute("src")) {
      		if (src.match(myName)) {
				return src;
      		}
		}
	}
}


/***************************************************************************
						JanYiiEditor Class

				Provides editing facilities for a unique element 						
***************************************************************************/


//Constructor 
function JanYiiEditor (factoryObj, elementId){
	this.jqueryObj;							//Content JQuery Object.	
	this.id = elementId;					//Element id
	this.factoryObj = factoryObj;			//Factory object
	this.siteUrl;           				//Site url e.g. http://localhost/yiiDevelopment/
	this.updateUrl;							//URL for Ajax update 
	this.dataItemName; 						//Name of the DB column to be updated.
	this.dataItemID;						//ID (key) of the record to be updated.
	this.dataModel;							//Name of the model object responsible for DB updates
	this.contentBeforeEditing;				//Element content before any editing.
	this.editingModeToggle = false; 		//Indicates whether edit controls are visible. 
	this.toggleBar;							//Main editor div that can be toggled to view/hide it. 
	this.editButton;						//Button used to toggle editor. 
	this.currentBar;						//The current child bar (e.g. images bar).
	this.toolBar;							//The panel with all the editor buttons on it. 
	this.originalBackgroundColor;			//Original Background Color
	this.fontList;							//The control to list fonts
	this.fontSizeList;						//The control to list font sizes
	this.imageBar;							//The bar containing the image selection controls
	this.colorsBar;							//The bar for colors
	this.downloadBar;						//The bar containing the download link selection controls
	this.pageBar;							//The bar containing the page link selection controls
	this.linkBar; 							//The bar for inserting a link
	this.pasteBar;							//The bar for pasting HTML 
	this.imagePanel;						//The panel on the image bar for scrolling images
	this.imageUrl;							//Url to use so access user images 
	this.alignment; 						//Image bar alignment control 
	this.rightMargin;						//Image bar right margin  control
	this.leftMargin;						//Image bar left margin control
	this.topMargin;							//Image bar top margin control
	this.bottomMargin; 						//Image bar bottom margin control
	this.scale;								//Image bar scale control	
	this.t = this.factoryObj.messageObj		//Translation obj to covert message names to their display format
	this.currentColorCode = '';				//Current color 
	this.treeWin = null;					//Window for DOM Tree output
	this.firstTimeOpen = true;				//True if first time the editor opened since the page was loaded

	this.jqueryObj = $('#' + this.id);
	this.siteUrl = this.factoryObj.siteUrl;	//getBaseURL();    
	this.imageUrl = this.siteUrl + this.factoryObj.userImagesPath.substring(2);  					
	this.updateUrl = this.jqueryObj.attr("updateUrl");
	this.dataItemName = this.jqueryObj.attr("dataItemName");
	this.dataItemID = this.jqueryObj.attr("dataItemID");
	this.dataModel = this.jqueryObj.attr("dataModel");
	this.contentBeforeEditing = this.jqueryObj.html();
	this.makeEditorControls();	
	this.originalBackgroundColor = this.jqueryObj.css('background-color');
	
	var thisInstance = this;
	var onbeforeunloadFunc = function(e){thisInstance.onbeforeunload.call(thisInstance,e);}
	window.onbeforeunload = onbeforeunloadFunc;
	
	this.toggleEditMode();
}


//----------------------------- Functions to create tool bars -----------------------------

//Create the main editor panel 
JanYiiEditor.prototype.makeEditorControls = function (){	
	var thisInstance = this;
	var toggleClickFunction = function(){thisInstance.toggleEditMode.call(thisInstance);}
	this.editButton = this.makeCustomEditBtn('editor.gif', 'Edit', toggleClickFunction); 		
	this.toggleBar = $("<div class='toggleBar'></div>");	
	this.toggleBar.append(this.editButton);
	this.toggleBar.insertBefore(this.jqueryObj);
	
	this.makefontList();							
	this.makeFontSizeList();
	
	this.maketoolBar();
	this.toolBar.insertBefore(this.jqueryObj);	
	this.toolBar.hide();
	
	this.makeImageBar();
	this.imageBar.insertBefore(this.jqueryObj);
	this.imageBar.hide();
	this.addImagesToPanel();
	
	this.makeDownloadBar();
	this.downloadBar.insertBefore(this.jqueryObj);
	this.downloadBar.hide();
	
	this.makePageBar();
	this.pageBar.insertBefore(this.jqueryObj);
	this.pageBar.hide();
	
	this.makeLinkBar();
	this.linkBar.insertBefore(this.jqueryObj);
	this.linkBar.hide();
	
	this.makePasteBar();
	this.pasteBar.insertBefore(this.jqueryObj);
	this.pasteBar.hide(); 
	
	this.makeColorsBar();
	this.colorsBar.insertBefore(this.jqueryObj);
	this.colorsBar.hide(); 
	
	/*
	//Tidy up toolbar presentation
	if(jQuery.browser.msie){
		document.getElementById(this.id + '_fonts').style.top = '-7px';
		document.getElementById(this.id + '_size').style.top = '-7px';
		document.getElementById(this.id + "_toolbar").style.height = '22px';
	}	
	else{
		document.getElementById(this.id + '_fonts').style.top = '-7px';
		document.getElementById(this.id + '_size').style.top = '-7px';
		document.getElementById(this.id + "_toolbar").style.height = '24px';
	}	*/ 
}


// Returns the version of Internet Explorer or a -1 (indicating the use of another browser).
JanYiiEditor.prototype.getInternetExplorerVersion = function ()
{
  var rv = -1; // Return value assumes failure.
  if (navigator.appName == 'Microsoft Internet Explorer')
  {
    var ua = navigator.userAgent;
    var re  = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
    if (re.exec(ua) != null)
      rv = parseFloat( RegExp.$1 );
  }
  return rv;
}


//Make the editor buttons 
JanYiiEditor.prototype.maketoolBar = function(){
	var thisInstance = this;
	this.toolBar = $('<div id="' + this.id + '_toolbar" class="toolbar"></div>');
	var imageClickFunction = function(){thisInstance.showImageBar.call(thisInstance);}
	var imageButton = this.makeCustomEditBtn('editor_image.gif', this.t.IMAGES, imageClickFunction);
	var downloadClickFunction = function(){thisInstance.showDownloadBar.call(thisInstance);}
	var downloadButton = this.makeCustomEditBtn('editor_download.gif', this.t.DOWNLOAD, downloadClickFunction);
	var pageClickFunction = function(){thisInstance.showPageBar.call(thisInstance);}
	var pageButton = this.makeCustomEditBtn('editor_page.gif', this.t.PAGE, pageClickFunction);			 				
	var clearAllClickFunction = function(){thisInstance.clearAll.call(thisInstance);};
	var clearAllButton = this.makeCustomEditBtn('editor_clear_all.gif', this.t.CLEAR_ALL, clearAllClickFunction); 				
	var saveClickFunction = function(){thisInstance.saveContent.call(thisInstance, false);};
	var saveButton = this.makeCustomEditBtn('editor_save.gif', this.t.SAVE, saveClickFunction);		
	var clearHeadingClickFunction = function(){thisInstance.clearHeading.call(thisInstance, false);};
	var clearHeadingButton = this.makeCustomEditBtn('editor_clear_heading.gif', this.t.CLEAR_HEADING, clearHeadingClickFunction);
	var linkClickFunction = function(){thisInstance.showLinkBar.call(thisInstance);};
	var linkButton = this.makeCustomEditBtn('editor_link.gif', this.t.LINK, linkClickFunction);		
	var colorsFunction = function(){thisInstance.showColorsBar.call(thisInstance);};
	var pickColorsButton = this.makeCustomEditBtn('editor_pick_color.gif', this.t.PICK_COLOR, colorsFunction, 'pickcolor', this.elementId + 'pickcolor');	
	var pasteClickFunction = function(){thisInstance.showPasteBar.call(thisInstance);};
	var pasteHtmlButton = this.makeCustomEditBtn('editor_paste.gif', this.t.PASTE, pasteClickFunction);
	var restoreClickFunction = function(){thisInstance.restoreContent.call(thisInstance);};
	var restoreButton = this.makeCustomEditBtn('editor_restore.gif', this.t.RESTORE_CONTENT, restoreClickFunction);	
	var helpClickFunction = function(){thisInstance.help.call(thisInstance);};
	var helpButton = this.makeCustomEditBtn('editor_help.gif', this.t.HELP, helpClickFunction);
	var domTreeClickFunction = function(){thisInstance.domTree.call(thisInstance);};
	var domTreeButton = this.makeCustomEditBtn('editor_dom_tree.gif', this.t.DOM_TREE, domTreeClickFunction);
	var testClickFunction = function(){thisInstance.test.call(thisInstance);};
	var testButton = this.makeCustomEditBtn('editor_test.gif', this.t.TEST, testClickFunction);
  	
  	if(! jQuery.browser.opera){	
		if(this.factoryObj.functionsArray.in_array('Font'))	
			this.toolBar.append(this.fontList);
		if(this.factoryObj.functionsArray.in_array('Size'))	
			this.toolBar.append(this.fontSizeList);	
	}			
	if(this.factoryObj.functionsArray.in_array('H1'))    
	    this.addStdBtn(this.toolBar, "editor_h1.gif", this.t.HEADING_1, "formatblock", '<h1>');
	if(this.factoryObj.functionsArray.in_array('H2'))    
	    this.addStdBtn(this.toolBar, "editor_h2.gif", this.t.HEADING_2, "formatblock", '<h2>');
	if(this.factoryObj.functionsArray.in_array('H3'))    
	    this.addStdBtn(this.toolBar, "editor_h3.gif", this.t.HEADING_3, "formatblock", '<h3>');   
	if(this.factoryObj.functionsArray.in_array('ClearHeading'))    
	    this.toolBar.append(clearHeadingButton);   		    	
  	if(this.factoryObj.functionsArray.in_array('Italic'))
	  	this.addStdBtn(this.toolBar, "editor_italic.gif", this.t.ITALIC, "italic", null);
	if(this.factoryObj.functionsArray.in_array('StrikeThrough'))    
	    this.addStdBtn(this.toolBar, "editor_strikethrough.gif", this.t.STRIKE_THROUGH, "strikethrough", null);
	if(this.factoryObj.functionsArray.in_array('Bold'))    
	    this.addStdBtn(this.toolBar, "editor_bold.gif", this.t.BOLD, "bold", null);
	if(this.factoryObj.functionsArray.in_array('Underline'))    
	    this.addStdBtn(this.toolBar, "editor_underline.gif", this.t.UNDERLINE, "Underline", null);
	if(this.factoryObj.functionsArray.in_array('PickColor')) 
	      this.toolBar.append(pickColorsButton);	      
	if(this.factoryObj.functionsArray.in_array('ForegroundColor'))    
	    this.addStdBtn(this.toolBar, "editor_color.gif", this.t.FOREGROUND_COLOR, "foreColor");	   
	if(this.factoryObj.functionsArray.in_array('Highlight'))    
	    this.addStdBtn(this.toolBar, "editor_highlight.gif", this.t.HIGHLIGHT, "hiliteColor");	       	      
	if(this.factoryObj.functionsArray.in_array('ClearFormat'))    
	    this.addStdBtn(this.toolBar, "editor_clear_format.gif", this.t.CLEAR_FORMAT, "removeFormat", '');     	    
	if(this.factoryObj.functionsArray.in_array('NumberedList'))    
	    this.addStdBtn(this.toolBar, "editor_numbered_list.gif", this.t.NUMBERED_LIST, "InsertOrderedList", null);
	if(this.factoryObj.functionsArray.in_array('UnorderedList'))    
	    this.addStdBtn(this.toolBar, "editor_unordered_list.gif", this.t.UNORDERED_LIST, "InsertUnorderedList", null);
	if(this.factoryObj.functionsArray.in_array('CentreJustify'))    
	    this.addStdBtn(this.toolBar, "editor_centre.gif", this.t.JUSTIFY_CENTRE, "JustifyCenter", null);
	if(this.factoryObj.functionsArray.in_array('LeftJustify'))    
	    this.addStdBtn(this.toolBar, "editor_left.gif", this.t.JUSTIFY_LEFT, "JustifyLeft", null);
	if(this.factoryObj.functionsArray.in_array('RightJustify'))    
	    this.addStdBtn(this.toolBar, "editor_right.gif", this.t.JUSTIFY_RIGHT, "JustifyRight", null);
	if(this.factoryObj.functionsArray.in_array('Indent'))    
	    this.addStdBtn(this.toolBar, "editor_indent.gif", this.t.INDENT, "Indent", null);
	if(this.factoryObj.functionsArray.in_array('Outdent'))    
	    this.addStdBtn(this.toolBar, "editor_outdent.gif", this.t.OUTDENT, "Outdent", null);
       
	if(this.factoryObj.functionsArray.in_array('Image'))    
	    this.toolBar.append(imageButton);	
	if(this.factoryObj.functionsArray.in_array('Download'))    
	    this.toolBar.append(downloadButton); 
	if(this.factoryObj.functionsArray.in_array('Page'))    
	    this.toolBar.append(pageButton);        
	if(this.factoryObj.functionsArray.in_array('Link'))    
	    this.toolBar.append(linkButton);
	    
	if(this.factoryObj.functionsArray.in_array('Unlink'))    	
	    this.addStdBtn(this.toolBar, "editor_remove_link.gif", this.t.UNLINK, "unlink", '');   	    
	      
	if(this.factoryObj.functionsArray.in_array('Paste'))    
	    this.toolBar.append(pasteHtmlButton);
	if(this.factoryObj.functionsArray.in_array('RestoreContent'))    
	    this.toolBar.append(restoreButton);
	if(this.factoryObj.functionsArray.in_array('ClearAll'))    
	    this.toolBar.append(clearAllButton);	       
	if(this.factoryObj.functionsArray.in_array('Help'))    
	    this.toolBar.append(helpButton);
	if(this.factoryObj.functionsArray.in_array('Save'))    
	    this.toolBar.append(saveButton); 
	if(this.factoryObj.functionsArray.in_array('DOMTree'))    
	    this.toolBar.append(domTreeButton);  
	if(this.factoryObj.functionsArray.in_array('Test'))    
	    this.toolBar.append(testButton);          
	     
}

//Make font list
JanYiiEditor.prototype.makefontList = function(){	
	var fonts = '<option selected value="">Font</option>';	
	for(var i=0; i < this.factoryObj.fontsArray.length; i++)
		fonts += '<option value="' + this.factoryObj.fontsArray[i] + '">' + this.factoryObj.fontsArray[i] + '</option>';
	//var fonts = '<option selected value="">Font</option><option value="Arial">Arial</option>	<option value="Comic Sans MS">Comic Sans MS</option>	<option value="Courier New">Courier New</option>	<option value="Tahoma">Tahoma</option>	<option value="Times New Roman">Times New Roman</option>	<option value="Verdana">Verdana</option>';		
	this.fontList = $('<select id="' + this.id + '_fonts"  class="font_list">'+ fonts +'</select>')
		.change(function(){
    		document.execCommand('FontName', false, this.value);
	    });	    
}						



//Make font size list
JanYiiEditor.prototype.makeFontSizeList = function(){	
	var sizes = '<option selected value="">Size</option><option value="1">1</option><option value="2">2<option value="3">3 </option><option value="4">4</option><option value="5">5</option><option value="6">6</option><option value="7">7</option>';
	this.fontSizeList = $('<select id="' + this.id + '_size" class="font_size" >'+ sizes +'</select>')
		.change(function(){
    		document.execCommand('FontSize', false, this.value);
	    });	  
}	


//Make the image bar 
JanYiiEditor.prototype.makeImageBar= function(){
	this.imageBar = $("<div class='imagebar'></div>");
	this.imagePanel = $("<div class='imagepanel'></div>");
	this.imageBar.append(this.imagePanel);
	this.alignment = $('<select class="imagecontrol" title="Alignment" name="Alignment"><option value="left">left</option><option value="right">right</option><option value="center">middle</option></select>');
	str = this.factoryObj.numericCtrlStr; 
	this.rightMargin = $(str);
	this.leftMargin = $(str); 
	this.topMargin = $(str); 
	this.bottomMargin = $(str);
	this.scale= $('<input  class="imagecontrol" style="width:50px" title="Scale (Resize Image)" type="text" size="4" maxlength="10" value=100>');   	
	this.imageBar.append("Align ");	
	this.imageBar.append(this.alignment);
	this.imageBar.append(" Right ");	
	this.imageBar.append(this.rightMargin);
	this.rightMargin.attr('Title', 'Right Margin');
	this.imageBar.append(" Left ");	
	this.imageBar.append(this.leftMargin);
	this.leftMargin.attr('Title', 'Left Margin');
	this.imageBar.append(" Top ");	
	this.imageBar.append(this.topMargin);
	this.topMargin.attr('Title', 'Top Margin');
	this.imageBar.append(" Bottom ");	
	this.imageBar.append(this.bottomMargin);
	this.bottomMargin.attr('Title', 'Bottom Margin');
	this.imageBar.append(" Scale% ");	
	this.imageBar.append(this.scale);	
}

//Add the user images to the image panel 
JanYiiEditor.prototype.addImagesToPanel = function(){
	var thisInstance = this;
	if(this.factoryObj.userImageNameArray.length == 0){
		this.imagePanel.html('<span style="color:blue;">' + this.t.NO_IMAGES_AVAILABLE_FOR_INSERT + '</span>');
	}
	else{
			//for (item in this.factoryObj.userImageNameArray){
		for( i=0; i <  this.factoryObj.userImageNameArray.length; i++ ){
			//image = this.factoryObj.userImageNameArray[item];
			image = this.factoryObj.userImageNameArray[i];
			imageClickFunction = function(){thisInstance.insertImage.call(thisInstance, this);}
			imageHtml = $('<img src="' + this.imageUrl + image + '" height="30" border="0" hspace="2" name="' + image + '" title="'+ image + '" alt="' + image + '">')
			.click(imageClickFunction);
			this.imagePanel.append(imageHtml);
		}
	}		
}

//Make the download bar 
JanYiiEditor.prototype.makeDownloadBar = function(){
	var thisInstance = this;
	labelTxt = '';
	if(this.factoryObj.downloadObj)
		labelTxt = this.t.DOWNLOAD_LINKS;
	this.downloadBar = $('<div class="downloadbar"> &nbsp; <label for="downloads" style="position:relative; top:-4px;"> ' + labelTxt + '</label> </div>');
	var html = this.makeDownloadListHtml();
	var downloadList = $('<span style="color:blue;">' + html + '</span>');
	this.downloadBar.append(downloadList);
	var downloadClickFunction = function(){thisInstance.insertDownloadLink.call(thisInstance, downloadList );}		
	var cssClass = 'insertbutton';
	var insertButton = this.makeCustomEditBtn('editor_insert.gif', 'Insert Link', downloadClickFunction, cssClass);
	if(this.factoryObj.downloadObj)
		this.downloadBar.append(insertButton);	
}

//make the download list HTML
JanYiiEditor.prototype.makeDownloadListHtml = function(){
	if(this.factoryObj.downloadObj  == null){
		return this.t.NO_DOWNLOAD_LINKS_AVAILABLE_FOR_INSERT;
	}
	else{
		
		var html = '<select style="position:relative; top:-5px;" class="download_control" name="file_list" id ="' + this.elementId + '_download_list"><option value=""></option>';
		for(var prop in this.factoryObj.downloadObj) {
    		html += '<option value="' + prop + '" >' + this.factoryObj.downloadObj[prop] + '</option>';
		}
		html += '</select>';
		return html;
	}	
}	

//Make the page bar 
JanYiiEditor.prototype.makePageBar = function(){
	var thisInstance = this;
	this.pageBar = $('<div class="pagebar"> &nbsp; <label for="pages"  style="position:relative; top:-4px;"> ' + this.t.PAGE_LINKS + '</label> </div>');
	var html = this.makePageListHtml();
	var pageList = $('<span style="color:blue;">' + html + '</span>');
	this.pageBar.append(pageList);
	var pageClickFunction = function(){thisInstance.insertPageLink.call(thisInstance, pageList );}		
	var cssClass = 'insertbutton';
	var insertButton = this.makeCustomEditBtn('editor_insert.gif', 'Insert Page', pageClickFunction, cssClass);
	this.pageBar.append(insertButton);	
}

//make the page list HTML
JanYiiEditor.prototype.makePageListHtml = function(){
	if(! this.factoryObj.pagesArray){
		return this.t.NO_PAGE_LINKS_AVAILABLE_FOR_INSERT;
	}
	else{
		var html = '<select style="position:relative; top:-5px;" class="page_control" name="page_list" id ="' + this.elementId + '_page_list"><option value=""></option>';
		for(var i = 0; i <  this.factoryObj.pagesArray.length ; i++)
    		html += '<option value="' + this.factoryObj.pageRoutesArray[i] + '" >' + this.factoryObj.pagesArray[i] + '</option>';
		html += '</select>';
		return html;
	}	
}	

//Make the link bar 
JanYiiEditor.prototype.makeLinkBar = function(){
	var thisInstance = this;
	var msg = '';
	if(this.t.LINK_PROMPT)
		msg = this.t.LINK_PROMPT;
	else
		msg = "Address (e.g. http://www.janyii.com or me@janyii.com)";
	
	this.linkBar = $('<div class="linkbar"><label for="'+ this.elementId +'_linkurl" style="position:relative; top:-4px;"></label> <span style="position:relative; top:-4px;"><small>' + msg + '</small></span> </div>');
	var linkInputBox = $('<input style="position:relative; top:-5px; margin-right:3px; width:180px" class="inputcontrol"  type="text"	id="'+ this.elementId +'_linkurl" >');
	this.linkBar.append(linkInputBox);
	var linkClickFunction = function(){thisInstance.insertLink.call(thisInstance, linkInputBox );}		
	var cssClass = 'insertbutton';
	var insertButton = this.makeCustomEditBtn('editor_insert.gif', 'Insert Link', linkClickFunction, cssClass);
	this.linkBar.append(insertButton);		
}

//Make paste bar 
JanYiiEditor.prototype.makePasteBar = function(){
	var thisInstance = this;
	this.pasteBar = $('<div class="pastebar" > </div>');
	var pasteInputArea = $('<textarea class="pastebox" id="'+ this.elementId + '_pastebox" rows="3" cols="70"></textarea>');
	this.pasteBar.append(pasteInputArea);
	var pasteClickFunction = function(){thisInstance.pasteHtmlArea.call(thisInstance, pasteInputArea );}
	var insertButton = this.makeCustomEditBtn('editor_insert.gif', 'Paste HTML', pasteClickFunction, cssClass);
	var cssClass = 'insertbutton';	
	this.pasteBar.append(insertButton);		
}

//Make colors bar 
JanYiiEditor.prototype.makeColorsBar = function(){
	var thisInstance = this;
	this.colorsBar = $('<div class="colorsbar" name="colorsbar" ></div>');
	for( i=0; i <  this.factoryObj.colorsArray.length; i++ ){
		color = this.factoryObj.colorsArray[i];
		code =  this.factoryObj.colorCodesArray[i];
		var span = document.createElement('span');
		span.style.backgroundColor = code;
		span.name = code;
		span.title = color;
		span.style.fontSize = '14px';	
		var txt = document.createTextNode(String.fromCharCode(160) + String.fromCharCode(160) + String.fromCharCode(160));
		span.appendChild(txt);
		var colorClickFunction = function(evt){thisInstance.pickColor.call(thisInstance, evt);}		
		span.onclick = colorClickFunction;
		this.colorsBar.append(span);
	}	
}

//Make edit button with special click function 
JanYiiEditor.prototype.makeCustomEditBtn = function(image, title, clickFunction, cssClass, id){ 
	var buttonClass = 'editorimage';

	if(cssClass){
		buttonClass = cssClass;	
	}
	if(! id){
		var button = $( '<img class="' + buttonClass + '" SRC="' + this.factoryObj.editorImagePath + image + '" alt="' + image + '" title="' +  title + '">')
		.click(
			clickFunction
		);	
	}	
	else{
		var button = $( '<img id="' + id + '" class="' + buttonClass + '" SRC="' + this.factoryObj.editorImagePath + image + '" alt="' + image + '" title="' +  title + '">')
		.click(
			clickFunction
		);	
	}	
		
	return button;	
}

//Make edit button that uses std execCommand functions and add to its panel 
JanYiiEditor.prototype.addStdBtn = function(panel,image, text, cmd, val) {
	
	var thisInstance = this;
	var clickFunction = function(){thisInstance.stdButtonClick.call(thisInstance, cmd, val);}
	var button =  $('<img class="editorimage" SRC="' + this.factoryObj.editorImagePath + image + '" alt="' + text + '"' + 'title="' + text + '">').click(clickFunction);
	
    panel.append(button);
}


//-----------------------------  Respond to events  -----------------------------

//DOM Tree 
JanYiiEditor.prototype.domTree = function(){
	var isIE = false;
	if(jQuery.browser.msie)
		isIE = true;
		
	if(this.treeWin){
    	this.treeWin.close();	
    }	
    
   	this.treeWin = window.open("", "sub2", "height=500,width=500, resizable, scrollbars");	
   	this.treeWin.innerHTML = '';
	
	str = '<div align="center" style=" color:navy;	font-size: 10pt; font-family: Verdana, Arial, Helvetica, sans-serif;	"><b>' + 'DOCUMENT TREE' + '</b></div><p>';
	output = walkChildNodes(document.getElementById(this.id),0, isIE);
	output = '<table border="1" style="	font-size: 8pt; font-family: Verdana, Arial, Helvetica, sans-serif;	">' + output + '</table>';
	str += '<div style="	font-size: 8pt; font-family: Verdana, Arial, Helvetica, sans-serif;	">' + output + '</div>';

   this.treeWin.document.write(str);	
}	

//clear heading
JanYiiEditor.prototype.clearHeading =  function(){
	 text = this.getSelectedText();
	 
	 if(!text)
	 	return;
	elem = this.getSelectedNode();
	
	 if(elem){
	 	if(elem.tagName.toLowerCase() == 'h1' || elem.tagName.toLowerCase() == 'h2'){
	 		this.moveChildrenBeneathParent(elem, elem.parentNode);
			elem.parentNode.removeChild(elem);
	 	}
	 	else if(elem.tagName.toLowerCase() == 'h3'){
	 		this.moveChildrenBeneathParent(elem, elem.parentNode);
			elem.parentNode.removeChild(elem);
	 	}
	 }
}	

//Set text backgrounf color in IE
JanYiiEditor.prototype.setIEHighlight = function(color){
	if (document.selection) { 
		rangeObject = document.selection.createRange(); 
		rangeObject.execCommand('BackColor', false, color);
	}	
}	

//Testing function  
JanYiiEditor.prototype.test = function(){
	alert('Test');
}	


//A function to emulate certain exec command where these are not available
//Operation: FontSize (value = 1 to 7)
//Operation: FontName (value = font family)
JanYiiEditor.prototype.executeOperation = function(operation, value){
	
	if(!window.getSelection())
		return; //only support DOM Range which means for IE only IE9 or later

	//Get selection, extract content
	selection = window.getSelection().getRangeAt(0);
	fragment = selection.extractContents();
	
	//Create new fragment and copy old fragment to it applying a style to text noded
	newFragment = document.createDocumentFragment()
	this.copyFragmentApplyingStyle(fragment, newFragment, operation, value);
	
	//Delete old fragment and insert new one
	selection.deleteContents();
	selection.insertNode(newFragment);
}	

//Copy old fragnment to new fragment, applying style to text
JanYiiEditor.prototype.copyFragmentApplyingStyle = function(nodeRef, newNode, operation, value) {
  
   for(var i=0; i < nodeRef.childNodes.length; i++){

   		var clone = nodeRef.childNodes[i].cloneNode(false); //false = don't clone children
   		
		if(nodeRef.childNodes[i].nodeType == 3){
			//text node
			parent = nodeRef.childNodes[i].parentNode;
			
			if(operation.toLowerCase() == 'fontsize'){
				
				if(parent.tagName && parent.tagName.toLowerCase() == 'font'){
					//Text node already has span as parent
					newNode.appendChild(clone);
					clone.parentNode.size = value;
				}
				else{	
					//Create a span object above text node
					var font = document.createElement('font');
					font.size = value;
					font.appendChild(clone);
					newNode.appendChild(font);
				}	
			}
			else if(operation.toLowerCase() == 'fontname'){	
				if(parent.tagName && parent.tagName.toLowerCase() == 'span'){
					//Text node already has span as parent
					newNode.appendChild(clone);
					clone.parentNode.style.fontFamily = value;
				}
				else{	
					//Create a span object above text node
					var span = document.createElement('span');
					span.style.fontFamily = value;
					span.appendChild(clone);
					newNode.appendChild(span);
				}	
			}	
		}
		else		
   			newNode.appendChild(clone);
   		
   		
   		//process children	
		if(nodeRef.childNodes[i].childNodes.length > 0){
   			this.copyFragmentApplyingStyle(nodeRef.childNodes[i], clone);
   		}	
   } 
}


//Handle click on standard button
JanYiiEditor.prototype.stdButtonClick = function(cmd, val)
{
	if(cmd == 'foreColor' || cmd == 'hiliteColor'){
		if(! this.currentColorCode)
		{
			alert(this.t.SELECTED_COLOR_REQUIRED)
			return;
		}	
		val = this.currentColorCode;
	}
	
	if(cmd == 'hiliteColor' && jQuery.browser.msie){
		this.setIEHighlight(val);
		return;	
	} 	
		
	try{	
		document.execCommand(cmd, false, val);
	}
	catch(err){
		//Handle FF justification problem
		//This can occur when justifying the first para. 		 
		var justifyError = false;
		if(cmd == 'JustifyCenter'){
			justifyError = true;
		}
		if(cmd == 'JustifyRight'){
			justifyError = true;
		}
		if(cmd == 'JustifyLeft'){
			justifyError = true;
		}
		if(justifyError){
			alert(this.t.ERROR_JUSTIFYING_TEXT);
		}
	}	
}	


//Save the edited content
JanYiiEditor.prototype.saveContent = function(closingEditor){
	var ok = confirm(this.t.OVERWRITE_PUBLISHED_VERSION);	
	if(! ok)
		return;		
	
	//Clean up html	
	this.prepareServerSideHtml();	
	
	//Convert site urls and save content
	str = this.jqueryObj.html();
	str = this.convertSiteURL(str);	
	this.contentBeforeEditing = this.jqueryObj.html();
	//if(! closingEditor)
		//this.toggleEditMode();
	
	$.post(
     	this.updateUrl,
     	{Data: str, DataItemName: this.dataItemName, DataItemID: this.dataItemID,  DataModel : this.dataModel}, 
     	function(xml) {
     		status = $("Status", xml).text();
     		if(status){
     			alert(status);
     		}
     	}
     );
}

//Prepare HTML to be saved on server
JanYiiEditor.prototype.prepareServerSideHtml = function (){
	
	//Trim required to remove FF added tabs that then cause <PRE> to be inserted.
	var str = this.jqueryObj.html();
	str = jQuery.trim(str);
	this.jqueryObj.html(str);
	
	//Find empty node and if the last node is a p (paragraph) node 
	emptyParaArray = new Array();
	var nodeRef = document.getElementById(this.id);
	var lastPara = null; 
    for(var i=0; i < nodeRef.childNodes.length; i++){
		switch (nodeRef.childNodes[i].nodeType) {
   			case 1:	
				//Find p elements
				if(nodeRef.childNodes[i].tagName.toLowerCase() == 'p'){									
					if(nodeRef.childNodes[i].firstChild){
					lastPara = 	nodeRef.childNodes[i];		
					}
					else{
						//Collect empty p elements 		
						emptyParaArray.push(nodeRef.childNodes[i]);
					}
				}	
				else{
					//Not a p element,  so last node is not a para 
					lastPara = null; 
				}
				break;
			case 3:
				//This is a text node, so last node is not a para 
				lastPara = null; 
				break; 
			default: 	
		}
	}	
	//Remove empty p elements 
	for(var i=0; i < emptyParaArray.length; i++){
		try{		
			nodeRef.removeChild(emptyParaArray[i]);
		}
		catch(err){
		}	
	}
	
	//If last element a para remove it, but retain its child nodes 
	if(lastPara){
		while (lastPara.firstChild){
    		lastPara.parentNode.insertBefore(lastPara.firstChild, lastPara);
		}
		lastPara.parentNode.removeChild(lastPara);
	}	
}

//If siteUrlTag defined, then replace site url in string by tag 
JanYiiEditor.prototype.convertSiteURL = function (str){	
	if(this.factoryObj.siteUrlTag == undefined){
		return str;
	}
	var re = new RegExp(this.siteUrl, 'i');
	str = str.replace(re, this.factoryObj.siteUrlTag);
	var re = new RegExp('../../../','i');
	str = str.replace(re, this.factoryObj.siteUrlTag);
	return str;
}

//Insert image into content 
JanYiiEditor.prototype.insertImage = function (obj){
	var scale = this.scale.val();
	if(! this.isNumber(scale) || !(scale > 0) ){
		alert(this.t.ERROR_WITH_SCALE);
		return;
	}
	image = obj.name;
	style = "float:" + this.alignment.val() + "; "; 
	style = style + "margin-left:" + this.leftMargin.val()  + "px; ";
	style = style + "margin-right:" + this.rightMargin.val()  + "px; ";
	style = style +  "margin-top:" + this.topMargin.val()  + "px; ";
	style = style + "margin-bottom:" + this.bottomMargin.val()  + "px; ";
	id = 'jyimageid_' + image;
	
	var html = '<img id ="' + id + '" src="' + this.imageUrl + image + '" style="' + style + '"  name="' + image + '" title="'+ image + '" alt="' + image + '">';	
	this.pasteHtml(html);
	
	newObj = document.getElementById(id)
	if(newObj && scale != 100){
		var newHeight = newObj.height * (scale /100);
		var newWidth = newObj.width * (scale / 100);
		newObj.height = newHeight;
		newObj.width = newWidth;
	}
	 
	//This apparently redundant resetting of the image source keeps it in absolute url format.
	if(newObj){
		newObj.src = this.imageUrl + image;
	}	
}

//Save picked color
JanYiiEditor.prototype.pickColor = function(evt){

	evt = (evt) ? evt : ((window.event) ? window.event : null);
	if(evt){
		var elem = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null);
	}
	if(elem){
		 if(elem){
			 code = elem.name;
			 this.currentColorCode = code;
			 colorDisplayId = this.elementId + 'colordisplay';
			 if(this.currentColorCode != '#000000')
			 	document.getElementById(this.elementId + 'pickcolor').style.borderColor = this.currentColorCode;
			 else{
			 	document.getElementById(this.elementId + 'pickcolor').style.borderColor = '';	
			 }	
		}	 
	}
}

//Prepare link HTML, and then paste into editable content
JanYiiEditor.prototype.insertLink = function(linkInputBox ){
	var str = this.getSelectedText();
	var url = linkInputBox.val();
	var html = '';
	var emailLink = false;
	
	if(url == ''){	
		return;
	}	
	
	if(str == ''){	
		alert(this.t.LINK_REQUIRES_TEXT);
		return;
	}
	
	emailLink = this.looksLikeMail(url);
	
	if(emailLink && this.factoryObj.functionsArray.in_array('WarningOnEmailLink')){
		var ok = confirm(this.t.CONFIRM_EMAIL_LINK);	
		if(! ok)
			return;			
	}	
	
	if(emailLink)
		html =  '<a href="mailto:' + url + '">' + str + '</a>';
	else
		html = '<a href="' +  url + '">' + str + '</a>';
	
	this.pasteHtml(html);
}

//Prepare download link HTML, and then paste into editable content
JanYiiEditor.prototype.insertDownloadLink = function(inputList){
	var str = this.getSelectedText();
	var jid = '#' + this.elementId + '_download_list';
	var downloadID = $(jid).val();

	if(downloadID == ''){	
		alert(this.t.LINK_REQUIRES_SELECTION);
		return;
	}	
	
	if(str == ''){	
		alert(this.t.LINK_REQUIRES_TEXT);
		return;
	}
	
	var url = this.factoryObj.siteUrl + this.factoryObj.userDownloadLinkPath +	downloadID;
	
	var html = '<a href="' +  url + '">' + str + '</a>';
	this.pasteHtml(html);
}

//Prepare page link HTML, and then paste into editable content 
JanYiiEditor.prototype.insertPageLink = function(inputList){
	var str = this.getSelectedText();
	var jid = '#' + this.elementId + '_page_list';
	var route = $(jid).val();
	
	if(route == ''){	
		alert(this.t.LINK_REQUIRES_SELECTION);
		return;
	}	
	
	if(str == ''){	
		alert(this.t.LINK_REQUIRES_TEXT);
		return;
	}
	
	if(route.substring(0,1) == '/')
		route = route.substring(1); 
	
	var url = this.factoryObj.siteUrl  + route;
	
	var html = '<a href="' +  url + '">' + str + '</a>';
	this.pasteHtml(html);
}

//Take text in HTML input area, and then paste into editable content 
JanYiiEditor.prototype.pasteHtmlArea = function(inputArea){
	var html = inputArea.val();	
	if(html == '' || html == undefined){
		alert(this.t.NOTHING_TO_PASTE);
		return;
	}
	this.pasteHtml(html);
}

//General paste function for adding HTML to editable content 
JanYiiEditor.prototype.pasteHtml = function(html){
	
	//Code to handle FF and others not liking to insert into area with <p> tags stripped out.
	//This is a consequence of removing <p> tags from final para when there is only one para
	//and this is empty except for <br> tag. 
	var str = document.getElementById(this.id).innerHTML;
	if(str == '<br>' || str == ''){
		document.getElementById(this.id).innerHTML = '<p><br></p>';
		alert(this.t.RESELECT_INSERTION_POINT);
		return;
	}

	if(! this.selectedInRange(this.id, this)){ 
		alert(this.t.SELECTION_MUST_BE_IN_EDIT_AREA);
		return;
	}	
	
	text = this.getSelectedText();
	if(text == '' && jQuery.browser.opera ){
		alert(this.t.SELECTION_MUST_BE_IN_EDIT_AREA);
		return;
	}	
	
	
	try{
		if(!jQuery.browser.msie){
			document.execCommand("insertHTML", false, html); 
		}	
		else if(document.selection){
			//IE 
			var div = document.getElementById(this.id);
			div.focus();
			document.selection.createRange().pasteHTML(html);
		}	
	}
	catch(e){
	}
}	

//Show help page
JanYiiEditor.prototype.help = function(){	
	var newWindow = window.open(this.factoryObj.helpUrl, '_blank');
 	newWindow.focus();	  
}

//Clear all content
JanYiiEditor.prototype.clearAll = function(){	
	var ok = confirm(this.t.CLEAR_ALL_CONTENT);
	if(! ok){
		return;
	}
	document.getElementById(this.id).innerHTML = ' ';
	//var txt = document.createTextNode('');
	//document.getElementById(this.id).append(txt);
}

//Show the image bar 
JanYiiEditor.prototype.showImageBar= function(){
	this.showPanel(this.imageBar);
}

//Show the download bar 
JanYiiEditor.prototype.showDownloadBar= function(){
	this.showPanel(this.downloadBar);
}

//Show the download bar 
JanYiiEditor.prototype.showPageBar= function(){
	this.showPanel(this.pageBar);
}

//Show the link bar 
JanYiiEditor.prototype.showLinkBar= function(){
	this.showPanel(this.linkBar); 
}

//Show the colors bar 
JanYiiEditor.prototype.showColorsBar= function(){
	this.showPanel(this.colorsBar); 
}

//Show the paste bar 
JanYiiEditor.prototype.showPasteBar= function(){
	this.showPanel(this.pasteBar); 
}

//Restore the contenet of the editable area 
JanYiiEditor.prototype.restoreContent= function(){
	var ok = confirm(this.t.RESTORE_THE_CONTENT_TO_LAST_SAVED);
	if(! ok){
		return;
	}
	this.jqueryObj.html(this.contentBeforeEditing); 
}


//-----------------------------  Show and hide panels  -----------------------------

//Toggle between the editor being visible and it being hidden. 
JanYiiEditor.prototype.toggleEditMode = function(){
    switch(this.editingModeToggle){
    case true:
    	if(jQuery.browser.opera && this.firstTimeOpen){
			//alert(this.t.OPERA_REDUCED_FUNCTIONALITY);
			;
		}
		this.jqueryObj.get(0).contentEditable = true;
		document.getElementById(this.id).className = 'contentactive';	
		this.jqueryObj.css({background:"#eeeeee"});	
		this.toolBar.show('slow');
		$(this.editButton).attr('title','Hide Editor');
		this.editingModeToggle=false; 
		this.firstTimeOpen = false;
		break;
    case false:
		this.jqueryObj.get(0).contentEditable = false;	
		document.getElementById(this.id).className = 'contenteditable';
		this.jqueryObj.css('background-color',this.originalBackgroundColor);
		this.hideChildPanels();	
		this.toolBar.hide('fast'); 		
		$(this.editButton).attr('title','Edit Content');
		this.editingModeToggle=true;
		this.currentBar = null;
		
		if(this.contentBeforeEditing != this.jqueryObj.html() && this.factoryObj.functionsArray.in_array('Save'))
			this.saveContent(true);		
				
        break;
    } 
}

//Show a child panel 
JanYiiEditor.prototype.showPanel = function(bar){	
	this.hideChildPanels();
	if(bar != this.currentBar){
		this.toolBar.removeClass('toolbar');
		this.toolBar.addClass('toolbarwithchild');
		bar.show('slow')
		this.currentBar = bar;
	}	
	else{
		this.currentBar = null;
	}
}

//Hide all child panels 
JanYiiEditor.prototype.hideChildPanels = function(){
	this.imageBar.hide('fast');	
	this.downloadBar.hide('fast');	
	this.pageBar.hide('fast');
	this.linkBar.hide('fast');
	this.colorsBar.hide('fast');
	this.pasteBar.hide('fast');
	this.toolBar.removeClass('toolbarwithchild');
	this.toolBar.addClass('toolbar');
}


//-----------------------------  Utility Functions  -----------------------------

//Test is numeric 
//From : http://stackoverflow.com/questions/18082/validate-numbers-in-javascript-isnumeric
JanYiiEditor.prototype.isNumber = function(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

//Get selected text, if any 
//From: Kolich.Selector.getSelected function 
JanYiiEditor.prototype.getSelectedText = function(){
  var t = '';
  if(window.getSelection){
    t = window.getSelection();
  }else if(document.getSelection){
    t = document.getSelection();
  }else if(document.selection){
    t = document.selection.createRange().text;
  }
  return t;
}

//If selection test in range - this is to stop pasting into inappropriate areas
JanYiiEditor.prototype.selectedInRange = function(id, contentObj){
	var inRange = false;
	
	//var currentPasteLocation = getSelectionBoundaryElement(true);
	var currentPasteLocation = this.getSelectedNode();
	if(currentPasteLocation == null){
		return inRange;
	} 

	var rangeObject;
	
	if(this.getInternetExplorerVersion() == 9){
		inRange = true;
	}	
	else if (window.getSelection) {	
		//Not IE	
		var node = currentPasteLocation; 
		while(node){
			if(node.id == id){
				inRange = true;
			}
			node = node.parentNode; 
		}	
	}
	else if (document.selection) { 
		//IE pre 9
		//This test must come after the above so that Opera uses 'getSelection' 
		str = this.getSelectedText();
		if(str){
			//test within range
			rangeObject = document.selection.createRange(); 
			var parent = rangeObject.parentElement(); 
			while(parent){
				if(parent.id == id){
					inRange = true;
				}
				parent = parent.parentElement; 
			}
			inRange = true;
		}
		else{
			//Cannot test selection so treat as OK 
			inRange = true;
		}	
	}
	return inRange;
}

//Get the currently selected node 
JanYiiEditor.prototype.getSelectedNode = function(){
    if (document.selection){
        return document.selection.createRange().parentElement();
	}        
    else{
        var selection = window.getSelection();
        if (selection.rangeCount > 0){
                return selection.getRangeAt(0).startContainer.parentNode;
        }        
    }
}

//Get parent of selection
JanYiiEditor.prototype.getSelectionParentElement = function() {
    var parentEl = null;
    if (window.getSelection) {
        var sel = window.getSelection();
        if (sel.rangeCount) {
            parentEl = sel.getRangeAt(0).commonAncestorContainer;
            if (parentEl.nodeType != 1) {
                parentEl = parentEl.parentNode;
            }
        }
    } else if (document.selection && document.selection.type != "Control") {
        parentEl = document.selection.createRange().parentElement();
    }
    return parentEl;
}

//Warning on naviagting from page
JanYiiEditor.prototype.onbeforeunload = function (e){
	if(this.treeWin)
		this.treeWin.close();	
		
	if(this.factoryObj.functionsArray.in_array('WarningOnNavigatingFromPage')){
		if(this.contentBeforeEditing != this.jqueryObj.html() && this.factoryObj.functionsArray.in_array('Save'))
		{
			//Code to confirm that users wishes to navigate away and loose changes
			//Only works in FF and IE
			message = this.t.LOOSE_CHANGES_ONBEFOREUNLOAD
			e=e||window.event; 
			e.returnValue = message;
			return message;
		}	
	}		
	return false;
}	

//move children of node to beneath parent node
JanYiiEditor.prototype.moveChildrenBeneathParent = function(nodeRef, parentNodeRef){
  	while( nodeRef.childNodes.length > 0){
  		currentNode =  nodeRef.childNodes[0]				
  		parentNodeRef.insertBefore(currentNode,nodeRef);
   }
}

//Check if this string look like an email address 
JanYiiEditor.prototype.looksLikeMail = function(str) {
    var lastAtPos = str.lastIndexOf('@');
    var lastDotPos = str.lastIndexOf('.');
    return (lastAtPos < lastDotPos && lastAtPos > 0 && str.indexOf('@@') == -1 && lastDotPos > 2 && (str.length - lastDotPos) > 2);
}


/***************************************************************************
						Additions To Array Class
						
***************************************************************************/

//Add in_array function to array
Array.prototype.in_array = function(value) {
	for(var i = 0, l = this.length; i < l; i++) {
		if(this[i] == value) {
			return true;
		}
	}
	return false;
}

/***************************************************************************
	Document tree code taken from TA rich_content_script.js
						
***************************************************************************/

function walkChildNodes(nodeRef, n, isIE) {
   var output = '';
   var indent = "";
   var i, j;
   
    if (n) {
        for (i = 0; i < n; i++) {
            indent += "+---";
        }
    } 
  
   for( i=0; i < nodeRef.childNodes.length; i++){
   		
   		switch (nodeRef.childNodes[i].nodeType) {
   		 case 1:
   			output += '<tr><td >';
   			output += indent;
   			output +=  '<span style="color:navy;"><b>' + nodeRef.childNodes[i].tagName.toLowerCase() + '</b></span>';
   			output += '</td><td  style="color:green;">';
   			
   			output += (nodeRef.childNodes[i].id) ? " ID:" + nodeRef.childNodes[i].id : "";
            output += (nodeRef.childNodes[i].name) ? " Name:" + nodeRef.childNodes[i].name : "";
   			var attributes = nodeRef.childNodes[i].attributes;
   			var attributeData = '';
   			
   			if(attributes && ! isIE){
   				for(j=0; j < attributes.length; j++){
					obj = attributes[j];
					if(obj.value){
						if(attributeData){
							attributeData += ' ' +  obj.name + ':' + obj.value;
						}
						else{
							attributeData = ' Attributes ' +  obj.name + '=' + obj.value;
						}	
					}	
				}	
   			}
   			output += attributeData;
   			output += "&nbsp;</td></tr>";
   			//output += "<br>";
   			break;
   		 case 3:
   		 	output += '<tr><td>';
   		 	output += indent;
   		 	output += '<span style="color:navy;"><b>text</b></span> ';
   		 	output += '</td><td   style="color:green;">';
   		 	value = nodeRef.childNodes[i].nodeValue;
   		 	len = value.length;
   		 	if (len > 30) {
               value = value.substr(0,30) + "...";
            }
   		 	value = value.replace(/ /, '&nbsp;');
   		 	value = htmlspecialchars(value);
   		 	output +=  '"' + value + '"';
   		 	output += " " + len + ' chars';	
   		 	output += "&nbsp;</td></tr>";
   			//output += "<br>";
   		 	break;
   		 case 8:
   		 	output += '<tr><td>';
   		 	output += indent;
            output += '<span style="color:navy;"><b>comment</b></span>';
            output += '</td><td   style="color:green;">';
            output += "&nbsp;</td></tr>";
            //output += "<br>";
            break;   		 	
   		 default:
   		 	output += '<tr><td>';
   		 	output += indent;
   		 	output +=  '<span style="color:navy;"><b>other (type' + nodeRef.childNodes[i].nodeType + ')</b></span>';
   		 	output += '</td><td   style="color:green;">';
            output += "</td></tr>";
   		 	//output += "<br>";
   		 }	
   			
   		if(nodeRef.childNodes[i].childNodes.length > 0){
   			output +=  walkChildNodes(nodeRef.childNodes[i], n + 1);
   		}	
   }
   
   return output;
}

function htmlspecialchars(ch) {
	ch = ch.replace(/</g, "&lt;");
	ch = ch.replace(/>/g, "&gt;");
	ch = ch.replace(/{/g, "&#123;");
	ch = ch.replace(/}/g, "&#125;");
	return ch;
}	




