/**************************************************************
* iOkun Grouop LTD. GEdit TM <BAH!>
* 
* @author: Max Raskin
* @since:  16/04/2007
*
* REQUIREMENTS: js: rDom.js (raskin's dom manipulation namespace)
*				css: gedit_inner.css , gedit_inner_ie.css , gedit.css
*
* Last modified: 14/05/2007
*
*############################
* Usage (Explanations below):
*############################
*(1) a. js  to include: gedit.js, rajax.js, rdom.js
	 b. css to include: gedit.css
*(2) in your init function:
*    var gEdit = GEditAPI.create('myGEditId', 'myGEditContainerID',someContainerElementObject);
*	 gEdit.saveURL      = '?action=myajaxHandler';

*
* (3) To retrieve data in php:
*	  $html = XGEdit::decodeData();
*
*
* #############
* Explanations:
* #############
* (1) a. gedit.js is the core, rajax.js is our ajax layer, rdom is our DOM layer
*     b. gedit.css sets styles for the toolbar and the edit/save/cancel buttons
* (2) myGEditContainerID can be any element that display's style property set to
*	  					 'block'
*	  GEditAPI.saveURL   - this is url via the current server where saved data 
* 					  	   is sent to.
*	  someContainerElementObject - Any object that supports the appendChild() method,
*						   it doesn't have to be an element, it can be a custom object.
*								   - its our toolbar container
*
*  (3) Data sent as $_POST['data_html'] , to get it us XGEdit:decodeData();
*/


var dbg = null;
if(typeof rDebugConsole != 'undefined') {
	dbg = rDebugConsole;
}
var isIE = (navigator.userAgent.toLowerCase().indexOf("msie") > -1);


var GEditAPI = {
	
	/**
	 * @var int
	 * id of timer that updates toolbar buttons state
	 */
	updateToolbarTimerId : null,
	/**
	 * @var Array
	 * array of toolbar buttons elements of active gedit (used within updateToolbarState() )
	 */
	tbBtns : [],
	
	/**
	* @var string
	* css file to use for the document in the iframe
	*/
	cssFile : 'css/gedit_inner.css',
	
	/**
	* @var string
	* css file to use for the document in the iframe for use by IE
	*/
	cssFileIE : 'css/gedit_inner_ie.css',

	/**
	* @var string
	* the edit controls area class name
	*/
	cssEditControlsClass : 'editControls',
	
	/**
	 * A container for the loading animated gif
	 */
	loadingAnim : null,
	
	/**
	 * @var string
	 * the edit area container class name for hi-lighting
	 */
	cssEditAreaContainerClass : 'gEditAreaContainer',
	
	/**
	* @var string
	* the edit controls area class name set when editing
	*/
	cssEditControlsEditingClass : 'editControlsEditing',
	
	cssClassToolbarHlite : 'gedit-tbhlite',
	
	cssClassToolbarButton : 'gedit_tb_button',
	
	cssClassToolbar : 'gEditToolbar',
	
	tbIdFontPicker : null,
	tbIdColorPicker : null,
	
	/**
	* @var array
	* list of fonts
	*/
	fonts : ['Arial', 'Comic Sans MS', 'David', 'Georgia', 'Times New Roman', 'Tahoma', 'Verdana'],
	
	gEdit: null,
	
	/**
	* @var array
	* list of colors
	*/
	colors : ['Yellow', 'Red', 'Black', 'Blue', 'Green', 'Aqua', 'Brown', 'White','#F0F8FF','#FAEBD7','#00FFFF','#7FFFD4','#F0FFFF','#F5F5DC','#FFE4C4','#000000','#FFEBCD','#0000FF','#8A2BE2','#A52A2A','#DEB887',
	'#5F9EA0','#7FFF00','#D2691E','#FF7F50','#6495ED','#FFF8DC','#DC143C','#00FFFF','#00008B','#008B8B','#B8860B','#A9A9A9','#006400','#BDB76B','#8B008B',
	'#556B2F','#FF8C00','#9932CC','#8B0000','#E9967A','#8FBC8F','#483D8B','#2F4F4F','#00CED1','#9400D3','#FF1493','#00BFFF','#696969','#1E90FF','#D19275',
	'#B22222','#FFFAF0','#228B22','#FF00FF','#DCDCDC','#F8F8FF','#FFD700','#DAA520','#808080','#008000','#ADFF2F','#F0FFF0','#FF69B4','#CD5C5C','#4B0082',
	'#FFFFF0','#F0E68C','#E6E6FA','#FFF0F5','#7CFC00','#FFFACD','#ADD8E6','#F08080','#E0FFFF','#FAFAD2','#D3D3D3','#90EE90','#FFB6C1','#FFA07A','#20B2AA',
	'#87CEFA','#8470FF','#778899','#B0C4DE','#FFFFE0','#00FF00','#32CD32','#FAF0E6','#FF00FF','#800000','#66CDAA','#0000CD','#BA55D3','#9370D8','#3CB371',
	'#7B68EE','#00FA9A','#48D1CC','#C71585','#191970','#F5FFFA','#FFE4E1','#FFE4B5','#FFDEAD','#000080','#FDF5E6','#808000','#6B8E23','#FFA500','#FF4500',
	'#DA70D6','#EEE8AA','#98FB98','#AFEEEE','#D87093','#FFEFD5','#FFDAB9','#CD853F','#FFC0CB','#DDA0DD','#B0E0E6','#800080','#FF0000','#BC8F8F','#4169E1',
	'#8B4513','#FA8072','#F4A460','#2E8B57','#FFF5EE','#A0522D','#C0C0C0','#87CEEB','#6A5ACD','#708090','#FFFAFA','#00FF7F','#4682B4','#D2B48C','#008080',
	'#D8BFD8','#FF6347','#40E0D0','#EE82EE','#D02090','#F5DEB3','#FFFFFF','#F5F5F5','#FFFF00','#9ACD32'],
	
	instances : [],
	
	
	/**
	* @var object
	* Ref to editor element
	*/
	e		   : null,
	/**
	* @var object
	* Ref to editor's document object
	*/
	doc		   : null,
	
	/**
	* @var string
	* GEdit's ajax url, for requesting data from server
	*/
	XURL : '?admin=xgedit',
	
	/**
	* GEdit creation function
	*
	* @param string id - an identifier for the control
	* @parma string editAreaContainer - the container to encompass GEdit id
	* @parma object toolbarContainer - the container to encompass the toolbar
	*/
	create : function(id, editAreaContainer, toolbarContainer)
	{
		var o = new GEdit(id, editAreaContainer, toolbarContainer);
		GEditAPI.instances.push(o);
		return o;
	},
	
	
	/**
	* Borrowed from fck editor, simple concept tho, 
	* replaces &quot; &gt; &lt; and &amp; with their
	* character represantations within an encoded string
	*
	* @param string text - encoded string
	* @return string - decoded string
	*
	*/
	HTMLdecode : function(text)
	{
		if ( typeof( text ) != "string" ) {
			text = text.toString() ;
		}

		text = text.replace(/&amp;/g, "&").replace(
			/&quot;/g, "\"").replace(
			/&lt;/g, "<").replace(
			/&gt;/g, ">");

		return text;
	},
	
	saving : false,
	
	onLoadSaveFrame : function (geditId) {
		var f = $(geditId + '__saveForm');
		var saveFrameId = geditId + '__saveFrame';
		var i = $(saveFrameId);
		if (GEditAPI.saving) {
			GEditAPI.saving = false;
			f.submit();
		} else {
			if (i.contentDocument) {
				var d = i.contentDocument;
			} else if (i.contentWindow) {
				var d = i.contentWindow.document;
			} else {
				var d = window.frames[saveFrameId].document;
			}
			if (d.location.href == "about:blank") {
				return;
			}
			
			if (d.body.innerHTML == 'done') {
				GEditAPI.loadingAnim.style.display = 'none';
				overlay.hide();
			}
		}
		
	},
	
	/**
	* Sets HTML source of edit control
	* @param string text
	*/
	setHTML : function (text)
	{	
		if (GEditAPI.gEdit.doc.body !== null)
		{
			GEditAPI.gEdit.doc.body.innerHTML = text;
		}
		
	},
	
	/**
	* Gets HTML source of edit control
	*
	*/
	getHTML : function ()
	{
		/*
		// AutoConvert to xhtml (still in the making)
		this.xhtml = '';
		
		
		this.getXHTML(GEditAPI.gEdit.doc.body,ignoreDiv);
		if (in_array(this.gEdit.editAreaContainer.nodeName.toLowerCase(), ['span', 'a', 'b'])) {
			this.xhtml = this.xhtml.replace('div', 'span', 'gi');
		}
		
		return this.xhtml;
		*/
		
		return GEditAPI.gEdit.doc.body.innerHTML;
		
	},
	
	
	/** 
	 * Invalid html to valid XHTML converter
	 * tested on FF and MSIE
	 *
	 */
	getXHTML : function (el)
	{
		var inlineTags = ['br', 'input', 'img', 'meta', 'link'];
		var invalidAttrs = ['hideFocus', 'contentEditable', 'tabIndex', 'start', 'isMap', 'loop', 'hspace', 'vspace','disabled', 'noWrap'];
		var currTag = '';
			for (var i = 0; i < el.childNodes.length; i++)
			{
				if (el.childNodes[i].nodeType == 1) {
					var tag =  el.childNodes[i].nodeName.toLowerCase();
					
					currTag = tag;
					
					//alert(currTag);
					var attribs = el.childNodes[i].attributes;
							
					for (var a = 0; a < attribs.length; a++) {
						if (attribs[a].name.charAt(0) != '_' && attribs[a].value.length != 0 
							&& attribs[a].value != 'null' && !in_array(attribs[a].name,invalidAttrs)) {
							tag += ' ';	
							
							tag += attribs[a].name + '=' + '"' + attribs[a].value + '"';
							
						}
					}
					
					if (isIE) {
						// fix style attribute
						var fixTag = el.childNodes[i];
						var gs = function (s) {return rDom.getCurrentStyle(fixTag, s)};
						var style = '';
						if (gs('color')) {
							style = 'style="';
							style+= 'color: ' + gs('color') + ';';
						}
						if (gs('font-weight')) {
							if (!style.length)
								style = 'style="';
							style+= 'font-weight: ' + gs('font-weight') + ';';
						}
						
						if (gs('text-align')) {
							if (!style.length)
								style = 'style="';
							style+= 'text-align: ' + gs('text-align') + ';';
						}
						
						if (gs('font-style')) {
							if (!style.length)
								style = 'style="';
							style+= 'font-style: ' + gs('font-style') + ';';
						}
						
						if (style.length) {
							style += '"';
						}
						
						tag+= ' ' + style;
						alert(tag);
					}
			
					tag = rDom.trim(tag);
					
					this.xhtml += '<' + tag;
					
					
					if (!in_array(currTag, inlineTags)) {
						this.xhtml += '>\n';
					} else {
						this.xhtml += ' />';
					}
				
					
				} else {
					
					var tNode = el.childNodes[i].nodeValue;
					if (!in_array((tNode), ['\n', '\t', '', '\r'])) {
						this.xhtml += el.childNodes[i].nodeValue;
					}
				}

				this.getXHTML(el.childNodes[i]);
				
			
			}
		
			// Close all tags
			if (el.nodeType == 1 && el.parentNode) {
				
				var aTag = el.nodeName.toLowerCase();
				
				if (aTag != 'body' && !in_array(aTag, inlineTags)) {
					this.xhtml += '</' + aTag + '>\n';
				} 
			}
	},
	
	/**
	* Gets configuration setting.
	* Settings are actually hidden fields, set by GEdit.setConf()
    *
	* These fields are id'd in the following format:
	* Say our editor's id is mygEdit, and we set a setting called value,
	* its id will be: conf_mygEdit_value
	*
	* NOTE: this function automatically supplies the conf_id prefix
	*
	* @param string name - setting's name to get
	* @param string[optional] instId - force usage of this instance id
	* @return string|null on failure
	*/
	getConf : function(name, instId)
	{
		if (typeof instId == 'undefined') {
			instId = GEditAPI.gEdit.e.id;
		}
		
		var el = $('conf_' + instId + '_' + name);

		if (el) {
			return el.value;
		}
		return null;
	},
	
	/**
	* Sets css file for iframe document
	* @param string cssFile
	*/
	
	setCss : function(cssFile)
	{
		var link = GEditAPI.gEdit.doc.createElement('link');
		link.setAttribute('type', 'text/css');
		link.setAttribute('rel', 'stylesheet');
		
		var loc =  document.location.href;
		var i = loc.length - 1;
		while (loc.charAt(i) != '/' && i >= 0) {
			i--;
		}

		loc = loc.substring(0,i+1);
		link.setAttribute('href', loc + cssFile);
		var head = GEditAPI.gEdit.doc.getElementsByTagName('head')[0];
		if (head) {
			head.appendChild(link);
		}
		
	},
	
	/**
	* This function is called when the iframe finished loading
	* @param object el - DOM element of the iframe
	*
	*/
	doLoad : function(el)
	{
		
		// attempt to get value from configs
   		var value = this.getConf('value');
   		var container = $(this.getConf('container'));
   		
   		
   		// Set font size, font family and color of editArea to iframe
   		var editArea = $(container).$('.editArea');
   		 
		this.gEdit.doc = (el.document) ? el.contentWindow.document : el.contentDocument;
		
		
		// Inner css file
   		if (isIE) {
   			var sSheet = this.gEdit.doc.createStyleSheet();
			sSheet.addRule('P', 'margin:0 !important;');
   			this.setCss(this.cssFileIE);
   		} else {
   			this.setCss(this.cssFile);
   		}
		
		
   		var body = this.gEdit.doc.body;
		if (body) {
			
		   		body.style.fontSize   = rDom.getCurrentStyle(editArea,'font-size');
		   		
		   		body.style.color 	  = rDom.getCurrentStyle(editArea,'color');
		   		body.style.fontFamily = rDom.getCurrentStyle(editArea,'font-family');
		   		body.style.fontWeight = rDom.getCurrentStyle(editArea,'font-weight');
		   		body.style.textAlign = rDom.getCurrentStyle(editArea,'text-align');
		   		body.style.direction = rDom.getCurrentStyle(editArea,'direction');
		   		body.style.padding = '0';
		   		body.style.margin = '0';
		}
   		
   		
   		el.style.width = '100%';
   		
   		var height = 200;
   		
   		if (this.gEdit.editAreaContainer.offsetHeight) {
   			height = this.gEdit.editAreaContainerHeight;
   		}
   		
   		/*if (isIE) {
   			height = editArea.parentNode.offsetHeight;
   		} else {
   			height = parseInt(rDom.getCurrentStyle(editArea.parentNode,'height'));
   		}*/
   		
   		try {
   			el.style.height = height + 'px';
   		} catch(e) {}
		
   						
   		
   		if (value !== null) {
   			this.setHTML(this.HTMLdecode(value));
   		}
   		
  
   		this.gEdit.doc.designMode = 'On';
   		//rDom.addEvent(this.gEdit.doc, 'keypress', this.onEditKeyPress);
   		//rDom.addEvent(this.gEdit.doc, 'click', this.onEditMouseClick);
   		
	},
		
	/**
	* Updates toolbar button states
	*/
	updateToolbarState : function () {
		
		if (!GEditAPI.tbBtns.length) {
			// Update button states
			rDom.getElementsByClassName(GEditAPI.gEdit.tb, GEditAPI.cssClassToolbarButton, GEditAPI.tbBtns);
		}
		
		var skipButtons = {'createlink' : 1, 'unlink' : 1, 'insertimage' : 1}
		
		for (var i=0; i<GEditAPI.tbBtns.length; i++) {
			// tmp[0] is the button's action
			var tmp = GEditAPI.tbBtns[i].id.split ('___');
			
			
			if (skipButtons[tmp[0]] !== 1) {
				if (GEditAPI.gEdit.doc.queryCommandState(tmp[0])) {
					GEditAPI.tbBtns[i].style.backgroundColor = 'rgb(100,201,232)';
				} else {
					GEditAPI.tbBtns[i].style.backgroundColor = '#E4E4E4';
				}
			}
		}
		
		var l = GEditAPI.gEdit.doc.queryCommandValue('createlink');
		// Update font picker state
		var fontName = GEditAPI.gEdit.doc.queryCommandValue('fontname');
		if (fontName != '') {
			GEditPopup.setText(fontName,GEditAPI.tbIdFontPicker);
		}
		
	},
	
	getToolbarButton : function(name) {
		
		return $(name.toLowerCase() + '___' + GEditAPI.gEdit.id);
	},
	
	/**
	* Executes MIDAS/HTML command
	* @param string 		  name - command name
	* @param string[optional] arg  - command argument
	*/
	execCommand : function(name,arg)
	{
		GEditAPI.gEdit.doc.execCommand(name,false,arg);
		GEditAPI.gEdit.focus();
	},
	
	/**
	* Event: Click
	* Fired by: binary toolbar button event (bold/italic/underline/justifyX)
	* 
	*/
	tbOnBtn : function (ev)
	{
		var action = GEditAPI.getActionFromEvent(ev);
		
		switch(action)
		{
			case 'createlink':
			{
				// todo - replace with divWindow
				var arg = prompt(gEditLang.enterURL, '');
				if (arg) {
					if (arg.substring(0, 7) != 'http://') {
						arg = 'http://' + arg;
					}
					GEditAPI.execCommand(action,arg);
				}
				GEditAPI.gEdit.focus();
				break;
			}
			case 'insertimage':
				GEditWndInsertImage.show();
				break;
			default:
				GEditAPI.execCommand(action);
		}
		
		
		GEditAPI.updateToolbarState();
		rDom.stopEvent(ev);
	},
	
	/**
	* Event: Click
	* Fired by: select box (font/fontsize/colors)
	* 
	*/
	tbOnSelChange : function (ev)
	{
		var selBox = rDom.getTarget(ev);
		GEditAPI.execCommand(GEditAPI.getActionFromEvent(ev),
							selBox.value);
		rDom.stopEvent(ev);
	},

	/**
	* Event: Click
	* Fired by: when clicking on cancel in the gEdit's container control box bar
	* @param object ev
	*/
	onControlCancel : function(ev)
	{
		GEditAPI.onControlSave.apply(GEditAPI.gEdit,[ev,true]);
		//GEditAPI.onControlSave(ev,true);
	},
	
	/**
	* Event: Click
	* Fired by: when clicking on save in the gEdit's container control box bar
	* @param object ev
	* @param bool[optional]dontSave (defaults to false)
	*		 - if true skips saving procedure but hides Save Changes button and destroys
	*		   the cancel button
	*/
	onControlSave : function(ev, dontSave)
	{
		if (rAjax.getNumBusyXhrs == rAjax.maxConns) {
			alert('המערכת טרם סיימה לשמור מידע קודם, אנא המתן...')
			return false;
		}
		// MSIE <a> element iframe container fix restore
		if (isIE) {
			var p = this.editAreaContainer.parentNode;
			while (p !== null) {
				
				if (p.nodeName.toLowerCase() == 'a') {
					p.href = this.aHref;
					break;
				}
				p = p.parentNode;
			}
		}
			
		clearInterval(GEditAPI.updateToolbarTimerId);
		GEditAPI.tbBtns = [];
		GEditAPI.updateToolbarTimerId = null;
		
		//rDom.removeEvent(GEditAPI.gEdit.doc, 'keypress', GEditAPI.onEditKeyPress);
   		//rDom.removeEvent(GEditAPI.gEdit.doc, 'click', GEditAPI.onEditMouseClick);
   		
   		// Remove cancel button
   		var btn = GEditAPI.gEdit.cancelControlButton;
   		rDom.toggleDisplay(btn.el.parentNode);
   		rDom.removeEvent(btn.el, 'click', btn.handlerFunc);
		btn.el.parentNode.removeChild(btn.el );
	
		
		rDom.cssClassRemove(GEditAPI.gEdit.editControls, 'editControlsEditing');
		GEditAPI.gEdit.isEditing = false;
		
		if (typeof dontSave == 'undefined') {
			GEditAPI.gEdit.save();
			// change from save to edit
			
			GEditAPI.gEdit.editArea.innerHTML = GEditAPI.gEdit.getHTML();
			// check this out
			//alert(GEditAPI.gEdit.getHTML());
			//alert(GEditAPI.gEdit.editArea.innerHTML);
		}
		
		GEditAPI.gEdit.hide();
		GEditAPI.gEdit.toggleEditArea();		
		
		var a = GEditAPI.gEdit.saveControlButton.el;
		

		
		rDom.stopEvent(ev);
	},
	
	getActionFromEvent : function (ev)
	{
		return rDom.getTarget(ev).id.split('___')[0];
	},
	
	getIdFromEvent : function (ev)
	{
		return rDom.getTarget(ev).id.split('___')[1];
	},

	/**
	* Right click on a editable element will activate editing mode
	*
	*/
	onContainerRightClick : function(ev) {
				
		// NOTE: this is current active gedit control
		
		// Cancel any editing in any other instance of gedit
		if (GEditAPI.gEdit !== null && GEditAPI.gEdit.id != this.id) {
			if (GEditAPI.gEdit.isEditing) {
				
				GEditAPI.onControlCancel(null);
			}
		}
		GEditAPI.gEdit = this;
		
		
		/*
		 MSIE <a> iframe container fix
		*/
		
		if (isIE) {
			var p = this.editAreaContainer.parentNode;
			while (p !== null) {
				
				if (p.nodeName.toLowerCase() == 'a') {
					this.aHref = p.href;
					var a = document.createElement('a');
					for (var i = 0 ; i < p.childNodes.length; i++) {
						a.appendChild(p.childNodes[i]);
					}
					p.parentNode.insertBefore(a,p);
					p.parentNode.removeChild(p);
					break;
				}
				p = p.parentNode;
			}
		}
		
		// Start updating toolbar
		if (GEditAPI.updateToolbarTimerId == null) {
			GEditAPI.updateToolbarTimerId = setInterval(GEditAPI.updateToolbarState,500);
		}
		
		
		rDom.removeEvent(rDom.getTarget(ev), 'contextmenu', GEditAPI.onContainerRightClick);
		
		this.isEditing = true;
		
		if (!this.isCreated()) {
			this.value = this.editArea.innerHTML;
			this.create('editorBody');
		} else {
			this.setHTML(this.editArea.innerHTML);
		}
		
		
		this.cancelControlButton = 
					this.createControlButton(gEditLang.cancel,
					'cancel', GEditAPI.onControlCancel);
		
		this.show();
		this.toggleEditArea();		
		
		this.editControls.style.display = 'block';
		
		
		if (this.toolbarOwner && !this.isToolbarCreated()) {
			this.toolbarOwner.appendChild(this.createToolbar(GEditAPI.cssClassToolbar));
		}
		
		rDom.cssClassAdd(this.editControls, GEditAPI.cssEditControlsEditingClass);
		
		
		rDom.stopEvent(ev);
		this.focus();
	}
};

/*********************************
* iOkun Group LTD. GEdit object
* WYSIWG editor for Mozilla/MSIE
*
* @author Max Raskin
* @since 15/04/2007
*
*  Last modified: 29/04/2007
*/

/**
* GEdit Constructor
* Say BAH?!
* @param string id - set editor element's id
* @param[optional]  object|string editAreaContainer - element to attach to -
*		  MUST contain an element classified as 'editArea'
*/
function GEdit(id, editAreaContainer, toolbarOwner)
{
	this.editAreaContainer = editAreaContainer;
	
	if (typeof editAreaContainer == 'string') {
		this.editAreaContainer = $(editAreaContainer);
	}	
	
	this.editAreaContainerHeight = this.editAreaContainer.offsetHeight;
	
	rDom.cssClassAdd(this.editAreaContainer, GEditAPI.cssEditAreaContainerClass);
	
	// CSS class name for editor element
	this.cssDivEditorClass = 'gEdit';
	
	// Editor reference (iframe)
	this.e = null;
		
	/**
	* @var string
	* stores editor identifier
	*/
	this.id = id;
	
	/**
	* @var object
	* stores a ref the container gEdit is attached to
	* using attachTo() method
	*/
	this.c = null
	
	/**
	* @var object
	* stores a ref the edit area gEdit is attached to (a container with 
	* the 'editArea' class) using attachTo() method.
	*/
	this.editArea = null;
	
	/**
	* @var object
	* stores a ref the edit controls area in the container gEdit 
	* is attached to (a container with 
	* the 'editArea' class) using attachTo() method.
	*/
	this.editControls = null;
	
	
	/**
	* @var object
	* stores ref to the edit/save change anchor button within the edit controls
	* area.
	*/
	this.editButton = null;
	
	/**
	* @var object
	* store toolbar div ref
	*/
	this.tb = null;
	
	/**
	* @var string
	* initial html source of editor
	*/
	this.value = '';
	
	/**
	* @var object
	* toolbar owner element or object, must support the appendChild() method
	*/
	this.toolbarOwner = toolbarOwner;
	
	/**
	* @var string
	* ajax server side save hander - will recieve data using POST['html_data']
	*/
	this.saveURL = null;
	
	this.eventOnEdit = null;
	this.eventOnSave = null;
	
	this.isEditing = false;
	
	if (this.editAreaContainer !== null) {
		if (this.attachTo(this.editAreaContainer)) {
			this.value = this.editArea.innerHTML;
		}
		
		rDom.addEvent(this.editAreaContainer,'contextmenu', GEditAPI.onContainerRightClick, this);
		
	}
	
	
}

/**
* 
* @param  object|string editAreaContainer -
*		  container of the element classified as 'editArea'
* @return bool
*/
GEdit.prototype.attachTo = function(editAreaContainer)
{
	
	if (typeof editAreaContainer == 'string')
	{
		this.c = $(editAreaContainer);
	}
	else if (typeof editAreaContainer == 'object')
	{
		this.c = editAreaContainer;
	}
	else {
		return false;
	}
	
	var arr = new Array();
	rDom.getElementsByClassName(this.c, 'editArea', arr);
	
	
	if (arr[0]) {
		this.editArea = arr[0];
	} else {
		var tmp = document.createElement('div');
		tmp.className = 'editArea';
		this.editArea = tmp;
		this.editArea.innerHTML = this.c.innerHTML;
		this.c.innerHTML = '';
		this.c.appendChild(tmp);
		
	}
	
	this.editControls = document.createElement('div');
	this.editControls.className = GEditAPI.cssEditControlsClass;
	
	this.toolbarOwner.appendChild(this.editControls);
	
	this.saveControlButton 	  = this.createControlButton(gEditLang.saveChanges, 'save', GEditAPI.onControlSave,true);
	
	this.setConf('container', editAreaContainer.id);
	
	return true;
}

/**
* Creates a control button (anchor) in the control box 
* (css class = 'editControls' by default)
* @param string text - button's text
* @param string name - button's name to be used in the internal id
* @param function handlerFunc - event handler function
*
* @return hash (associative array) - btn[text,name,handlerFunc,el = the DOM node of the anchor)
*/
GEdit.prototype.createControlButton = function(text, name, handlerFunc) {
	
	var a  = rDom.createEl('a', text);
	
	a.setAttribute('id', name + '___' + this.id);
	a.setAttribute('href', '#');
		
	rDom.addEvent(a, 'click', handlerFunc, this);
	
	this.editControls.appendChild(a);
	
	var btn = [];
	btn['text'] = text;
	btn['name'] = name;
	btn['handlerFunc'] = handlerFunc;
	btn['el']	= a;
	return btn;
}


/**
* Creates a new editor
* @param string[optional] cssBodyClass - class name to of which to set the
	*										 editor's body
* @return DOM object or null on failure
*
*/
GEdit.prototype.create = function()
{
	if (this.e !== null) return null;
	
	GEditAPI.gEdit = this;
	
	this.e = document.createElement('iframe');
	this.e.className = 'gEdit';
	this.e.setAttribute('id', this.id);
	this.e.setAttribute('src', 'about:blank');
	this.e.style.backgroundColor = 'transparent';
		
	
	if (this.value != '')
	{
		this.setConf('value', this._HTMLEncode(this.value));
	}
	
	
	
	var onLoadIframe = function (ev) {
		if (isIE) {
			this.e.setAttribute('allowTransparency','true');
		}
		
   		GEditAPI.el = rDom.getTarget(ev);
   		GEditAPI.doLoad(this.e);
   		  		
   		setTimeout(function(){GEditAPI.gEdit.focus();}, 100);
		rDom.stopEvent(ev);
	}


	rDom.addEvent(this.e, 'load', onLoadIframe, this);
	
	if (this.c !== null) this.c.appendChild(this.e);
	
	return this.e;
}

GEdit.prototype.isCreated = function()
{
	return (this.e !== null);
}

/**
* Sets configuration setting.
* Settings are actually hidden fields.
*
* These fields are id'd in the following format:
* Say our editor's id is mygEdit, and we set a setting called value,
* its id will be: conf_mygEdit_value
*
* NOTE: this function automatically supplies the conf_id prefix
*
* @param string name - setting's name to get
* @param string value - setting's value
* @return string|null on failure
*/
GEdit.prototype.setConf = function(name, value)
{
	var confEl = document.createElement('input');
	confEl.setAttribute('id','conf_' + this.id + '_' + name);
	confEl.setAttribute('type','hidden');
	confEl.setAttribute('value',value);
	
	document.body.appendChild(confEl);
}

/**
* Gets element's DOM object 
* even though, its returned by create()
* but, who knows...
* 
* @return object
*/
GEdit.prototype.getNode = function()
{
	return this.e;
}

/**
* Sets editor's html source
*
*/
GEdit.prototype.setHTML = function(html)
{
	GEditAPI.setHTML(html);
}

GEdit.prototype.toggleEditArea = function()
{
	rDom.toggleDisplay(this.editArea);
}

/**
* Gets editor's html source
*
*/
GEdit.prototype.getHTML = function()
{
	return GEditAPI.getHTML();
}

/**
* Hides editor using css's display property
*
*/
GEdit.prototype.hide = function()
{
	this.e.style.display = 'none';
	if (this.tb !== null) this.tb.style.display = 'none';
}

/**
* Shows editor using css's display property
*
*/
GEdit.prototype.show = function()
{
	this.e.style.display = 'block';
	if (this.tb !== null) this.tb.style.display = 'block';
}

GEdit.prototype.save = function()
{
	if (this.saveURL === null) {
		return null;
	}
	overlay.show();
	
	/****
	 * Saving is perfromed thusly:
	 * 1. an invisible iframe is created per gedit instance and appended to document's body.
	 * 2. an invisible form with its target attribute set to that iframe's name is created
	 *    with one hidden field, that form is then appended to document's body.
	 * 3. the gedit html data is set as the value of that hidden field and then
	 *    the form is submitted.
	 *
	 */
	var iframeId = this.id + '__saveFrame';
	var formId	 = this.id + '__saveForm';
	if (!GEditAPI.loadingAnim) { // create loading anim if not created yet
		GEditAPI.loadingAnim = document.createElement('div');
		GEditAPI.loadingAnim.innerHTML = '<img src="imgs/loading.gif" style="position:fixed;left:10px;top:10px;z-order:9999;float:left;z-index:9999;" />';
		document.body.appendChild(GEditAPI.loadingAnim);
		if (rDom.getCurrentStyle(GEditAPI.loadingAnim,'position') != 'fixed') {
			GEditAPI.loadingAnim.style.position = 'absolute';
			GEditAPI.loadingAnim.style.float	= 'left';

			var fixAnimPos = function () {
				
				GEditAPI.loadingAnim.style.top  =  (document.documentElement.scrollTop + 10) + 'px';
				GEditAPI.loadingAnim.style.left =  '10px';
			}
			fixAnimPos();
			setInterval(fixAnimPos, 100);
		}
	} else { // hide loading anim
		GEditAPI.loadingAnim.style.display = 'block';
	}
	if (!$(iframeId)) {
		// create save iframe for this gedit's instance
		
		var d = document.createElement('div');
		d.innerHTML = '<iframe style="display:none" src="about:blank" id="'+iframeId+'" name="'+iframeId+'" onload="GEditAPI.onLoadSaveFrame(\''+this.id+'\')"></iframe>';
		document.body.appendChild(d);
		
		
		var d2 = document.createElement('div');
		
		d2.innerHTML = '<form style="display:none" method="post" id="' + formId +'" target="' + iframeId +'" action="' + this.saveURL + '">' +
						'<input type="hidden" name="data_html" /></form>';
		d2.firstChild.firstChild.value = this.getHTML();
		document.body.appendChild(d2);
		GEditAPI.saving = true;
	} else {
		$(formId).firstChild.value = this.getHTML();
		$(formId).submit();
	}
	
}

/**
* Creates a toolbar button and returns it
*
* @param string text
* @param string id
* @param string tooltip
* @param function func - event handler function, by convention
*						functions will be in the GEditAPI namespace,
*						and will be formatted: tbOn<Action>
*						i.e. GEditAPI.tbOnBold for on bold action
*/
GEdit.prototype.createToolbarButton = function(text,id,tooltip,func,cssClass)
{
	var btn = document.createElement('input');
	
	// Each button's id shall contain a the editor's id too
	// so a reference can be made from within its event handler
	btn.setAttribute('id', id + '___' + this.id);
	btn.setAttribute('type','button');
	
	if (tooltip !== null) {
		btn.setAttribute('title',tooltip);
	}

	if (cssClass === null) {
		cssClass = '';
	} else {
		cssClass += ' ';
	}
	
	cssClass += ' ' + GEditAPI.cssClassToolbarButton;
	
	btn.setAttribute('value',text);
	btn.className = cssClass;
		
	rDom.addEvent(btn,'click',func);
	
	
	return btn;
}

/**
* Creates font name box
* @return object - select box element
*/
GEdit.prototype.createFontBox = function()
{
	var pickerBox = rDom.createEl('select');
	pickerBox.appendChild(rDom.createEl('option', gEditLang.pickAFont));
	pickerBox.className = 'gEditPickerBox';
	//attach : function (id,owner,className, items) {
	GEditAPI.tbIdFontPicker = GEditPopup.attach('fontname',pickerBox, 'gEditFontPicker', GEditAPI.fonts);
	
	return pickerBox;
}

/**
* Creates font size box
* @return object - select box element
*/
GEdit.prototype.createFontSizeBox = function()
{
	var sel = document.createElement('select');
	sel.setAttribute('id', 'fontsize___' + this.id);
	
	sel.appendChild(rDom.createEl('option',gEditLang.fontSize));
	
	for (var i = 1; i <= 7; i++)
	{
		var opt = rDom.createEl('option',i);
		opt.setAttribute('value',i);
		sel.appendChild(opt);
	}
	
	rDom.addEvent(sel,'change',GEditAPI.tbOnSelChange)
	return sel;
}

GEdit.prototype.focus = function()
{
	//this.e.focus();
	wnd = (this.e.contentWindow) ? this.e.contentWindow : this.e.window;
	if (wnd) wnd.focus();
}

/**
* Creates forecolor select box
* @return object - select box element
*/
GEdit.prototype.createForeColorBox = function()
{
	var pickerBox = rDom.createEl('select');
	pickerBox.appendChild(rDom.createEl('option', gEditLang.pickAColor));
	pickerBox.className = 'gEditPickerBox';
	//attach : function (id,owner,className, items) {
	tbIdColorPicker =  GEditPopup.attach('forecolor',pickerBox, 'gEditColorPicker', GEditAPI.colors, true);
	return pickerBox;
}
/**
* Creates a toolbar and returns its container (div)
* @param  string[optional] cssClass - class for the div
* @return object
*/
GEdit.prototype.createToolbar = function(cssClass)
{
	var tb = document.createElement('div');

	if (cssClass !== null)
		tb.className = cssClass;

	tb.setAttribute('id', 'toolbar___' + this.id);

	// The following buttons are binary state buttons,
	// which means - two states, on or off, basically,
	// their action's name is kept within the id of the button
	// for instance, if a button's action is bold and the instance id is gEdit
	// then the button id will be gEdit___bold
	// each of these buttons have one common event handler
	
	// B/U/I
	tb.appendChild(this.createToolbarButton('', 'bold', 
											gEditLang.bold, GEditAPI.tbOnBtn, 'gedit_tb_bold'));

	tb.appendChild(this.createToolbarButton('', 'italic',
											gEditLang.italic, GEditAPI.tbOnBtn, 'gedit_tb_italic'));
	tb.appendChild(this.createToolbarButton('', 'underline', 
											gEditLang.underline, GEditAPI.tbOnBtn, 'gedit_tb_underline'));

	

	// Justify L/C/R
	tb.appendChild(this.createToolbarButton('', 'justifyright', 
											gEditLang.justifyRight, GEditAPI.tbOnBtn, 'gedit_tb_justifyright'));

	tb.appendChild(this.createToolbarButton('', 'justifycenter', 
											gEditLang.justifyCenter, GEditAPI.tbOnBtn,'gedit_tb_justifycenter'));

	tb.appendChild(this.createToolbarButton('', 'justifyleft', 
											gEditLang.justifyLeft,GEditAPI.tbOnBtn,'gedit_tb_justifyleft'));
	
	tb.appendChild(this.createToolbarButton('', 'justifyfull', 
											gEditLang.justifyFull,GEditAPI.tbOnBtn,'gedit_tb_justifyfull'));
	
	tb.appendChild(this.createToolbarButton('', 'createlink', 
											gEditLang.createLink,GEditAPI.tbOnBtn,'gedit_tb_createlink'));
											
	tb.appendChild(this.createToolbarButton('', 'unlink', 
											gEditLang.unlink,GEditAPI.tbOnBtn,'gedit_tb_unlink'));

	tb.appendChild(this.createToolbarButton('', 'insertimage', 
											gEditLang.insertImage,GEditAPI.tbOnBtn,'gedit_tb_insertimage'));
	tb.appendChild(this.createToolbarButton('', 'insertunorderedlist', 
											gEditLang.insertUL,GEditAPI.tbOnBtn,'gedit_tb_insertul'));
	tb.appendChild(this.createToolbarButton('', 'insertorderedlist', 
											gEditLang.insertOL,GEditAPI.tbOnBtn,'gedit_tb_insertol'));

	tb.appendChild(document.createElement('br'));
	// Font names,sizes,fore color
	tb.appendChild(this.createFontBox());
	tb.appendChild(this.createFontSizeBox());
	tb.appendChild(this.createForeColorBox());
	
	this.tb = tb;
	
	return tb;
}

GEdit.prototype.setSelectionRange = function(input, start, end) {
	if (!isIE) {
		input.setSelectionRange(start, end);
	} else {
		// assumed IE
		var range = input.createTextRange();
		range.collapse(true);
		range.moveStart("character", start);
		range.moveEnd("character", end - start);
		range.select();
	}
}

GEdit.prototype.pasteHTML = function(string) {
	if (isIE) {
		this.doc.selection.createRange().pasteHTML(string);
	} else {
		/*var random_string = "insert_html_" + Math.round(Math.random()*100000000);
		GEditAPI.execCommand("insertimage", random_string);
		var pat = new RegExp("<[^<]*" + random_string + "[^>]*>");
		this.doc.body.innerHTML = this.doc.body.innerHTML.replace(pat, string);*/
		GEditAPI.execCommand('inserthtml',string);
	}
}

GEdit.prototype.getSelectionRange = function(obj) {
	/* 
   Get the selection start and end positions inside a text object

   Syntax:
     coords = selectionCoords ( object )

   Return value:
     Returns an array with 2 elements. Index 0 contains the start 
     position of the selection. Index 1 contains the end position 
     of the selection.
     On error or empty selection function returns an array filled
     with -1.

   Remarks:
     Works fine with onMouseUp event.

   Browser support:
     Internet Explorer 4+ 

   Copyright (C) Mateusz Turcza <mturcza@tlen.pl>

   Licence:
     GNU General Public License
     (http://www.gnu.org/licenses/lgpl.html)
*/
  var selectionStart = 0
  var selectionEnd   = 0
  if(document.selection && document.selection.createRange) {
    // document.selection is native to Internet Explorer 4+
    // (Mac versions of IE 4.0x may have problems with TextRange)
    var ini = obj.value // initial value of text field
    var sel = document.selection
    var srn = sel.createRange()
    if(srn.text.length>0 && srn.parentElement().id==obj.id) {
      // selection not empty, and within text field
      var sbf = String(srn.text)  // - buffer selected text
      sel.clear()                 // - remove selected string
      var bkm = srn.getBookmark() // - mark current place of carriage
      var trn = obj.createTextRange()  // - create text range
          trn.moveToBookmark(bkm)      // - the beginning of text range is
          trn.moveStart('character',0) //   the last position of carriage
      var len = obj.value.length  // - total length of text in the text field
                                 //   after removing selection
          trn.moveEnd('character',len) // - end of text range is equal to total length
          trn.select()                 // - select text range
      var rgt = String(trn.text) // - string on the right hand side of selection
      var lft = ini.substring(0,len-trn.text.length) // - string on the left hand side
      // recreate selection
      obj.value = ini // - recreate initial text field value
      trn.collapse()  // - move carriage to the beginning 
      trn.moveStart('character',lft.length) // - start of selection 
      trn.moveEnd('character',sbf.length)   // - end of selection
      trn.select() // - select
      selectionStart = lft.length
      selectionEnd   = lft.length + sbf.length -1
    }
  }
  return [selectionStart,selectionEnd];
}
GEdit.prototype.getSelectionEnd = function(input) {
	if (!isIE)
		return input.selectionEnd;
	var range = document.selection.createRange();
	var isCollapsed = range.compareEndPoints("StartToEnd", range) == 0;
	if (!isCollapsed)
		range.collapse(false);
	var b = range.getBookmark();
	return b.charCodeAt(2) - 2;
}

GEdit.prototype.getSelection = function() {
	if (isIE) {
		return this.doc.selection;
	} else {
		return this.e.contentWindow.getSelection();
	}
};

GEdit.prototype.createRange = function(sel) {
	if (isIE) {
		return sel.createRange();
	} else {
		this.focus();
		if (typeof sel != "undefined") {
			try {
				return sel.getRangeAt(0);
			} catch(e) {
				
				return this.doc.createRange();
			}
		} else {
			return this.doc.createRange();
		}
	}
};

GEdit.prototype.isToolbarCreated = function()
{
	return (this.tb != null);
}


/**
* Borrowed from fck editor, simple concept tho,
* replaces " & < > with their
* HTML encoded represantations in a given string
*
* @param string text - string to encoded
* @return string - encoded string
*
*/
GEdit.prototype._HTMLEncode = function( text )
{
	if ( typeof( text ) != "string" )
		text = text.toString() ;

	text = text.replace(/&/g, "&amp;").replace(
		/"/g, "&quot;").replace(
		/</g, "&lt;").replace(
		/>/g, "&gt;") ;
//"
	return text ;
}

var GEditPopup = {
	
	/**
	* @var array
	* Stores instances of _GEditPopupObject
	*/
	_instances  : [],
	/**
	* @var int
	* Stores smallest index available for a the next instance
	*/
	_freeInst	: 0,
	
	_initMiscTimerIds : [],
	
	// Active index
	i		: 0,
	
	// Active popup
	p : 0,
	
	_GEditPopupObject : function (command,owner,className,isColorsMenu) {
		this.el = null;
		this.className = className;
		this.owner	   = owner;
		this.command   = command;
		this.isColorsMenu = !!isColorsMenu;
	},
	
	attach : function (command,owner,className, items,isColorsMenu) {
		var o = GEditPopup;
		o._setFreeInstance();
		var popup = new o._GEditPopupObject(command,owner,className,isColorsMenu)
				
		o._instances[o._freeInst] = popup;
		o._init(items);
		return o._freeInst;
	},
	
	_init : function(items) {
		var o = GEditPopup;
		
		// Set currently active popup
		o.p = o._instances[o._freeInst];
		
		o.p.el = document.createElement('ul');
		
		o.p.el.className = o.p.className;
		
		o.p.el.setAttribute('id', 'tb' + Math.floor(Math.random()*999999) + '___' + GEditAPI.gEdit.id);
		
		for (var i = 0; i < items.length; i++)
		{
			var a = rDom.createEl('a');
			
			if (o.p.isColorsMenu) {
				a.style.backgroundColor = items[i];
				a.title = items[i];
			} else {
				a.appendChild( document.createTextNode(items[i]));
			}
			a.setAttribute('href', '#');
			a.style.fontFamily = items[i];
			rDom.addEvent(a, 'click', o.onItemClick);
			o.p.el.appendChild(rDom.createEl('li').appendChild(a));
		}
				
		rDom.toggleDisplay(o.p.el);
		document.body.appendChild(o.p.el);
		
		rDom.addEvent(o.p.owner, 'click', o.onOwnerClick);
		rDom.addEvent(document, 'click',  o.onOwnerBlur);
		
		if (GEditAPI.gEdit.doc) {
			rDom.addEvent(GEditAPI.gEdit.doc, 'click',  o.onOwnerBlur);
		}
		
		
		
	
		
	},
	
	/**
	* Event: click
	* Fired when clicking a menu item
	*/
	onItemClick : function (ev) {
		var o = GEditPopup;
		
		var arg = rDom.getTarget(ev).innerHTML;
		if (o.p.isColorsMenu) {
			arg = rDom.getTarget(ev).title;
		}
		
		GEditAPI.execCommand(o.p.command, arg);
		o.p.owner.style.fontFamily = rDom.getTarget(ev).innerHTML;
		o.setText(o.p.owner.style.fontFamily);
		o.onOwnerBlur();
		rDom.stopEvent(ev);
	},
	
	/**
	* Event: click
	* Fired when clicking the menu owner parent
	*/
	onOwnerClick : function (ev) {
		
		
		var o = GEditPopup;
		
		// Store active popup index
		o.i = o.getItemByOwner(rDom.getTarget(ev));
		
		// Store active popup
		o.p = o._instances[o.i];
		
		if (o.p.el.style.display == 'block') {
			
			o.p.el.style.display = 'none';
			
			rDom.stopEvent(ev);
			
			return;
		}
		
		for (var i = 0; i < o._instances.length; i++) {
			o._instances[i].el.style.display = 'none';
		}
		
		
		var y = 5;
		if (isIE) {
			y = 22;
		}
		
		var pos = rDom.getElementPos(o.p.owner);
		
		o.p.el.style.left = pos.x + 'px' ;
		o.p.owner.zIndex = '1';
		o.p.el.style.top  = (pos.y + y) + 'px';
		m
		rDom.toggleDisplay(o.p.el);
		GEditAPI.gEdit.focus();
		rDom.stopEvent(ev);
	},
	
	getItemByOwner : function(el) {
		var o = GEditPopup;
		for (var i = 0; i < o._instances.length; i++) {
			if (o._instances[i].owner == el) {
				return i;
			}
		}
		return null;
	},
	
	/**
	* Event: blur (lose of focus)
	* when losing focus either by clicking on the document or the editing iframe itself
	*/
	onOwnerBlur : function (ev) {
		
		var o = GEditPopup;
		if (rDom.getTarget(ev) != o.p.owner) {
			o.p.el.style.display = 'none';
		}
		
	},
	
		/**
	* Sets text of the select box first option child
	* @param string text
	* @param int[optional] instId - active instance id
	*/
	setText : function (text, instId) {
		var o = GEditPopup;
		
		if (typeof instId == 'undefined' || instId === null) {
			instId = o.i;
			
		}
		
		
		o._instances[instId].owner.firstChild.text = text;
	},
	
	
	/**
	* Looks for a free instances in the _instances array
	* and sets _freeInst param accordingly
	*/
	_setFreeInstance : function()
	{
		var o = GEditPopup;
		var found = false;
		for (var i = 0; i < o._instances.length; i++)
		{
			if (o._instances[i] === null) {
				found = true;
				o._freeInst = i;
				break;
			}
		}
		
		if (!found) {
			o._freeInst = o._instances.length;
		}
	}
	
};

/**
* Insert Image window
*
*/
var GEditWndInsertImage  = {
	_wnd : null,
	
	// Determines whether we're in the browsing tab
	isBrowsing : true,
	
	show : function() {
		var o = GEditWndInsertImage;
		
		if (o._wnd === null) {

			var tmp = document.createElement('div');
			var ret = rAjax.openGetSync(GEditAPI.XURL + '&op=insertimage');
			//alert(ret);
			tmp.innerHTML = ret;
			o._wnd = tmp.firstChild.cloneNode(true);
			document.body.appendChild(o._wnd);
			GMoveable.makeMoveable(o._wnd.getElementsByTagName('h2')[0], o._wnd);
			
			tmp.removeChild(tmp.firstChild);
			tmp = null;
			
			rDom.addEvent($('insImgBrowse'), 'click', o.onTabSwitch);
			rDom.addEvent($('insImgUpload'), 'click', o.onTabSwitch);
			rDom.addEvent($('insImgClose'), 'click',  o.close);
			rDom.addEvent($('insImgSelDsel'), 'click',  o.onSelDesel);
			rDom.addEvent($('insImgDelSel'), 'click',  o.onMultiRemove);
			
			rDom.addEvent(document, 'keypress',  o.onWndKeyPress);
			
		}
		o._wnd.style.display = 'block';
		var docSize = rDom.getDocSize();
		o._wnd.style.top = '40px';
		o._wnd.style.left = (docSize.width / 2) - (parseInt(rDom.getCurrentStyle(o._wnd,'width')) /2) + 'px';
		o._wnd.style.opacity = '0.8';
	},
	
	onWndKeyPress : function(ev) {
		var o = GEditWndInsertImage;
		if (rDom.getKeyCode(ev) == 27) { // escape
			o.close();
		}
	},
	
	/**
	* Event handler : Click
	*
	* Multiple items removal:
	* Fired when clicking remove selected items
	* submits a hidden form with a hidden value named
	* productIds , that'll contain all selected items
	* ids in a string delimited by | character.
	*/
	onMultiRemove : function(ev)
	{
		var items		 = $('insImgFrame').contentWindow.document.getElementById('insImgItems');
		items.value = '';
		
		var checkBoxes = $('insImgFrame').contentWindow.document.getElementsByName('check');
		
		for (var i = 0; i < checkBoxes.length; i++)
		{
			if (checkBoxes[i].checked) {
				items.value += checkBoxes[i].value + '|';
			}
		}
		
		if (!items.value.length)
		{
			alert('You must select at least one item.');
			rDom.stopEvent(ev);
			return;
		}
		
		items.value = items.value.substring(0, items.value.length - 1);
		
		if (!confirm('Are you sure?')) {
			rDom.stopEvent(ev);
		} else { // submit form with hidden input
			$('insImgFrame').contentWindow.document.getElementById('insImgMultiRemFrm').submit();
		}
	},
	
	/**
	* Event handler : Click
	* Fire when clicking on Select/Deselect all
	*/
	onSelDesel : function(ev)
	{
		var toSel = null;
		
		var checkBoxes = $('insImgFrame').contentWindow.document.getElementsByName('check');
		
		for (var i = 0; i < checkBoxes.length; i++)
		{
			if (toSel === null)
				if (checkBoxes[i].checked)
					toSel = false;
				else
					toSel = true;
			checkBoxes[i].checked = toSel;
		}
		
		rDom.stopEvent(ev);
	},
	
	/**
	* Called from the browse iframe when user selects an image
	* or the insert image window (the iframe's container) when user
	* click on cancel
	*
	* @param string[optional] imageFileName
	*
	*/
	close : function(imageFileName) {
		var o = GEditWndInsertImage;
		
		if  (typeof imageFileName == 'string') {
			GEditAPI.execCommand('insertimage', imageFileName);
		}
		o._wnd.style.display = 'none';
	},
	
	onTabSwitch : function(ev) {
		if ($('insImgFrame').src != rDom.getTarget(ev).href) {
			$('insImgFrame').src = rDom.getTarget(ev).href;
			var anchors = $('insImgTabs').getElementsByTagName('a');
			for (var i = 0; i< anchors.length; i++) {
				rDom.cssClassSwap(anchors[i], 'tabSelected', 'tabUnselected');
			}
		}
		rDom.stopEvent(ev);
	}
};

var GMoveable = {
	/**
	* @var array
	* Stores instances of _GMoveableObject
	*/
	_instances  : [],
	/**
	* @var int
	* Stores smallest index available for a the next instance
	*/
	_freeInst : null,
 
	
	/**
	* @var object
	* Stores current mouse offset relative to dragable element
	*/
	_mouseOffset : [],
	
	/**
	* @param object dragEl - the element that you use
	*								 the mouse cursor to drag the window.
	* @param object wndEl		  - the whole window element thats moveable
	*/
	makeMoveable : function(dragEl, wndEl) {
		var o = GMoveable;
		
		o._setFreeInstance();
		
		o._instances[o._freeInst] = new o._GMoveableObject(dragEl, wndEl);
		
		// Window drag n drop events
		
		rDom.addEvent(dragEl,  'mousedown', o.onMouseDown);
		rDom.addEvent(dragEl,  'mouseup',   o.onMouseUp);
		//rDom.addEvent(dragEl,  'dblclick',  o.onDblClick);
		rDom.addEvent(document,'mousemove', o.onMouseMove);
	},
	
	_GMoveableObject : function (dragEl, wndEl) {
		this.dragEl = dragEl;
		this.wndEl  = wndEl;
		this.isDragging = false;
		wndEl.style.position = 'absolute';
		wndEl.style.margin = '0';
	},
	
	/**
	* Gets GMoveableObject by draggable element
	* @param object dragEl - the element that you use
	*								 the mouse cursor to drag the window.
	* @return object - instances of GMoveableObject
	*/
	getObjByDrag : function (dragEl) {
		var o = GMoveable;
		
		for (var i = 0; i < o._instances.length; i++) {
			if (o._instances[i].dragEl == dragEl) {
				return o._instances[i];
			}
		}
		
		return null;
	},
	
	// Handles divWindow dropping event
	onMouseUp : function(ev) {
		var obj = GMoveable.getObjByDrag(rDom.getTarget(ev));
		obj.isDragging = false;
		obj.wndEl.style.zIndex = '20';
	},
	
	/*// Handles divWindow double click event (minimize/maximize)
	onDblClick : function (ev)
	{
		var wndEl = GMoveable.getObjByDrag(rDom.getTarget(ev)).wndEl;
		if (rDebugConsole.container.offsetHeight >= rDebugConsole.normalHeight)
		{
			 rDebugConsole.container.style.height = rDebugConsole.minHeight + 'px';
			 rDebugConsole.outputList.style.display = 'none';
		}
		else
		{
		 	rDebugConsole.container.style.height =  rDebugConsole.normalHeight + 'px';
		 	rDebugConsole.outputList.style.display = 'block';
		}
	},*/
	
	// Handles divWindow moving event
	onMouseMove : function(ev) 
	 {
	 	obj = GMoveable._currObj;
	 	if (obj) {
		 	if (obj.isDragging)
		 	{
			 	var coords = rDom.getMouseCoords(ev);
			 	obj.wndEl.style.zIndex = '9999';
			 	obj.wndEl.style.left = (coords.x - (GMoveable._mouseOffset.x )) + 'px';
			 	obj.wndEl.style.top  = (coords.y - (GMoveable._mouseOffset.y )) + 'px';
		 	
		 	}
	 	}
	 },
	
	// Handles signaling of start drag event
	onMouseDown : function(ev)  
	{
		obj = GMoveable.getObjByDrag(rDom.getTarget(ev));
				
		GMoveable._currObj = obj;
		if (obj !== null) {
		obj.isDragging = true;
		
		var coords   = rDom.getMouseCoords(ev);
		var elCoords = rDom.getElementPos(obj.wndEl);
		GMoveable._mouseOffset.x = coords.x - elCoords.x;
		GMoveable._mouseOffset.y = coords.y - elCoords.y;
		}
	},
	
		
	/**
	* Looks for a free instances in the _instances array
	* and sets _freeInst param accordingly
	*/
	_setFreeInstance : function()
	{
		var o = GMoveable;
		var found = false;
		for (var i = 0; i < o._instances.length; i++)
		{
			if (o._instances[i] === null) {
				found = true;
				o._freeInst = i;
				break;
			}
		}
		
		if (!found) {
			o._freeInst = o._instances.length;
		}
	}
}
