/*
	
    Copyright (c) 2010 JanYii Ltd (contact via http://www.janyii.com/)
	

*/  
  

/***************************************************************************
						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.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	
	
	//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]);	
    		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.downloadBar;						//The bar containing the download 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.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');
	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.makeLinkBar();
	this.linkBar.insertBefore(this.jqueryObj);
	this.linkBar.hide();
	
	this.makePasteBar();
	this.pasteBar.insertBefore(this.jqueryObj);
	this.pasteBar.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 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);};
	var saveButton = this.makeCustomEditBtn('editor_save.gif', this.t.SAVE, saveClickFunction);	
	var linkClickFunction = function(){thisInstance.showLinkBar.call(thisInstance);};
	var linkButton = this.makeCustomEditBtn('editor_link.gif', this.t.LINK, linkClickFunction);	
	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);
  	
  	if(jQuery.browser.opera){
		//alert(this.t.OPERA_REDUCED_FUNCTIONALITY);
		;
	}
	else{	
		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('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('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('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('Link'))    
	    this.toolBar.append(linkButton);
	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);  
}

//Make font list
JanYiiEditor.prototype.makefontList = function(){	
	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" 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;
	this.downloadBar = $('<div class="downloadbar"> &nbsp; <label for="downloads" > ' + this.t.DOWNLOAD_LINKS + '</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);
	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 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 link bar 
JanYiiEditor.prototype.makeLinkBar = function(){
	var thisInstance = this;
	this.linkBar = $('<div class="linkbar"><label for="'+ this.elementId +'_linkurl" >URL</label> (e.g. http://www.janyii.com) </div>');
	var linkInputBox = $('<input class="inputcontrol" size="40" 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 edit button with special click function 
JanYiiEditor.prototype.makeCustomEditBtn = function(image, title, clickFunction, cssClass){ 
	var buttonClass = 'editorimage';

	if(cssClass){
		buttonClass = cssClass;	
	}

	var button = $( '<img 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 buttonHtml =  '<img class="editorimage" SRC="' + this.factoryObj.editorImagePath + image + '" alt="' + text + '"' + 'title="' + text + '">'; 
	var button =$(buttonHtml).
    	click(function(){
    		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);
				}
			}
	    });
    panel.append(button);
}


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

//Save the edited content
JanYiiEditor.prototype.saveContent = function(){
	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();
	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;
	}	
}

//Prepare link HTML, and then paste into editable content
JanYiiEditor.prototype.insertLink = function(linkInputBox ){
	var str = this.getSelectedText();
	var url = linkInputBox.val();
	
	if(url == ''){	
		return;
	}	
	
	if(str == ''){	
		alert(this.t.LINK_REQUIRES_TEXT);
		return;
	}
	
	var 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);
}

//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;
	}	 
	
	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;
	}
	this.jqueryObj.html('');
}

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

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

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

//Sow 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:
		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; 
		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;
        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.linkBar.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;
        }        
    }
}


/***************************************************************************
						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;
}



