/*******************************************************************
 *		  Global JavaScript file for SimpleEditor
 * 
 *	website		: http://amix.dk/
 *	author		: Amir Salihefendic (amix@amix.dk)
 *					
 *******************************************************************/
 
/*******************************************************************
 *		 
 * IMPORTANT VARIABLES
 * This section explains some important variables that are going
 * to help you understand this script better.
 *					
 *******************************************************************/
/*
   SimpleEditor.browser: A variable that holds which browser the user is using
   this._txtArea: The unchanged textarea
   this._editorLayer: A layer (div) that we use to replace the textarea
   this._iFrame: The iFrame 
   this._editArea: A variable for the iFrame document (used to many thangs)
*/


/*******************************************************************
 *		 
 * GLOBAL
 * This is where the most important functions are
 *					
 *******************************************************************/

//\
// The main function to call. This function exchanges the textare with
// it's own editor control
//\
function SimpleEditor(textarea) {
	//Check if the browser is supported
	this.checkBrowser();
	
	//If the browser isn't set don't do anything
	if(SimpleEditor.browser == 'ie' || SimpleEditor.browser == 'mozilla') {
		this._txtAreaName = textarea; //Set a global _txtArea variable
		this.changeTextArea(); //Hides the textarea
		this.createLayerArea(); //Creates ta layer for the editor :]
		this.createToolbar(); //Create the toolbar
		this.createiFrame(); //Create the iFrame used by our editor
	}

} //END F SimpleEditor

//\
// Load the language scripts
//\
(function() {
	//Find head and the first script tag
	var head = document.getElementsByTagName('head')[0];

	//Create an script element 
	var script = document.createElement('script');
	
	//Set some code to javascript element
	script.src = GLOBAL_EDITOR_URL + GLOBAL_LANGUAGE + ".js";
	
	//Apend it to our head, before our first script_tag (I had some problems with this shit)
	head.appendChild(script);
})();


//\
// BROWSER DETECTION
//\
SimpleEditor.prototype.checkBrowser = function () {

	//Convert userAget to lowerCase (so we aren't effected by iE MsIE)
	var lowerUserAgent = navigator.userAgent.toLowerCase(); 
	
	//Check if the version of Internet Explorer is 5.5 or 6.0 (which are the two suported IE browsers)
	if((lowerUserAgent.indexOf('ie 5.5') != -1) || (lowerUserAgent.indexOf('ie 6.') != -1)) {
		SimpleEditor.browser = 'ie';
	}

	//Check if the version of Mozilla is over 1.3b
	if((lowerUserAgent.indexOf('gecko') != -1) && navigator.productSub > 20021201) {
		SimpleEditor.browser = 'mozilla';
	}

	//Last check if it safari or opera, if it is, drop them!
	if((lowerUserAgent.indexOf('safari') != -1) || (lowerUserAgent.indexOf('opera') != -1)) {
		SimpleEditor.browser = 'not_supported';
	}

} //END F checkBrowser


//\
// Function that loads the the CSS style file
//\
SimpleEditor.loadStyleFile = function () {
	url = GLOBAL_EDITOR_URL + 'simple_editor.css';
	document.write("<style type='text/css'>@import url(" + url + ");</style>");
	
} //END F loadStyleFile

SimpleEditor.loadStyleFile();


/*******************************************************************
 *		 
 * CHANGE THE TEXT AREA FUNCTIONS
 * This spot holds functions that exchange the textarea with our
 * own control
 *					
 *******************************************************************/

//\
// Function that changes the textarea with our own control
//\
SimpleEditor.prototype.changeTextArea = function() {
	this._txtArea = document.getElementById(this._txtAreaName); //Make a link to the textarea
	this._txtArea.style.display = 'none'; //Hide the textarea
} //END F changeTextArea

//\
// Function that creates MagicArea
//\
SimpleEditor.prototype.createLayerArea = function() {
    var editor = this;
	editor._editorLayer = document.createElement('div'); //Create the layer
	editor._txtArea.parentNode.insertBefore(this._editorLayer, this._txtArea); //Insert the layer
    
    if(editor._txtArea.form) {
        editor._txtArea.form.onsubmit = function() {
            editor._txtArea.value = editor.getHTML();
        };
    }

    window.onunload = function() {
        editor._txtArea.value = editor.getHTML();
    };
    
} //END F createMagicArea

//\
// Function that returns the HTML 
//\
SimpleEditor.prototype.getHTML = function () {
    var result = this._editArea.body.innerHTML;
    result = result.replace(/<br>/gi, "<bml:skip />");
    result = result.replace(/<span style="font-weight: bold;">(.*?)<\/span>/gi, "<bml:wow>$1</bml:wow>");
    result = result.replace(/<img.*?src=".*?amirs\/(.*?).gif".*?>/gi, '<bml:emoticon type="$1" />');
    result = result.replace(/<img.*?src="(.*?)".*?>/gi, '<bml:picture url="$1" />');
    result = result.replace(/<STRONG>(.*?)<\/STRONG>/gi, "<bml:wow>$1</bml:wow>");
    result = result.replace(/<P>(.*?)<\/P>/gi, "$1<bml:skip />");
    result = result.replace(/<a href="(.*?)">(.*?)<\/a>/gi, '<bml:link url="$1">$2</bml:link>');
    result = result.replace(/&nbsp;/g, ' ');
    return result;
}


//\
// Function that creates the iFrame
//\
SimpleEditor.prototype.createiFrame = function () {
	var editor = this;
	
	//Create the iFrame
	this._iFrame = document.createElement('iframe');
	this._iFrame.className = 'SE_global'; //Append a style to our iFrame
		
	this._editorLayer.appendChild(this._iFrame); //Insert the iFrame into the layer
	
	this.setWidthAndHeight(); //Set width and height of the iFrame
	this.setStyle(); //Set the style for the editor

	//Create a global of the iFrame document
	this._editArea = this._iFrame.contentWindow.document;
	
	//Write some HTML code to the iFrame
	this.writeCode(this.htmlCode());
	
	this.turnDesignMode(); //Turn the design mode on
	this.focus(); //Put the foucs on the iFrame

	SimpleEditor.addEvents (this._editArea, ['mousedown', 'mouseup', 'drag'],
	function (event) {
		return editor.editorEvent(SimpleEditor.browser == 'ie' ? editor._iFrame.contentWindow.event : event);
	});
	
} //END F createiFrame


//\
// Function that puts the design mode on
// (depends on what browser the user is using) 
//\
SimpleEditor.prototype.turnDesignMode = function () {
	if(SimpleEditor.browser == 'mozilla') {
		this._editArea.designMode = 'on';
	} 
	else {
		this._editArea.body.contentEditable = true;
	}
	return this._editArea;
} //END F turnDesignMode

//\
// Function that sets style for the editor
//\
SimpleEditor.prototype.setStyle = function () {
	//Mozilla has a thick border - we need to reduce it to 1px
	if(SimpleEditor.browser == 'mozilla') this._iFrame.style.borderWidth = "1px";
} //END F setStyle

//\
// Function that sets width and height for the iframe
//\
SimpleEditor.prototype.setWidthAndHeight = function () {
	this._iFrame.style.width = this._txtArea.style.width;
	this._iFrame.style.height = this._txtArea.style.height;
} //END F setWidthAndHeight

//\
// Function that writes some HTML to the iFrame
//\
SimpleEditor.prototype.htmlCode = function () {
	var html_code;

	html_code = '<html>\n<head>\n</head>\n<body>'; //Write the standard html tags
	//html_code += this._txtArea.value; //Write the current value of our textarea
	html_code += "</body>\n</html>"; //Close the html tags
	return html_code;
} //END F htmlCode

//\
// Function that writes some data to the editor
//\
SimpleEditor.prototype.writeCode = function(data) {
	this._editArea.open(); //Open data access
	this._editArea.write(data); //Write the passed data
	this._editArea.close(); //Close data access
} //END F HtmlCode


/*******************************************************************
 *		 
 * EDITOR RELATED FUNCTIONS
 * This class of functions holds functions that are related to
 * editor (iFrame) specific things
 *					
 *******************************************************************/

//\
// Functions that puts focus on the iFrame
//\
SimpleEditor.prototype.focus = function () {
	this._iFrame.contentWindow.focus(); //Put the focus on the iFrame	
} //END F focus


/*******************************************************************
 *		 
 * EVENT HANDLER FUNCTIONS
 * This spot holds event related functions
 *					
 *******************************************************************/
 
 //\
 // Function that adds an event to an element
 //\
 SimpleEditor.addEvent = function(element, action, func) {
   //Check if it's ie, if it is do it the IE style, else do it Mozilla style
	if (SimpleEditor.browser == 'ie') {
		element.attachEvent("on" + action, func);
	} else {
		element.addEventListener(action, func, true);
	}
	
} //END F addEvent


//\
// Functions that adds events :)
//\
SimpleEditor.addEvents = function(element, actions, func) {
	for(i = 0; i < actions.length; i++) {
		SimpleEditor.addEvent(element, actions[i], func);
	}
	
} //END F addEvents


//\
// Editor (iFrame document) handler - I to the Izzo :D
//\
SimpleEditor.prototype.editorEvent = function (ev) {
		
	//Loop all our buttons and see if the match up
	//the current text state in our iFrame document
	for(i = 0; i < this.buttons_list.length; i++) {
		var is_button = this.buttons_list[i][0];
		var is_it_exec = this.buttons_list[i][1];	
		
		//Check if it's a button
		if(is_button = 'button' && is_it_exec) {
			
			//Command
			var command = this.buttons_list[i][2];
			
			//Assign element
			var element = this.toolbarObject[command];
			
			//Run the command on our iFrame, to see if it's it
			if(this._editArea.queryCommandState(command)) {
				element.state = true;
				element.className = 'SE_buttonOnMouseDown';
			}
			else {
				element.state = false;
				element.className = 'SE_button';	
			}

		}
		
	} //end for
	
} //END F editorEvent


//\
// Function that does a command
//\
SimpleEditor.prototype.doCommand = function(cmd_id, UI, param) {
   //Focus our editor
   this.focus();
   
   //Exec the command
   if(cmd_id == "createlink") {
       if(SimpleEditor.browser == 'mozilla') {
           var url;
           if((url = prompt("URL", "http://"))) {
               this._editArea.execCommand(cmd_id, false, url);
           }
       }
       else {
           this._editArea.execCommand(cmd_id, true, param);
       }
   }
    else if(cmd_id == "insertimage") {
       if(SimpleEditor.browser == 'mozilla') {
           var url;
           if((url = prompt("URL", "http://"))) {
               this._editArea.execCommand(cmd_id, false, url);
           }
       }
       else {
           this._editArea.execCommand(cmd_id, true, param);
       }
    }
   else if(cmd_id == "insertsmile"){
       this._editArea.execCommand("insertimage", UI, param);
   }
    else 
       this._editArea.execCommand(cmd_id, UI, param);
   
} //END F doCoomand


 /*******************************************************************
 *		 
 * COLOR PALETTE FUNCTIONS
 * Functions that are with handling of the color palettte
 *					
 *******************************************************************/
//\
// Function that creates the colors palette
//\
SimpleEditor.prototype.createColorsPalette = function () {
	var editor = this; //Used for nesting

	//Create palette layer we use
	var paletteLayer = document.createElement('div');
		
	//Append a class to our layer
	paletteLayer.className = 'SE_palletteLayer';
	paletteLayer.style.display = 'none';
	
	//Kind of shitty they don't show the same offset :-(
	if(SimpleEditor.browser == 'mozilla') {
		offsetTop = 22;
		offsetLeft = 10;
	} else {
		offsetTop = 40;
		offsetLeft = 12;
	}

	
	//Get the forecolor button left placement
	var button_left = this.toolbarObject['forecolor'].parentNode.offsetLeft + offsetLeft;
	//Append the style to our pallete layer	
	paletteLayer.style.left = button_left + 'px';
		
	//Get the button top placement (which is the placement of our toolbarlayer)
	var button_top = this.toolbar.parentNode.offsetTop + offsetTop;
	
	//Append it to our pallete layer
	paletteLayer.style.top = button_top + 'px';
		
	//Create the fine colors
	paletteLayer.appendChild(this.createColorTable());
	
	this._editorLayer.appendChild(paletteLayer);

	//Assign a global	
	this.palleteLayer = paletteLayer;

} //END F createColorsPalette


//\
// Create the show color row
//\
SimpleEditor.prototype.createShowColorRow = function () {
	//Create a row
	var row = document.createElement('tr');
		
	//Create a column
	var column = document.createElement('td');
	
	//Append the start style
	column.className = 'SE_paletteShowColor';
	column.style.backgroundColor = '#ccc';
	
	//Set the default value
	column.innerHTML = 'Smile!';
		
	//Append column span
	column.colSpan = 8;
	
	row.appendChild(column);
	
	//Append a global
	this.columnColor = column;
	
	//return the row
	return row;
	
} //END F createShowColorRow

//\
// Create the table that has all the colors
//\
SimpleEditor.prototype.createColorTable = function () {
	var editor = this; //For nesting
	
	var table = document.createElement('table');	
	var tbody = document.createElement('tbody');
	
	table.appendChild(tbody);
	
	tbody.appendChild(this.createShowColorRow());
	
	var color_rows = new Array();
	
	color_rows[0] = ['happy','sceptical', 'pondering', 'annoying'];
	color_rows[1] = ['geek','cry', 'wink', 'sad'];
	color_rows[2] = ['hot','tongue', 'confused', 'what'];
	color_rows[3] = ['sleepy','surprised', 'computer', 'dunno'];
	color_rows[4] = ['rolling','dontsay', 'party', 'ill'];
	
	this.colorRows = color_rows;
	
	function appendEvents(element, i, j) {
			
		SimpleEditor.addEvent(element, 'mouseover', function () {
			var name = editor.colorRows[i][j];
			
			editor.columnColor.innerHTML = name;
			
		});

		SimpleEditor.addEvent(element, 'click', function () {
			//Assign Color
			var name = editor.colorRows[i][j];

			//Do the command on our "editor"
			var img_name = color_rows[i][j];
            var img_src = "SimpleEditor/smilies/" + img_name + "_smile.gif";
			editor.doCommand('insertsmile', false, img_src);

			//Hide and reset our forecolor button + our color palette
			editor.palleteLayer.style.display = 'none';
				
			//Assign the value aswell
			editor.palleteMouseOver = false;
				
			//Toolbar button forecolor
			editor.toolbarObject['forecolor'].className = 'SE_button';
			editor.toolbarObject['forecolor'].state = false;

		});
	}
	
	for(i = 0; i <= 4; i++) {
		var row = document.createElement('tr');
		
		for(j = 0; j < 4; j++) {
			var column = document.createElement('td');
		
            var img = document.createElement('img');
			var img_name = color_rows[i][j];
            img.src = "SimpleEditor/smilies/" + img_name + "_smile.gif";
           
			column.className = 'SE_paletteColorColumn';
            column.appendChild(img);
			appendEvents(column, i, j);
			
			row.appendChild(column);
		}

		tbody.appendChild(row);
	}

	tbody.appendChild(this.createCloseRow(this.palleteLayer, 8));
	
	return table;
	
} // END F createColorTable


//\
// Function that creates a close row..
//\
SimpleEditor.prototype.createCloseRow = function (element, span) {
	var editor = this; //Used for function nesting
	
	//Create row
	var row = document.createElement('tr');
	
	//Create column
	var column = document.createElement('td')
	
	//Append a class to our column
	column.className = 'SE_close';

	//Column span
	column.colSpan = span;
	
	//Append some text, that is international :]
	column.innerHTML = SimpleEditor.language_pack.buttons_text['close_layer'];
	
	//Append some events
	//Mouseover
	SimpleEditor.addEvent(column, 'mouseover', function () {
		column.className = 'SE_close_mouseOver';
	});

	//Mouseout
	SimpleEditor.addEvent(column, 'mouseout', function () {
		column.className = 'SE_close';
	});

	//Mousedown
	SimpleEditor.addEvent(column, 'mousedown', function () {
		column.className = 'SE_close_mouseDown';
	});

	//Mouse click
	SimpleEditor.addEvent(column, 'click', function () {
		//Hide and reset our forecolor button + our color palette
		editor.palleteLayer.style.display = 'none';
		
		//Assign the value aswell
		editor.palleteMouseOver = false;
		
		//Toolbar button forecolor
		editor.toolbarObject['forecolor'].className = 'SE_button';
		editor.toolbarObject['forecolor'].state = false;
			
		//Set the button back to normal
		column.className = 'SE_close';
	});

	
	row.appendChild(column);

	return row;
	
} //END F createCloseRow


/*******************************************************************
*		 
* TOOLBAR FUNCTIONS
* Functions that are toolbar oriented
*					
*******************************************************************/
 
 //\
 // Function that creates the toolbar
 //\
SimpleEditor.prototype.createToolbar = function () {
   	//We need this so we can access our editor in nested functions
   	SE_editor = this; 
   	
   	//Create the layer element
   	this.toolbar = document.createElement('div'); 
   	
   	//Append a style to the toolbar
   	this.toolbar.className = 'SE_toolbar';
   	
   	//Configure buttons
   	this.configButtons();
   	
   	//Create the buttons
   	this.createButtons();
   		
   	//Insert the toolbar inside magic area
   	this._editorLayer.appendChild(this.toolbar);	
   	
	//Create the color palette
	this.createColorsPalette();

} //END F createToolbar


//\
// Function that configures the buttons
//\
SimpleEditor.prototype.configButtons = function () {
	//Be sure that the name of your new button is the same as the name of the button
	//same goes if you are going to assign it a tooltip!
	
	// button[exec command, type, name, function, state]
	// exec command = is it supported by the browser, or is it a "homemade" function"
	
	//Bold button
   	var button_bold = new Array('button', true, 'bold', function(editor) {editor.doCommand('bold'); });
   	
	//Link button
	var button_link = new Array('button', false, 'link', function(editor) {editor.doCommand("createlink")});
	var button_image = new Array('button', false, 'image', function(editor) {editor.doCommand("insertimage")});
  	
	//Forecolor button
	var button_forecolor = new Array('button', false, 'forecolor', function(editor) { });

	 
  	//Seperator that seperates our buttons
   	var seperator = new Array('notbutton', false, 'seperator');
	
   	//Array of buttons - the order is how they are going to be showed in the toolbar!
   	this.buttons_list = new Array(button_bold, seperator, button_forecolor, seperator, button_link, seperator, button_image);
   
} //END F configButtons

//\
// Function that creates the table that holds our buttons
//\
SimpleEditor.prototype.createToolbarTable = function( ) {
	//Create the table element
	var table = document.createElement('table');
	
	//Set some properites
	table.border = '0px';
	table.cellSpacing = '0px';
	table.cellPadding = '0px';
	
	//Append the table on our toolbar	
	this.toolbar.appendChild(table);
		
	//Tbody is required by the great browser IE,...
	this.table_tbody = document.createElement('tbody');
	table.appendChild(this.table_tbody);

} //END F createToolbarTable


//\
// Function that creat the buttons
//\
SimpleEditor.prototype.createButtons = function() {
	var editor = this;
	
	//Create a table for our toolbar
	this.createToolbarTable();
	
	//Create a row
	var table_row = document.createElement('tr');

	//Apend our row to the tbody
	this.table_tbody.appendChild(table_row);

	//Create toolbar objects
	this.toolbarObject = new Object();
	
	//\
	// Ok, this is wierd, we _must_ place our create button inside a function
	// else it does not work (i.e. if you place the creation in the loop!)
	// Array count: used to see what buttons we are in, buttons_list[array_count]
	//\
	function createButton(element, button_tooltip, button_command, array_count) {
		var button_layer = null;
	
		//Create a layer for the button
		button_layer = document.createElement('div');
		
		//Append a alt text to our element
		button_layer.title = button_tooltip;

		//Append a id for the button
		button_layer.id = element;
		
		//Assign a state for the button (true if it's pressed, false if it ain't)
		button_layer.state = false;
			
		//Append a class to your element
		button_layer.className = 'SE_button';
				
		//Create a new img element
		var button_img = document.createElement('img');			 
		
		//Set the image source for our button
		button_img.src = GLOBAL_EDITOR_URL + 'images/' + GLOBAL_LANGUAGE + '/' + element + '.gif';
		
		//Set some default style to our button image
		button_img.className = 'SE_img';
			
		//Set the pictures width and height
		button_img.width = 20; button_img.height = 20;
			
		//Append our button to our button layer
		button_layer.appendChild(button_img);
				
		//On mouse over
		SimpleEditor.addEvent(button_img, 'mouseover', function () {
			
			//Check if the button isn't pressed (false)
			if(!button_layer.state) {
				//Passing by the element
				SimpleEditor.appendClass(button_layer, 'SE_buttonOnMouseOver');
			}
		});
		
		//On mouse out
		SimpleEditor.addEvent(button_img, 'mouseout', function () {

			//Check if the button isn't pressed (false)
			if(!button_layer.state) {
				//Passing by the element
				SimpleEditor.appendClass(button_layer, 'SE_buttonOnMouseOut');
			}

			//Special case for the forecolor button
			if(button_layer.id == 'forecolor') {
				if(editor.palleteMouseOver) {		
					//Keep it down
					SimpleEditor.appendClass(button_layer, 'SE_buttonOnMouseDown');
					button_layer.state = true;
				}
				else {
					//Reset the button
					SimpleEditor.appendClass(button_layer, 'SE_buttonOnMouseOut');
					button_layer.state = false;
				}
			}
			
		});
		
		//On mouse down	
		SimpleEditor.addEvent(button_img, 'mousedown', function () {
			
			//Check if the button isn't pressed (false)'
			if(!button_layer.state) {	
				//Passing by the element
				SimpleEditor.appendClass(button_layer, 'SE_buttonOnMouseDown');
				button_layer.state = true;
			} 
			//If the buttons pressed ...
			else {
				SimpleEditor.appendClass(button_layer, 'SE_button');
				button_layer.state = false;
			}
            
			
			//Special case for the list buttons!
			switch(button_layer.id) {
				case 'insertorderedlist':
					editor.toolbarObject['insertunorderedlist'].state = false;
					editor.toolbarObject['insertunorderedlist'].className = 'SE_button';
				break;

				case 'insertunorderedlist':
					editor.toolbarObject['insertorderedlist'].state = false;
					editor.toolbarObject['insertorderedlist'].className = 'SE_button';
				break;
			} //End switch

		});

		//On mouse click
		SimpleEditor.addEvent(button_img, 'click', function () {
			button_command(editor);
			
			//Special case for the forecolor button
			if(button_layer.id == 'forecolor') {
								
				//If it's clicked again reset the button'
				if(editor.palleteMouseOver) {
					editor.palleteMouseOver = false;
					editor.palleteLayer.style.display = 'none';
					
					//Reset the forecolor button
					SimpleEditor.appendClass(button_layer, 'SE_button');
					button_layer.state = false;
				} 
				else {
					editor.palleteLayer.style.display = 'inline';
					editor.palleteMouseOver = true;
				}

			}
            
            if(button_layer.id == "link") {
                editor.toolbarObject['link'].state = false;
                editor.toolbarObject['link'].className = 'SE_button';
            }
            
            if(button_layer.id == "image") {
                editor.toolbarObject['image'].state = false;
                editor.toolbarObject['image'].className = 'SE_button';
            }
		});
		
		return button_layer;	
	} //END F createButton
	   	
	// Here we go!
	// Loop the configurated buttons
	for(i = 0; i < this.buttons_list.length; i++) {
				
		//Check what kind of buttons we are making
		switch(this.buttons_list[i][2]) {
			
			//If the "button" is seperator
			case 'seperator':
				var button_layer = document.createElement('div');
				button_layer.className = 'SE_seperator';
			break;	
			
			//Else just run normal buttons
			default:
				var button_name = this.buttons_list[i][2];
				var button_tooltip = SimpleEditor.language_pack.tooltips[button_name];	
				var button_command = this.buttons_list[i][3];
				
				//This function is located here.. we can't place the code here
				//for some kinky reason! See that we also pass i -> else we can't find the buTTon :D
				button_layer = createButton(button_name, button_tooltip, button_command, i);

				//Create a object in our toolbarObjects
				this.toolbarObject[button_name] = button_layer;
			break;
		} //End switch
	
		//Create a column item for the button inside our toolbar table
		//To find table_row look at the top of this function
		var table_cell = document.createElement('td');
		table_cell.appendChild(button_layer);
		table_row.appendChild(table_cell);
						
	} //End loop creation buttons

} // END F createButtons


//\
// Append a class to an element
//\
SimpleEditor.appendClass = function (element, className) {
	element.className = className;
} //END F appendClass
