
//==============================================================================================
//					EvaaCore
//==============================================================================================

var EvaaCore = {
	onloadExecuted: true,

	onload: function(){
		EvaaAJAX.setup();

		EvaaCore.onloadExecuted = true;
	}

};



//==============================================================================================
//					Public Methods
//==============================================================================================

// Clears all feedback messages (popups, etc...) which are shown to user
// This method is meant to be overridden
function Evaa_ClearAllMessages(){

}

function _evaa_IsInDebugMode(){
	return typeof(_evaa_debugmode) != 'undefined' && _evaa_debugmode ;
}


//==============================================================================================
//					Evaa Object
//==============================================================================================

var Evaa = {
	ScriptFragment: '(?:<evaa_script.*?>)((\n|\r|.)*?)(?:<\/evaa_script>)'
};




//==============================================================================================
//					Evaa Effects
//==============================================================================================

//------------------------------------------------------- Smooth Scrolling
Fx.Scroll = Class.create();
Fx.Scroll.prototype = Object.extend(new fx.Base(), {
    initialize: function(options) {
        this.setOptions(options);
    },

    scrollTo: function(el){
        var desty = Position.cumulativeOffset($(el));
        var dest = desty[1];
        var client = window.innerHeight || document.documentElement.clientHeight;
        var full = document.documentElement.scrollHeight;
        var top = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop;
        if (dest+client > full) this.custom(top, dest - client + (full-dest));
        else this.custom(top, dest);
    },

    scrollToTop: function(){
        var client = window.innerHeight || document.documentElement.clientHeight;
        var full = document.documentElement.scrollHeight;
        var top = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop;
        if (client > full) this.custom(top, full - client);
        else this.custom(top, 0);
    },

    increase: function(){
        window.scrollTo(0, this.now);
    }
});


//------------------------------------------------------- Accordion
function evaa_accordion(togglerClass, stretcherClass, animate, active, overloadIds, overloadIds2){
	var users = false;
	if (animate == null || animate == true){
		animate = 'open-first';
	}else if(animate==false){
		animate = false;
	}
	if (overloadIds == null){
		var stretchers = document.getElementsByClassName(stretcherClass);
	}
	else{
		var stretchers = new Array();
		for (var x = 0; x < overloadIds.length; x++){
			var stretch = document.getElementById('userAccount_stretcher_' + overloadIds[x]);
			stretchers.push(stretch);
		}
	}
	if (animate || animate == 'open-first'){
		stretchers.each(function(item){
			if (item.className =='userAccount_stretcher' && item.id != ('userAccount_stretcher_' + active)){
				Element.setStyle(item, {'height': '55', 'overflow': 'hidden'});
				users = true;
				var children = item.childNodes[0].childNodes;
				for (var i = 0; i < children.length; i++)
				{
					var child = children[i];
					if (child.className == 'users_stretcher'){
						Element.setStyle(child, {'height':'0'});
						break;
					}
				}
			}
			else{
				Element.setStyle(item, {'height': '0', 'overflow': 'hidden'});
			}
		});
	}
	if (overloadIds2 == null){
		var togglers = document.getElementsByClassName(togglerClass);
	}
	else{
		var togglers = new Array();
		for (var x = 0; x < overloadIds2.length; x++){
			var togg = document.getElementById('userAccount_toggler_' + overloadIds2[x]);
			togglers.push(togg);
		}
	}
	var myAccordion = new Fx.Accordion(togglers, stretchers, { opacity: false, start: animate, duration: 400, transition: Fx.Transitions.expoInOut,

		onBeforeActive: function(toggler, i){
			if (toggler.className == 'userAccount_toggler'){
					var stretcher = this.elements[i];
					var children = stretcher.childNodes[0].childNodes;
					for (var i = 0; i < children.length; i++)
					{
						var child = children[i];
						if (child.className == 'users_stretcher'){
							child.style.height = child.childNodes[0].clientHeight + 'px';
						}
					}
					stretcher.style.height = stretcher.childNodes[0].clientHeight + 'px';
					//setTimeout("Backend._adjustMain()",500);
				}
		},

		onActive: function(toggler, i){
			if (toggler != null){
				if (toggler.className == 'moduletab_toggler'){
					toggler.style.background = 'url("ui/modules/images/module_report.jpg") no-repeat';
				}
			}
		},

		onBackground: function(toggler, i){
			if (toggler.className == 'moduletab_toggler'){
				toggler.style.background = 'url("ui/modules/images/module_registration.jpg") no-repeat';
			}
			else if (toggler.className == 'userAccount_toggler'){
				var stretcher = this.elements[i];
				var children = stretcher.childNodes[0].childNodes;
				for (var i = 0; i < children.length; i++)
				{
					var child = children[i];
					if (child.className == 'users_stretcher'){
						child.style.height = 0 + 'px';
					}
				}
			}
		},
		originalHeight : (users || !animate ?'55':'0')

	});
	return myAccordion;

};





//==============================================================================================
//					Javascript Extensions
//==============================================================================================
Object.extend(String.prototype, {
  stripEvaaScripts: function() {
    return this.replace(new RegExp(Evaa.ScriptFragment, 'img'), '');
  },

  extractEvaaScripts: function() {
    var matchAll = new RegExp(Evaa.ScriptFragment, 'img');
    var matchOne = new RegExp(Evaa.ScriptFragment, 'im');
    return (this.match(matchAll) || []).map(function(scriptTag) {
      return (scriptTag.match(matchOne) || ['', ''])[1];
    });
  },

  evalEvaaScripts: function() {
    return this.extractEvaaScripts().map(function(script) { return eval(script) });
  }
});






//==============================================================================================
//					EvaaWindow Object
//==============================================================================================

var EvaaWindow = {};

EvaaWindow.Events = {
	events: [],
	onbeforeunloadEvents: [],

	register: function(eventType, event){

		//TODO: Need to check whether there's already a function attached to the event before overwriting with fireEvents()

		if(eventType == "beforeunload"){ // prototype is not handling returning of string back to beforeunload handler. So, we consider it as a special case here.
			window.onbeforeunload = EvaaWindow.Events.fireOnBeforeUnloadEvents;
			this.onbeforeunloadEvents.push(event);
		}else{
			Event.observe(window, eventType, EvaaWindow.Events.fireEvents, false);
			this.events.push([eventType, event]);
		}
	},

	fireEvents: function(evt) {
		for(var i=0, length=EvaaWindow.Events.events.length; i < length; i++){
			if(evt.type == EvaaWindow.Events.events[i][0]){
				EvaaWindow.Events.events[i][1]();
			}
		}
	},

	fireOnBeforeUnloadEvents: function(evt){
		var retVal;
		for(var i=0, length=EvaaWindow.Events.onbeforeunloadEvents.length; i < length; i++){
			retVal = EvaaWindow.Events.onbeforeunloadEvents[i]();
			if(typeof(retVal) == 'string'){
				return retVal;
			}
		}
	}

};


// TODO: Need to come up with mechanism to ensure the onload is not overwritten
EvaaWindow.Events.register("load", EvaaCore.onload);



EvaaWindow.Open = function(url, name, features){
	if(name==null){
		name = "NewWindow";
	}
	if(features==null){
		features = "toolbar=yes, menubar=yes, location=yes, resizable=yes, scrollbars=yes, status=yes";
	}
	var newWindow = window.open(url, name, features);
	newWindow.focus();
	return newWindow;
};


//==============================================================================================
//					EvaaAJAX Object
//==============================================================================================

var EvaaAJAX = Class.create();

EvaaAJAX.defaultFeedbackType = 1;

EvaaAJAX.prototype = {
	setOptions: function(options) {
		this.options = {
			isEvaaAJAX: true,
			url: "index.php",
			method: "post",
			feedbackType: EvaaAJAX.defaultFeedbackType, // Supports 3 types: 0-don't show any feedback at all, 1-(default)show normal loading notification, 2-show modal loading notification
			max_waiting_time: 120000,
			asynchronous: true,
			evalScripts: true,
			insertion: undefined
		}
		Object.extend(this.options, options || {});

	},

	initialize: function(options){
		this.setOptions(options);
	},

	Update: function(placeholder, className, methodName, params){
		var sParameters = this.buildParams(className, methodName, params);

		this.ajax = new Ajax.Updater(
			placeholder,
			this.options['url'],
			{
				method: this.options['method'],
				parameters: sParameters,
				evalScripts: this.options['evalScripts'],
				feedbackType: this.options['feedbackType'],
				max_waiting_time: this.options['max_waiting_time'],
				asynchronous: this.options['asynchronous'],
				isEvaaAJAX : this.options['isEvaaAJAX'],
				insertion : this.options['insertion']
			});
	},

	Request: function(responseHandler, className, methodName, params){

		//Build parameters
		var sParameters = this.buildParams(className, methodName, params);
		if(typeof(responseHandler) == "string"){
			responseHandler = eval(responseHandler); // Attempt to convert to function
		}

		this.ajax = new Ajax.Request(
			this.options['url'],
			{
				method: this.options['method'],
				parameters: sParameters,
				onComplete: function(request){
					if(request.status >= 200 && request.status < 300){ // Note: If status=0, we don't execute responseHandler
						responseHandler(request);
					}},
				feedbackType: this.options['feedbackType'],
				max_waiting_time: this.options['max_waiting_time'],
				asynchronous: this.options['asynchronous']
			});
	},

	Exec: function(className, methodName, params){
		this.Request(function(response, json){this.execHandler(response, json, this.options['evalScripts']);}.bind(this),
						className, methodName, params);
	},


	//------------------------------------- Internal Methods


	buildParams: function(className, methodName, params){
		if (className != '' && methodName != ''){
			return "_evaa_o=" + className + "&_evaa_e=" + methodName + (params==null || params=="" ? "" : "&" + params);
		}
		else{
			return (params==null || params=="" ? "" : "&" + params);
		}
	},

	execHandler: function(request, json, evalScript){
		if(evalScript){
			request.responseText.evalScripts();
		}

	}

};


//--------------------------------------------------- EvaaAJAX Shortcut & utility methods
EvaaAJAX.Update = function(placeholder, className, methodName, params){
	var level = EvaaAJAX.defaultFeedbackType;
//	if (methodName == 'TabClicked' ||
//		methodName == 'SelectAllRows' ||
//		methodName == 'DeselectAllRows' ||
//		methodName == 'BoxClosed'){
//		level = 0;
//	}
	var evaaAjax = new EvaaAJAX({feedbackType:level});
	evaaAjax.Update(placeholder, className, methodName, params);
};

EvaaAJAX.UpdateSync = function(placeholder, className, methodName, params){
	var level = EvaaAJAX.defaultFeedbackType;
	var evaaAjax = new EvaaAJAX({feedbackType:level, asynchronous:false});
	evaaAjax.Update(placeholder, className, methodName, params);
};

EvaaAJAX.Request = function(responseHandler, className, methodName, params){
	var evaaAjax = new EvaaAJAX();
	evaaAjax.Request(responseHandler, className, methodName, params);
};

EvaaAJAX.Exec = function(className, methodName, params){
	var evaaAjax = new EvaaAJAX();
	evaaAjax.Exec(className, methodName, params);
};

EvaaAJAX.isCallInProgress = function(xmlHttpRequest){
	switch (xmlHttpRequest.readyState) {
		case 1: case 2: case 3:
			return true;
			break;

		// Case 4 and 0
		default:
			return false;
			break;
	}
};

EvaaAJAX.buildParams = function(className, methodName, params){
	var evaaAjax = new EvaaAJAX();
	evaaAjax.buildParams(className, methodName, params);
};

EvaaAJAX.setup = function(){
	//Create loading DIV (if necessary) & hide it
	if($('loading')==null){
		new Insertion.Top(document.body, '<div id="loading" class="loading_default" style="display:none;" >&nbsp;</div>');
	}
	Element.hide('loading');
};


//--------------------------------------------------- EvaaAJAX.Handlers
EvaaAJAX.Handlers = {
	onCreate: function(request){
		if(typeof(request.options['isEvaaAJAX'])=='undefined'){
			return;
		}

		Evaa_ClearAllMessages();

		var connectionTimeout = new EvaaAJAX.ConnectionTimeout(request);
		request.options['timeoutId'] = connectionTimeout.startMonitoring();

		// Setting unique id for request. Using timeoutId. (any better way?)
		request.options['uid'] = request.options['timeoutId'];

		EvaaAJAX.Loading.show(request);

	},

	onComplete: function(request){
		if(typeof(request.options['isEvaaAJAX'])=='undefined'){
			return;
		}

		clearTimeout(request.options['timeoutId']);
		EvaaAJAX.Loading.hide(request);
	},

	onException: function(request, exception){
		if(typeof(request.options['isEvaaAJAX'])=='undefined'){
			return;
		}

		EvaaAJAX.Loading.hide(request);

		if(_evaa_IsInDebugMode()){
			var description = '';
			try{
				for (var property in exception) {
				        description += property + '=' + exception[property] + '\n';
				}
			}catch(e){}
			alert('Ajax-OnException: ' + exception + '\n\n' + description);

		}else{
			switch(request.options['feedbackType']){
				case 1: case 2:
					EvaaAJAX.Handlers.showErrorMessage(request, "We have encountered an error. The operation could not be completed. \nPlease try again...");
					break

				//case 0
				default:
					// Don't show anything
			}

		}
		return true;
	},

	onFailure: function(request){
		if(typeof(request.options['isEvaaAJAX'])=='undefined'){
			return;
		}

		EvaaAJAX.Loading.hide(request);

		if(_evaa_IsInDebugMode()){
			var status = Try.these(
			function() { return request.status },
			function() { return 'timed out'}
			);

			var description = '';
			try{
				for (var property in request) {
				        description += property + '=' + request[property] + '\n';
				}
			}catch(e){}

			alert ('Ajax-OnFailure: status(' + status + ')\n\n' + description);

		}else{

			switch(request.options['feedbackType']){
				case 1: case 2:
					EvaaAJAX.Handlers.showErrorMessage(request, "We have encountered an error. The operation could not be completed. \nPlease try again...");
					break

				//case 0
				default:
					// Don't show anything
			}

		}
		return true;
	},

	showErrorMessage: function(request, message){
		// Show error message only if it hasn't been displayed previously
		if(typeof(request.options['errorMsgShown']) == 'undefined'){
			alert(message);
			request.options['errorMsgShown'] = true;
		}
	}
};

// Register global handlers
Ajax.Responders.register({
	onCreate: EvaaAJAX.Handlers.onCreate,
	onComplete: EvaaAJAX.Handlers.onComplete,
	onException: EvaaAJAX.Handlers.onException,
	onFailure: EvaaAJAX.Handlers.onFailure
	});


//--------------------------------------------------- EvaaAJAX.ConnectionTimeout
EvaaAJAX.ConnectionTimeout = Class.create();
EvaaAJAX.ConnectionTimeout.prototype = {
	request: null,
	timeoutId: 0,

	initialize: function(request){
		this.request = request;
	},

	startMonitoring: function(){
		this.timeoutId = setTimeout(this.checkTimeout.bindAsEventListener(this), this.request.options['max_waiting_time']);
		return this.timeoutId;
	},

	stopMonitoring: function(){
		clearTimeout(this.timeoutId);
	},

	checkTimeout: function(){
		if (EvaaAJAX.isCallInProgress(this.request.transport)) {
			this.request.transport.abort();
			this.onTimeout();
			// Run the onFailure method if we set one up when creating the AJAX object
			if (this.request.options['onFailure']) {
				this.request.options['onFailure'](this.request.transport);
			}
		}
	},

	onTimeout: function(){
		switch(this.request.options['feedbackType']){
			case 1: case 2:
				EvaaAJAX.Handlers.showErrorMessage(this.request, "The internet connection seems to be having some problems. We could not complete the operation.");
				break

			//case 0
			default:
				// Don't show anything
		}
	}

};


//--------------------------------------------------- EvaaAJAX.Loading
EvaaAJAX.Loading = {
	visibleCount: [[], [], [], []],

	show: function(request){

		if(EvaaAJAX.Loading.visibleCount[request.options['feedbackType']].indexOf(request.options['uid'])==-1){
			EvaaAJAX.Loading.visibleCount[request.options['feedbackType']].push(request.options['uid']);
		}

		switch(request.options['feedbackType']){

			case 1:
				var newLoading = document.createElement('div');
				newLoading.setAttribute('id', 'loading');
				if(navigator.userAgent.indexOf("MSIE")!=-1){
					newLoading.setAttribute('className', 'loading');
					loadingTop = $('loading').style.top.replace('px','');
					loadingLeft = $('loading').style.left.replace('px','');
				}else{
					newLoading.setAttribute('class', 'loading');
					loadingTop = $('loading').style.top;
					loadingLeft = $('loading').style.left;
				}
				newLoading.style.top = loadingTop;
				newLoading.style.left = loadingLeft;
				newLoading.style.display = 'block';
				newLoading.innerHTML = $('loading').innerHTML;

				Element.remove('loading');
				bod = document.getElementsByTagName('body')[0];
				bod.appendChild(newLoading);
				break;

			case 2:
				var curtain = $(document.createElement('div'));
				curtain.id = 'curtain';
				var loading2 = $(document.createElement('div'));
				loading2.id = 'loading2';
				bod 			= document.getElementsByTagName('body')[0];
				bod.appendChild(curtain);
				bod.appendChild(loading2);
				break;

			case 3:
				loadingEl = $('loading');
				loadingEl.style.top = (document.documentElement.scrollTop || document.body.scrollTop)+"px";
				Element.show(loadingEl);
				break;

			//case 0
			default:


		}
	},

	hide: function(request){
		var feedbackType = request.options['feedbackType'];
		if(EvaaAJAX.Loading.visibleCount[feedbackType].indexOf(request.options['uid'])==-1){
			return ; // Loading is already hidden
		}
		EvaaAJAX.Loading.visibleCount[feedbackType] =
				EvaaAJAX.Loading.visibleCount[feedbackType].without(request.options['uid']);
		switch(feedbackType){
			case 1:
				if(EvaaAJAX.Loading.visibleCount[1].length == 0){
					Element.hide('loading');
				}
				Backend.liftcurtain();
				break;

			case 2:
			  	Element.remove($('curtain'));
			    Element.remove($('loading2'));
				break;

			case 3:
				if(EvaaAJAX.Loading.visibleCount[1].length == 0){
					Element.hide('loading');
				}
				break;

			default:

		}
	}
}


//==============================================================================================
//					Evaa Utility Methods
//==============================================================================================
Evaa.Heartbeat = Class.create();
Evaa.Heartbeat.prototype = {
	timer: null,
	interval: 0,

	initialize: function(interval){
		this.interval = interval;
	},

	start: function(){
		if(this.timer != null){
			this.stop();
		}
		this.timer = setInterval(this.performHeartbeat, this.interval);

	},

	stop: function(){
		clearInterval(this.timer);
	},

	performHeartbeat: function(){
		new Ajax.Request( "index.php", {method: "get", parameters: "heartbeat"});
	}

};



//==============================================================================================
//					Evaa Controls
//==============================================================================================


Evaa.InPlaceRichEditor = Class.create();

Evaa.InPlaceRichEditor.prototype = Object.extend(Ajax.InPlaceEditor.prototype, {
  initialize: function(element, options) {
    this.url = window.location.protocol+"//"+window.location.host+window.location.port+window.location.pathname+"/index.php";
    this.element = $(element);

    this.options = Object.extend({
      okButton: true,
      okText: "ok",
      cancelLink: true,
      cancelText: "cancel",
      savingText: "Saving...",
      clickToEditText: "Doubleclick to edit",
      okText: "ok",
      rows: 1,
      onComplete: function(transport, element) {
        new Effect.Highlight(element, {startcolor: this.options.highlightcolor});
      },
      onFailure: function(transport) {
        alert("Error communicating with the server: " + transport.responseText.stripTags());
      },
      callback: function(form) {
        return Form.serialize(form);
      },
      handleLineBreaks: true,
      loadingText: 'Loading...',
      savingClassName: 'inplaceeditor-saving',
      loadingClassName: 'inplaceeditor-loading',
      formClassName: 'inplaceeditor-form',
      highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor,
      highlightendcolor: "#FFFFFF",
      externalControl: null,
      submitOnBlur: false,
      ajaxOptions: {},
      evalScripts: false,
      ServerPath: false
    }, options || {});

    this.options.evalScripts = false;

    if(!this.options.formId && this.element.id) {
      this.options.formId = this.element.id + "-inplaceeditor";
      if ($(this.options.formId)) {
        // there's already a form with that name, don't specify an id
        this.options.formId = null;
      }
    }

    if (this.options.externalControl) {
      this.options.externalControl = $(this.options.externalControl);
    }

    this.originalBackground = Element.getStyle(this.element, 'background-color');
    if (!this.originalBackground) {
      this.originalBackground = "transparent";
    }

    this.element.title = this.options.clickToEditText;

    this.ondblclickListener = this.enterEditMode.bindAsEventListener(this);
    this.mouseoverListener = this.enterHover.bindAsEventListener(this);
    this.mouseoutListener = this.leaveHover.bindAsEventListener(this);
    Event.observe(this.element, 'dblclick', this.ondblclickListener);
    Event.observe(this.element, 'mouseover', this.mouseoverListener);
    Event.observe(this.element, 'mouseout', this.mouseoutListener);
    if (this.options.externalControl) {
      Event.observe(this.options.externalControl, 'dblclick', this.ondblclickListener);
      Event.observe(this.options.externalControl, 'mouseover', this.mouseoverListener);
      Event.observe(this.options.externalControl, 'mouseout', this.mouseoutListener);
    }
  },

  createForm: function() {
    this.form = document.createElement("form");
    this.form.id = this.options.formId;
    Element.addClassName(this.form, this.options.formClassName);
    this.form.onsubmit = this.onSubmitRichEditor.bind(this);

    FCKeditor.loadAutogrowPlugin = true;
    setTimeout(function(){FCKeditor.loadAutogrowPlugin = false;}, 1000);
	this.oFCKeditor = new FCKeditor( 'FCKeditor-'+this.element.id ) ;

	this.oFCKeditor.ToolbarSet = 'Evaa_ContentManager';
//	if(this.options.ServerPath){
//		this.oFCKeditor.Config['ImageBrowserURL'] = this.oFCKeditor.BasePath + "editor/plugins/evaa_filemanager/browser/default/browser.html?Type=Image&Connector=connectors/php/connector.php?ServerPath=" + this.options.ServerPath
//		this.oFCKeditor.Config['ImageUploadURL'] = this.oFCKeditor.BasePath + "editor/plugins/evaa_filemanager/upload/php/upload.php?Type=Image&ServerPath=" + this.options.ServerPath
//		this.oFCKeditor.Config['LinkUploadURL'] = this.oFCKeditor.BasePath + "editor/plugins/evaa_filemanager/upload/php/upload.php?ServerPath=" + this.options.ServerPath
//	}



//	oFCKeditor.Height	= 300 ;
	this.oFCKeditor.Value	= this.getText();

	this.RegisterEditor(this.oFCKeditor.InstanceName, this);

//	this.oFCKeditor.Config[ 'ToolbarLocation' ] = 'Out:parent(xToolbar)' ;
	this.form.innerHTML = this.oFCKeditor.CreateHtml() +
						  "<input type='hidden' name='_evaa_o' value='Evaa_EventContentManager'>" +
				  		  "<input type='hidden' name='_evaa_e' value='UpdateContent'>"	+
				  		  "<input type='hidden' name='contentName' value='"+this.element.id+"'>" ;

	this.editField = document.createElement("input");
	this.editField.type = "hidden";
	this.editField.name = "content";
	this.form.appendChild(this.editField);

//	this.maximizeEditor();


  },

  maximizeEditor: function(){
  	if(typeof(FCKeditorAPI)!='undefined'){
  		var oEditor = FCKeditorAPI.GetInstance(this.oFCKeditor.InstanceName);

  		if(oEditor.Status == FCK_STATUS_ACTIVE){
  			FCKeditorAPI.GetInstance(this.oFCKeditor.InstanceName).Commands.GetCommand('FitWindow').Execute();

  			return ;
  		}
  	}

	setTimeout(this.maximizeEditor.bind(this), 1000)

  },


  onSubmitRichEditor: function(){
  	this.editField.value = FCKeditorAPI.GetInstance(this.oFCKeditor.InstanceName).GetXHTML();
  	return this.onSubmit();
  },

  removeForm: function() {
  	this.UnRegisterEditor(this.oFCKeditor.InstanceName);
    if(this.form) {
      if (this.form.parentNode) Element.remove(this.form);
      this.form = null;
    }
  },

  dispose: function() {
    if (this.oldInnerHTML) {
      this.element.innerHTML = this.oldInnerHTML;
    }
    this.leaveEditMode();
    Event.stopObserving(this.element, 'dblclick', this.ondblclickListener);
    Event.stopObserving(this.element, 'mouseover', this.mouseoverListener);
    Event.stopObserving(this.element, 'mouseout', this.mouseoutListener);
    if (this.options.externalControl) {
      Event.stopObserving(this.options.externalControl, 'dblclick', this.ondblclickListener);
      Event.stopObserving(this.options.externalControl, 'mouseover', this.mouseoverListener);
      Event.stopObserving(this.options.externalControl, 'mouseout', this.mouseoutListener);
    }
  },


  // 'Static' Methods
  _editors: [],

  RegisterEditor: function(FCKEditorInstanceName, inPlaceRichEditorInstance){
  	Evaa.InPlaceRichEditor.prototype._editors.push([FCKEditorInstanceName, inPlaceRichEditorInstance]);
  },

  UnRegisterEditor: function(FCKEditorInstanceName){
	Evaa.InPlaceRichEditor.prototype._editors.each(function(editor, index){
		if(editor != null && editor[0]==FCKEditorInstanceName){
			Evaa.InPlaceRichEditor.prototype._editors[index]=null;
			throw $break;
		}
	});
  },

  GetInPlaceRichEditorInstance: function(FCKEditorInstanceName){
	var editor = Evaa.InPlaceRichEditor.prototype._editors.find(function(editor){
		return editor!=null && editor[0]==FCKEditorInstanceName;
	});
	return editor[1];
  }



});


Field.scrollFreeActivate = function(field) {
  setTimeout(function() {
  	try{
    	Field.activate(field);
  	}catch(e){};
  }, 1);
}


//==============================================================================================
//	Utility Functions
//==============================================================================================

/**
*
*  Base64 encode / decode
*  http://www.webtoolkit.info/
*
**/
 
var Base64 = {
 
	// private property
	_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
 
	// public method for encoding
	encode : function (input) {
		var output = "";
		var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
		var i = 0;
 
		input = Base64._utf8_encode(input);
 
		while (i < input.length) {
 
			chr1 = input.charCodeAt(i++);
			chr2 = input.charCodeAt(i++);
			chr3 = input.charCodeAt(i++);
 
			enc1 = chr1 >> 2;
			enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
			enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
			enc4 = chr3 & 63;
 
			if (isNaN(chr2)) {
				enc3 = enc4 = 64;
			} else if (isNaN(chr3)) {
				enc4 = 64;
			}
 
			output = output +
			this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
			this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
 
		}
 
		return output;
	},
 
 
	// private method for UTF-8 encoding
	_utf8_encode : function (string) {
		string = string.replace(/\r\n/g,"\n");
		var utftext = "";
 
		for (var n = 0; n < string.length; n++) {
 
			var c = string.charCodeAt(n);
 
			if (c < 128) {
				utftext += String.fromCharCode(c);
			}
			else if((c > 127) && (c < 2048)) {
				utftext += String.fromCharCode((c >> 6) | 192);
				utftext += String.fromCharCode((c & 63) | 128);
			}
			else {
				utftext += String.fromCharCode((c >> 12) | 224);
				utftext += String.fromCharCode(((c >> 6) & 63) | 128);
				utftext += String.fromCharCode((c & 63) | 128);
			}
 
		}
 
		return utftext;
	}
 
}
