/**
 * @author Stefan Pasel
 * @copyright 2007 blueend.com
 * @package xelos
 * @version 1.0
 */

/* BLUEEND FUNCTIONS -------------------------------------------------------------------------------------------- */

/**
* JS CSS Hide Class (Hide elements if JS is active)
* + Disable NO JS Hide Class by overriding it
*/
var style = document.createElement("style");
style.setAttribute("type","text/css");
var cssStr = ".xf_js_hide{display:none !important;}\n.xf_nojs_hide,.xf_nojs_hide_block{display:block;}\n.xf_nojs_hide_inline{display:inline;}";
if(style.styleSheet){// IE
	style.styleSheet.cssText = cssStr;
} else {// w3c
	var cssText = document.createTextNode(cssStr);
	style.appendChild(cssText);
}
document.getElementsByTagName("head")[0].appendChild(style);

/**
* Multifield for Form-Helper
*/
if(typeof(XF_JS) == "undefined")      XF_JS = {};
if(typeof(XF_JS.User) == "undefined") XF_JS.User = Class.create();
if(typeof(XF_JS.i18n) == "undefined") XF_JS.i18n = Class.create();
if(typeof(XF_JS.String) == "undefined") XF_JS.String = {};

/* No Firebug active */
if(typeof(console) == "undefined"){console = {}; console.log = function(msg){};};

// Initialize i18n Default Values --> Modified later in page call
XF_JS.i18n.thousandSep = ',';
XF_JS.i18n.decimalPoint = '.';

XF_JS.String.getNumericValue = function(v){
	var r = parseFloat(v.replace(new RegExp('['+XF_JS.i18n.thousandSep+']', "g"),'').replace(new RegExp('['+XF_JS.i18n.decimalPoint+']', "g"),'.'));
	return (isNaN(r))?0:r;
};

// XF JS View
XF_JS_View = Class.create();
XF_JS_View.prototype = {
	initialize:function(url){
		this.url = url;
		// Initialize Default Values --> Modified later in page call (in xf_ui)
		this.currentInstance = false;
		this.currentPage = false;
		this.currentCMD = false;
	},
	getParams: function(){
		return this.url.href.toQueryParams();
	},
	// Returns the current url with the additional params as passed, e.g. {test: 1}
	// @todo: Make function undestanding XF view, page, cmd for replacing
	getURL: function(params, url){
		if (url == undefined) url = this.url.href; // Use current URL if nothing passed
		var uri = parseUri(url);
		var base = uri['path'];
		if (typeof params == 'string'){
			var sub_uri = parseUri(params);
			base = sub_uri['path'];
			var new_params = $H(url.toQueryParams()).merge((params.toQueryParams())).toQueryString();
		} else {
			var new_params = $H(url.toQueryParams()).merge($H(params)).toQueryString();
		}
    return base + '?' + new_params;
	},
  linkTo: function(url,usePOST){
    if (usePOST===true){
      return this._linkToPost(url);
    } else {
      document.location = url;
    }
  },
  // Submit url via POST request using hidden form
  _linkToPost: function(url){
    params = url.toQueryParams();
    url = url.split("?");
    url = url[0];
    var fhtml = '<form id="XF_JS.postLinkForm" action="'+url+'" method="post">';
    $H(params).each(function(p) {fhtml+='<input type="hidden" name="'+p.key+'" value="'+p.value+'">';}.bind(this));
    fhtml += '</form>';
    document.body.innerHTML += fhtml;
    document.getElementById("XF_JS.postLinkForm").submit();
  }
}
XF_JS.View = new XF_JS_View(document.location);

XF_JS.ajaxLinkReplace = function(el,target,options){
		this.el = $(el);
		if (!this.el) return false;
		this.el.onclick = function(e, url, source, target){
				evalScripts: true,
				$(target).ajaxReplace(url,{
						onFailure:function(){
							window.location =	url;
						},
						postBody: '&ajax_source='+source+'&ajax_target='+target
					});
					return false;
			}.bindAsEventListener(this, this.el.href, this.el.id, target);
};

XF_JS.ajaxLinkUpdate = function(el,target){
		this.el = $(el);
    if (!this.el) return false;
		this.el.onclick = function(e, url, source, target){
				$(target).ajaxUpdate(url,{
						evalScripts: true,
						onFailure:function(){
							window.location =	url;
						},
						postBody: '&ajax_source='+source+'&ajax_target='+target
					});
					return false;
			}.bindAsEventListener(this,this.el.href, this.el.id, target);
};

/**
* Container Object for AJAX Reloaded Blocks
*/

XF_JS.ajaxContainer = {
	create: function(el, url, options){
		if ($(el).ajaxContainer){
			if (url) $(el).ajaxContainer.setURL(url);
			return $(el).ajaxContainer;
		} else {
			return new XF_JS.ajaxContainerInstance(el, url, options);
		}
	}
};

XF_JS.ajaxContainerInstance = Class.create();
XF_JS.ajaxContainerInstance.prototype = {
	initialize:function(el,url,options){
    this.options = options || {useBackHistory: false};
        
		this.el = $(el);
    this.checkAnchor(false, url);
		this.setURL(url);
		this.el.ajaxContainer = this;

		if (this.options.periodicalUpdate){
			this.startPerdiodicalUpdater(this.options.periodicalUpdate);
		}

    if (this.options.ajaxFill==true)
      this.reload();
    
    if (this.options.useBackHistory){
      this.pe = new PeriodicalExecuter(this.checkAnchor.bind(this),0.5);
    }
  },
  
  checkAnchor:function(pe, url){
    if (this.options.useBackHistory){
      if (!url) url = this.url;
      url = decodeURIComponent(url);
      if(window.location.hash && window.location.hash.substr(1,1)=='!' && url != window.location.hash.substr(2)){
        this.reload({},window.location.hash.substr(2));
      }
    }
  },
  setURL: function(url){
    if (this.options.useBackHistory){
      if (this.url!=url){
        window.location = '#!'+url;
      }
    }
    this.url = url;
  },
	startPerdiodicalUpdater:function(frequency){
		this.updater = new Ajax.PeriodicalUpdater(this.el, this.url, {
			  frequency: frequency,
			  postBody: '&ajax_target='+this.el.identify()
			});
	},
	stopPerdiodicalUpdater:function(){
		if (this.updater) this.updater.stop();
	},
 	reload: function(params, url, post_params){
  	if ((!url) || typeof(url)=='undefined') url = this.url;
  	url = XF_JS.View.getURL(params, url);
    this.setURL(url);
    
    // POST Parameters, will only be submitted for this reload compared to GET params which will be used for further requests
    var post_once_params = '';
    if (post_params && (typeof(post_params) == 'object')){
      post_once_params = $H(post_params).toQueryString();
    }
  	this.el.ajaxUpdate(url,{postBody: '&ajax_target='+this.el.identify()+'&'+post_once_params, evalScripts: true});
  },
  
  isVisibleInViewport: function(){
    el = this.el;
    var top = el.offsetTop;
    var left = el.offsetLeft;
    var width = el.offsetWidth;
    var height = el.offsetHeight;
    while(el.offsetParent) {el = el.offsetParent; top += el.offsetTop; left += el.offsetLeft; }
    return (top < (window.pageYOffset + window.innerHeight) && left < (window.pageXOffset + window.innerWidth) && (top + height) > window.pageYOffset && (left + width) > window.pageXOffset);
  }
  
};

/**
* Multifield for Form-Helper
*
*/

if(typeof(XForm) == "undefined")
	XForm = {};

XForm.Multifield = Class.create();
XForm.Multifield.prototype = {
	initialize:function(el,options){
		this.multfield_src = $(el);
		if (options != 'undefined')
			this.options = options;

		//Enable shortcut
		var copies = this.multfield_src.up().select('.copy');
		copies.each(function(el){
			shortcut("ENTER",function(){this.duplicate(this.multfield_src)}.bind(this),{target:$(el).down('input'), propagate: false});
		}.bind(this));
	},
	duplicate:function(el){
	 var outer = document.createElement('div');
	 outer.className = 'multifield copy';
	 var el_copy = $(el).cloneNode(true);
	 el_copy.id = false;
	 outer.appendChild(el_copy);
	 new Insertion.Bottom(outer,'<a href="javascript:void(0);" class="icon_remove" onclick="$(this).up().remove();">'+this.options.delete_text+'</a>');
	 $(el).up().appendChild(outer);
   this.onDuplicate(el_copy);
	 try
	 {
	  if (this.options.clear_values) {
	  	el_copy.select('input').each(function(el){
	    	el.value = null;
	    });
		}
	 	el_copy.focus();
	 	el_copy.select();
	 	shortcut("ENTER",function(){this.duplicate(this.multfield_src)}.bind(this),{target:el_copy, propagate: false});
	 }
	 catch(e)
	 {}

	},
	disable:function(){
		var copies = this.multfield_src.up().select('.copy');
		copies.each(function(el){
			$(el).down('input').disable();
		});
		this.multfield_src.next('a').hide();
	},
	enable:function(){
		var copies = this.multfield_src.up().select('.copy');
		copies.each(function(el){
			$(el).down('input').enable();
		});
		this.multfield_src.next('a').show();
	},
  onDuplicate: function(element){}
}

XF_JS.Form = Class.create();
XF_JS.Form.Multifield = XForm.Multifield;

/**
* Populate Options
*/
XForm.Populatefield = Class.create();
XForm.Populatefield.prototype = {
  initialize:function(src,trgt,options){
    this.src_id = src;
    this.trgt_id = trgt;
    this.initField(false);          
    this.WTO = false;
    this.options = $H({
      afterPopulate: Prototype.emptyFunction,
      beforePopulate: Prototype.emptyFunction,
      url: false
    });
    if(options)
      for(o in options)
        this.options[o] = options[o];

    if(!this.options.url){
      this.options.url = this.src.up('form').action ? this.src.up('form').action : window.location.toString();
    }

    this.srctc.XF_JS_Populatefield = this;
    //new Form.Element.Observer(this.src, 0.5, function(){this.scheduleRequest();}.bind(this)); //DW: Changed to Event.observe for better ui speed
  },
  initField:function(directReload){
    this.src = $(this.src_id);
    this.trgt = $(this.trgt_id);
    this.trgtc = this.trgt.up();
    this.srctc = this.src.up();
    Event.observe(this.src, 'change',  this.requestData.bind(this)); 
    if (directReload==true){
      this.requestData();
    }        
  },
  scheduleRequest:function(){
  	if (this.WTO)
			window.clearTimeout(this.WTO);
		this.WTO = window.setTimeout(function(){ this.requestData();}.bind(this),500);
	},
  requestData:function(){
    if (!this.trgtc.select('select')){
      this.trgtc.update('Loading...');
    } else {
      this.trgtc.select('select').invoke('disable');
    }
    this.trgtc.addClassName('ajax_loader_small_right');

    new Ajax.Request(this.options.url, {
        method: 'post',
        postBody: this.src.serialize() + '&populate=' + this.options.target + '&src=' + this.options.src,
        onSuccess: this.populateData.bind(this),
        onFailure: function(){alert('error');}
      });
  },
  populateData:function(r,j){
    this.trgtc.update(r.responseText);
    this.trgtc.removeClassName('ajax_loader_small_right');
    if (this.trgtc.XF_JS_Populatefield){
      // Support cascaded update across multiple levels
      this.trgtc.XF_JS_Populatefield.initField(true);
    }   
  }
}

/**
* XF Form Field Helper to support inputFiltering, displayFormat
* new XF_JS.Form.Field('myField', {inputFilter: 'numeric'});
*/

XF_JS.Form.Field = Class.create();
XF_JS.Form.Field.prototype = {
  initialize: function (field, options) {
    this.field = $(field);
    if (!this.field) return false;
    this.field.xfField = this;
    this.field.getNumericValue = this.getNumericValue.bind(this);
    this.field.formatAsNumeric = this.formatAsNumeric.bind(this);
    this.field.setValue = this.setValue.bind(this);

    this.options = options;
    if (this.options['inputFilter']) this.setInputFilter(options['inputFilter']);
    if (this.options['displayFilter']=='numeric' || options['displayFilter']=='money'){
    	if (this.options['displayFilter']=='money') this.options.decimalCount = 2;
    	this.field.observe('blur', function(){this.formatAsNumeric();}.bind(this));
    	this.formatAsNumeric();
		}
    if (options['autoTitle']){
      this.setInputTitle(); // Init
      this.field.observe('blur', function(){this.setInputTitle();}.bind(this));
      this.field.observe('focus', function(){this.focusInputField();}.bind(this));
      if (this.field.form) $(this.field.form).observe('submit', function(){this.focusInputField();}.bind(this)); // Do not submit caption as value
    }
    if (options['selectOnFocus']){
    	this.field.observe('focus', function(){this.field.select();}.bind(this));
    }
    if (options['autoSize']){
      this.updateAutoSize();
      this.field.observe('keyup', function(){this.updateAutoSize();}.bind(this));
    }
    if (options['submitOnEnter']){
      this.field.observe('keypress', this.submitOnEnter.bindAsEventListener(this));
    }
    if (false || options['autoSuggest']){
      var node = Builder.node('div');
      node.addClassName('autocomplete');
      this.field.insert({after: node});
      this.autoSuggestCompleter = new Ajax.Autocompleter(this.field, node, false, {paramName: 'value', parameters: 'mode=inline', tokens: ' '});
      this.field.observe('keyup', this.autoSuggest.bindAsEventListener(this));
    }
  },
  autoSuggest: function(event){
    if (true){
      if ($(event.target)){
        var word = this.getWordAtCursor();
        if (word.substring(0,1)=='#'){
          // TAG Suggest
          //@todo: Check if tagging is available
          this.autoSuggestCompleter.url = '/tagging/suggest/'; // Enable
          this.autoSuggestCompleter.options.minChars = 2; // Enable
        } else if (word.substring(0,1)=='@'){
          // USER Suggest 
          //@todo: Check if messenger is available
          this.autoSuggestCompleter.url = '/messenger/func/list_user'; // Enable
          this.autoSuggestCompleter.options.minChars = 2; // Enable
        } else {
          this.autoSuggestCompleter.options.minChars = 99999; // Disable
        }
      }
    }
  },
  getWordAtCursor: function(){
    var s = $(this.field).value;
    var pos = $(this.field).selectionStart;
    while (s[pos] == " ") pos--;
    pos = s.lastIndexOf(" ", pos) + 1;
    var end = s.indexOf(" ", pos);
    if (end == -1) end = s.length; 
    var word = s.substring(pos, end);
    return word;
  },
  setInputFilter: function(filter){
    this.field.FieldInputFilter = this;
    if (typeof(filter) == 'string') {
      filters = filter.split(',');
      this.filter = new Array();
      this.regex_filter = new Array();

      filters.each(function(filter) {
        switch (filter) {
					case "money":
          case "numeric":
          case "decimal":
            this.regex_filter.push(',.\\-');
          case "integer":
            this.regex_filter.push('\\d');
            break;
          case "operator":
            this.filter = this.filter.concat([40,42,41,37,43,44,45,46,47,94,60,61,62]);
            break;
          case "alpha":
          case 'string':
            this.regex_filter.push('\\w');
            break;
        }
      }.bind(this));
    }
    this.regex_filter = '['+this.regex_filter.join('')+']';
    this.field.observe('keypress', this.checkKey.bindAsEventListener(this));
  },
  checkKey: function(e) {
    if ((e.charCode < 32) || (this.filter.indexOf(e.charCode)>-1) || String.fromCharCode(e.charCode).match(this.regex_filter)  || document.all)
    {
    	// || document.all was added because IE doesn't work with this yet. (HotFix by SP)
      return true;
		}
    else {
      e.stop();
      return false;
    }
  },
  // Returns a JS Float and uses local number format settings to handle decimal point conversion
  getNumericValue: function(){
    return XF_JS.String.getNumericValue($F(this.field));
  },
  formatAsNumeric: function(){
    var value = this.getNumericValue();
    var min_precision = 0;
    var max_precision = 8;
    if (this.options.decimalCount){
      min_precision = this.options.decimalCount;
      max_precision = this.options.decimalCount;
    }
    this.field.value = value.number_format(min_precision, false, false, max_precision);
  },
  setInputTitle: function(){
    if (this.options['autoTitle'] && $F(this.field)==''){
      this.field.value = this.options['autoTitle'];
      this.field.addClassName('auto_title');
    } else {
      this.field.removeClassName('auto_title');
    }
  },
  focusInputField: function(){
    if (this.options['autoTitle'] && (this.field.hasClassName('auto_title') || this.options['autoTitle']==$F(this.field))){
      this.field.value = '';
      this.field.removeClassName('auto_title');
    }
  },
  setValue: function(val){
  	this.field.value = val;
  	this.setInputTitle();
  	if (this.options['displayFilter']=='numeric') this.formatAsNumeric();
  },
  updateAutoSize: function(){
    this.field.setStyle({height: 'auto'});
    this.field.rows = 1;
    var text = this.field;
    var adjustedHeight = text.clientHeight;
    var maxHeight = false
    if ( !maxHeight || maxHeight > adjustedHeight )
    {
      adjustedHeight = Math.max(text.scrollHeight, adjustedHeight);
      if ( maxHeight )
         adjustedHeight = Math.min(maxHeight, adjustedHeight);
      if ( adjustedHeight > text.clientHeight )
         text.style.height = adjustedHeight + "px";
    }
  },
  submitOnEnter: function(ev){
     if (ev.keyCode==13 && ev.shiftKey==false){
       var form = this.field.up('form');
       if (form && form.submit){
         if (typeof(form.submit) == 'function')
          form.submit(); // Is function
         else 
          form.submit.click() // Is button
       }
       ev.stop();
     }
  }
}


/**
* Ajax Form
* (c) by blueend web:applications
*/

var ajaxForm = Class.create();
ajaxForm.prototype = {
  initialize:function(formID,outputID,defaultSuccessHandler,loadingIndicator){
    //Initial Setup
    this.form = $(formID);
		this.postBody = '';

		//Check Fields
		if(this.form.getInputs('file').size()>0){
			//Detected a file upload field.
			//Ajax Form can NOT be used
			return false;
		}

    if (outputID != undefined && outputID != false)
      this.output = $(outputID);
    else
      this.output = false;

    if (defaultSuccessHandler != undefined)
      this.defaultSuccessHandler = defaultSuccessHandler;
    else
      this.defaultSuccessHandler = false;

		if (loadingIndicator != undefined)
      this.lI = $(loadingIndicator);
    else
      this.lI = false;

    //Add Listeners
    this.form.onsubmit = this.formSubmit.bindAsEventListener(this);

    //Hide Output DIV by default
    if (this.output)
    	this.output.hide();

    //Timed Observer to see if anything changed in the form
    new Form.Observer(this.form, 0.9, function(){this.setSaveStatus(false)}.bind(this));
  },
  setSaveStatus:function(state){
  	this.form_saved = state;
	},
	hasUnsavedChanges:function(){
		return this.form_saved;
	},
  formSubmit:function(successHandler)
  {
	  	if (successHandler != undefined)
	      this.successHandler = successHandler;
	    else
	      this.successHandler = false;

      var url = this.form.action ? this.form.action : document.location;
      this.convertFCK();
			if(this.lI)
				this.lI.show();
      else
        this.showOutput('Loading...','ajax_loader_large_left pad_left');

      //submitting the form via AJAX here
      new Ajax.Request(url, {
        method: 'post',
        postBody: this.form.serialize() + '&'+ this.postBody,
        onSuccess: this.formSubmitSuccess.bind(this),
        onFailure: this.formSubmitFailure.bind(this)
      });
      return false;//Form will not be submitted the original method..
  },
  formSubmitFailure:function(ajaxResponse,jsonResponse)
  {
  	if(this.lI)
			this.lI.hide();
    this.showOutput('Form Sending failed','error');
    //if (confirm('Try the usual submit?'))
    //{
      //Clear Eventlistener?
      //this.form.submit();
    //}
  },
  formSubmitSuccess:function(ajaxResponse)
  {
  	jsonResponse = ajaxResponse.headerJSON;

  	if(this.lI)
			this.lI.hide();

		if(jsonResponse == 'undefined')
		{
			jsonResponse = {};
			jsonResponse.formOK = false;
		}

    try{
      Ext.QuickTips.init();
    }
    catch(e){
    }

		if (ajaxResponse.responseText != "")
		{
			var status = jsonResponse.formOK ? 'success' : 'error';
    	this.showOutput(ajaxResponse.responseText, status);
    }

    //Reset Field errors
    this.form.select('.formError').invoke('removeClassName','formError');

    //check JSON for input errors...
    if(!jsonResponse.formOK && jsonResponse.fieldErrors)
    {
      jsonResponse.fieldErrors.each(function(t){
        if ($(t.field))
        {
        	$(t.field).addClassName('formError');
	        try{
	          new Tooltip(t.field, t.err_msg);
	        }catch(e){
	          $(t.field).title = t.err_msg;
	        }
				}
      });
    }
    if (jsonResponse.formOK && this.defaultSuccessHandler)
      this.defaultSuccessHandler(ajaxResponse.responseText,jsonResponse);
    if (jsonResponse.formOK && this.successHandler)
      this.successHandler(ajaxResponse.responseText,jsonResponse);

  },
  convertFCK:function(){
  	//Check for FCK Instances and retrieve HTML prior AJAX call
  	try{
	  	var FCKInstances =$H(FCKeditorAPI.__Instances).keys();
			FCKInstances.each(function(i){
				if(!$('FCKout_'+i))
          new Insertion.After(i+'___Frame','<input type="hidden" id="FCKout_'+i+'" name="'+i+'" value="">');

				$('FCKout_'+i).value = FCKeditorAPI.GetInstance(i).GetHTML();
				$(i).name = '_empty';
			});
		}catch(e){}
  },
  showOutput:function(text,status)
  {
    //Ggf noch ein Parsing/Transformation etc.
    if (this.output)
    {
    	if (this.output.hasClassName('status') || this.output.className == ''){
    		this.output.className = 'status '+status;
    	}

	    this.output.innerHTML = text;
	    //If invisible show it now
	    if (!this.output.visible())
	    {
	      try{
	        Effect.Appear(this.output,{duration:0.6, queue: {position:'end', scope: 'ajaxform', limit:1}});
	      }
	      catch(e)
	      {
	        this.output.show();
	      }
	    }
	    else
	    {
	    	try{
	        new Effect.Pulsate(this.output,{pulses: 1, queue: {position:'end', scope: 'ajaxform', limit:1}});
	      }
	      catch(e)
	      {
	        this.output.show();
	      }
			}
		}
		else if (status == 'error')
		{
			Control.Modal.open(text);
		}
  },
  reset:function(){
  	this.form.reset();
	}
}
XF_JS.Form.ajaxForm = ajaxForm;


/*
* Create A Wizard DIV-Based
* (c) by blueend web:applications
*/
var pageWizard = Class.create();
pageWizard.prototype = {
	initialize:function(elID){
		this.wizard = $(elID);
		this.required_fields = new Array();
		this.pages = $$('#'+elID+' .page');
		this.pages.invoke('hide');
		this.pages[0].show();
		this.currentPage = 0;
		this.form = this.wizard.up('form');
		if (this.form){
			this.form.onsubmit = this.formsubmit.bindAsEventListener(this);
		}
	},

	nextPage:function(){
		this.gotoPage(this.currentPage+1);
	},

	prevPage:function(){
		this.gotoPage(this.currentPage-1);
	},

	gotoPage:function(pageNum){
	  if (pageNum<0) pageNum = 0;
	  if (pageNum>this.pages.length) pageNum = this.pages.length;
	  error = false;
		if (pageNum > this.currentPage) error = this.checkRequiredFields(this.currentPage);
		if (!error)
		{
			this.pages.each(function(el,page){
				if (el.visible() && (page != pageNum))
				{
					try{Effect.BlindUp(el,{duration: 0.25, queue: 'front'});}
					catch(e){el.hide();};
				} else if (page == pageNum){
					try{Effect.BlindDown(el,{duration: 0.25, queue: 'end'});}
					catch(e){el.show();};
				}
			});
			this.currentPage = pageNum;
		}
	},

	addRequiredField: function(fieldID, options) {
		if ($(fieldID))
			this.required_fields.push({field:$(fieldID), options: options});
	},

	checkRequiredFields: function(pageNum) {

	  currentPage = this.pages[pageNum];
	  error = false;
		this.required_fields.each(function(el){

			// Remove old error classes
		  el.field.removeClassName('error');
		  if (el.field.up('.form_row')) el.field.up('.form_row').removeClassName('error');

			// Only elements in the current page are relevant for checking
			if (el.field.descendantOf(currentPage) && el.field.style.display!='none')
			{
				// Execute Checks
				field_error = false;
				if (el.field.value=='') field_error = true;
				if (el.options.minSize && (el.field.value.length<el.options.minSize) ) field_error = true;
				if (((el.options.checkCondition)) && (el.options.checkCondition()==false)) field_error = false;

				// Show possible errors
				if (field_error)
				{
				  if (el.field.up('.form_row'))
				  	el.field.up('.form_row').addClassName('error');
				  else
					  el.field.addClassName('error');
					error = true;
				}
			}
		})
		return error;
	},

	formsubmit: function(e){
		if ((this.currentPage + 1) < this.pages.length){
			Event.stop(e);//Form is not considered finished
			this.nextPage();
		}else{
			//Check before submitting
			if (this.checkRequiredFields(this.currentPage)){
				Event.stop(e);
			}
		}
	}
};

XF_JS.pageWizard = pageWizard;


/*
* Prototype based TABs (Really really unobtrusive)
* (c) by blueend web:applications
*/
var smartTabs = Class.create();
smartTabs.prototype = {
	initialize: function(tabID, options)
	{
		try{
			if(typeof tabID == 'object'){
				this.tab_element = $(tabID);
				tabID = $(tabID).identify();
			}else{
				this.tab_element = $(tabID);
			}
			if (options && options.use_cookie == false){
				this.cookie = false;
				this.selected = 0;
			}else{
	      var cookie_settings = {expires:9999999, path: '/'};
				this.cookie = new CookieJar(cookie_settings);
				this.cookie_id = 'smartTab_'+tabID;
				this.selected = this.cookie.get(this.cookie_id);
				this.selected = (this.selected>0) ? this.selected : 0;
			}
		}catch(e){
			this.cookie = false;
			this.selected = 0;
		}
		if (this.tab_element)
		{
		  this.tab_element.tabs = this;
		  links = new Array();
		  ajax_hrefs = new Array();
		  this.loaded_tabs = new Array();
		  this.tab_element.addClassName('smartTabs');
			this.options = options;
			this.hidden_tabs = false;
			this.tabid_by_name = new Object();
			if (options && options.head_tag) head_tag=options.head_tag; else head_tag='h2';
      var tab_class = 'tab';
      if (options && options.tab_class) tab_class=options.tab_class; else tab_class='tab';      
      this.tabs = $$('#'+tabID+' .'+tab_class);
      if (options && options.selected) selected=options.selected; else selected=this.selected;
			if (options && options.hide_heading) hide_heading=true; else hide_heading=false;
			if (options && options.tab_nav_position){
				tab_nav_position=options.tab_nav_position;
			} else {
				if (this.tab_element.hasClassName('smartTabs_left')){
					tab_nav_position='left';
				}else if (this.tab_element.hasClassName('smartTabs_right')){
					tab_nav_position='right';
				}else{
					tab_nav_position='top';
				}
			}
			
			if (selected<0){
				selected = 0;
			} else if (selected>this.tabs.length-1) {
				selected = this.tabs.length-1; // Don't run out of bounds
			} 
			this.tab_element.addClassName('smartTabs_'+tab_nav_position);
			this.selected = selected;
			var i = 0;
			
			if(window.location.hash){
				var hash_select = window.location.hash.substring(1);
			}else {
				var hash_select = false;
			}

			has_hidden_tabs = false;
			var skeleton = new Element('div').addClassName('tab_nav');
      this.tabs.each(function(el){
				el.hide();
				el.id = tabID+'_'+i;
				headings = $$('#'+tabID+' #'+el.id+' > '+head_tag);
				my_class_addon = '';
				ajax_href = '';
				try {
					caption = headings[0].innerHTML;
					if (headings[0].down('a'))
					{
						ajax_href = headings[0].down('a').href;
						caption = headings[0].down('a').innerHTML;
					}
					if (hide_heading) headings[0].hide();
					my_class_addon = headings[0].className;

				} catch(e){caption = 'Tab '+i};
				
				if (i==selected){ 
					my_class = 'selected'; 
				} else if(hash_select && el.id == hash_select) {
					selected = i;
					this.selected = i;
					my_class = 'selected';
				}else { 
					my_class=''; 
				}

				var link = new Element('a',{href:ajax_href+'#'+el.id, 'class':my_class+' '+my_class_addon}).update(caption);
				if (headings[0].hasClassName('hidden_tab'))
				{
					has_hidden_tabs = true;
					$(link).hide();
				}
				links.push(link);
				skeleton.insert(link);
				ajax_hrefs.push(ajax_href);
				i++;
			});
			this.ajax_hrefs = ajax_hrefs;
			this.links = links;
			this.links.each(function(el){
				el.onclick = function(){this.clickTab(el); return false;}.bindAsEventListener(this);
			}.bind(this));

   		if(has_hidden_tabs){
				link = new Element('a', {href:'#'});
				link = $(link);
				link.innerHTML = "&gt;";
				link.addClassName('hidden_tab_link');
				link.onclick = function(){this.showHiddenTabs(); return false;}.bindAsEventListener(this);
				skeleton.insert(link);
				this.hidden_tabs=true;
			};
			if (this.links[selected]) this.links[selected].onclick();
			this.tab_element.insert({top:skeleton});
			if (tab_nav_position != 'top'){
				var h = skeleton.getHeight();
				this.tabs.invoke('setStyle','min-height:'+h+'px;_height:'+h+'px;');
			}
			
		}
	},

	clickTab: function(tab_element)
	{
		var tabID = tab_element.href.match(/#(\w.+)/)[1];

		if ((this.options && this.options.collapse==true) && this.selected_el==tab_element){
			// Clicked on current tab --> Collapse
			this.tabs.each(function(el){ el.hide(); });
			this.links.each(function(el){  el.removeClassName('selected');});
			selected = false; selected_el=false;
			this.tab_element.addClassName('collapsed');
		} else {
			// Regular tab click mode
			this.tabs.each(function(el){ if (el.id==tabID) el.show(); else el.hide();});
			i=0;
			this.links.each(function(el){ if (el==tab_element){$(el).addClassName('selected'); selected=i; selected_el = el;} else $(el).removeClassName('selected'); i++;} );
			this.tab_element.removeClassName('collapsed');
		}

		this.selected = selected;
		this.selected_el = selected_el;
		this.loadTab(selected);
		try{
			this.cookie.put(this.cookie_id,selected);
		}catch(e){}
		return false;
	},

	next: function() { this.select(this.selected+1); },
  prev: function() { this.select(this.selected-1); },
  first: function(){ this.select(0); },
  last: function() { this.select(999999); },
  collapse: function(){this.select(this.selected); this.tab_element.addClassName('collapsed');},

	select: function(selected)
	{
		if (isNaN(parseInt(selected))) // is no Integer? -> Get TabID by Name first!
			if (! (selected = (this.getTabIDbyName(selected))))
				return false;

		// Don't run out of bounds
		if (selected<0) selected = 0; else if (selected>this.tabs.length-1) selected = this.tabs.length-1;
		if (this.links[selected].hasClassName('hidden_tab') && this.hidden_tabs) this.showHiddenTabs();
		this.links[selected].onclick();
	},

	getTabIDbyName: function(search_name)
	{
			// Search by name!
			var count = 0;
			var selected = false;
			this.tabs.each(function(el){
				if (el.attributes['name'])
				{
					if (el.attributes['name'].value == search_name)
					{
						selected = count;
					}
				}
				count++;
			});
			return selected;
	},

	loadTab: function(selected, reload)
	{
	  if (typeof(reload)=='undefined') reload = false;;
  	element = this.tabs[selected];
  	if (this.ajax_hrefs[selected] && (reload || !this.loaded_tabs[selected]))
  	{
	  	element.innerHTML = '';
			Element.addClassName(element, 'ajax_loader_large');
	    var options = Object.extend(
    			{
    				onSuccess:function(selected,response,json){
    						Element.update(this.tabs[selected],response.responseText);
    						Element.removeClassName(this.tabs[selected], 'ajax_loader_large');
								this.loaded_tabs[selected] = true;
    					}.bind(this,selected)
    			}
    			, arguments[2] || {});
					new Ajax.Request(this.ajax_hrefs[selected], options);
		}
	},
	
	showHiddenTabs: function()
	{
		this.links.each(function(el){
			if (el.hasClassName('hidden_tab'))
				try {Effect.Appear(el,{duration:0.5});} catch(e){ el.hide();};
		});
		this.tab_element.getElementsBySelector('.hidden_tab_link').each(function(el){el.hide()});
	}
};
XF_JS.smartTabs = smartTabs;

/**
* Prototype based Tree-Component
* (c) by blueend web:applications
*/
var smartTreeNode = Class.create();
	smartTreeNode.prototype = {
    initialize: function(NodeElement, ParentNode, TreeRoot, options)
    {
    	// Initialize Node
    	if (NodeElement.el) return false; // Already initialized!
    	NodeElement.el = this;
    	this.Node = NodeElement; // UL Element
    	this.ParentLI = this.Node.up('li');
    	this.ParentNode = ParentNode; // Reference to Parent Node (smartTreeNode Obj)
    	this.TreeRoot = TreeRoot; // Reference to Main Tree Node (smartTree Obj)

    	if ((this.TreeRoot.nodestore.indexOf(NodeElement.readAttribute('rel')) < 0 && !NodeElement.previous('span.selected')) ||
    			(this.Node.hasClassName('ajax_not_loaded'))){
        	NodeElement.hide();
          NodeElement.up().addClassName('closed');
			} else {
					NodeElement.up().addClassName('expanded');
			}

			var li_span = Builder.node( 'span', {className: 'icon'});
			li_span.innerHTML = '&nbsp;';
			li_span.onclick = function(){this.toggle()}.bindAsEventListener(this);
      this.Node.up().insert({top: li_span});

      var caption = this.Node.down('a');
      if (caption)
        if (caption.hasClassName('caption'))
          caption.onclick = function(){this.toggle();}.bindAsEventListener(this);

      // Initialize Childs
      this.TreeRoot.initializeChildNodes(this.ParentNode, this.TreeRoot);
    },

    refresh: function()
    {
    	if (this.TreeRoot.options.ajaxURL && this.Node.hasClassName('ajax_not_loaded')){
    		this.ParentLI.addClassName('ajax_loading');
    		this.Node.ajaxReplace(this.TreeRoot.options.ajaxURL,{onComplete: this.refresh_finished.bindAsEventListener(this), parameters: {action: 'load', tree_parent_id: this.ParentLI.readAttribute('rel')}});
    	}
    },

    refresh_finished: function()
    {
	    this.Node.removeClassName('ajax_not_loaded');
	    this.ParentLI.removeClassName('ajax_loading');
	    this.Node = this.ParentLI.down('ul');
      this.TreeRoot.initializeChildNodes(this.ParentLI, this.TreeRoot);
      if (this.TreeRoot.options.onNodeRefresh && (typeof this.TreeRoot.options.onNodeRefresh === 'function')){
        this.TreeRoot.options.onNodeRefresh(this);
      }
    },

    collapse: function()
    {
        this.ParentLI.removeClassName('expanded');
        this.ParentLI.addClassName('closed');
        this.TreeRoot.saveVisibility(this.ParentLI,'hide');
        Effect.toggle(this.Node,'blind',{duration: 0.1});
    },

    expand: function()
    {
    		this.ParentLI.removeClassName('closed');
        this.ParentLI.addClassName('expanded');
        this.TreeRoot.saveVisibility(this.ParentLI,'show');
        Effect.toggle(this.Node,'blind',{duration: 0.1});
        this.refresh();
    },

    toggle: function()
    {
    	if (this.Node.style.display!='none')
    		this.collapse();
    	else
    		this.expand();
    }
	};

var smartTree = Class.create();
  smartTree.prototype = {
    initialize: function(ID, options)
    {
    	try{
      	var cookie_settings = {expires:9999999, path: '/'};
				this.cookie = new CookieJar(cookie_settings);
				this.cookie_id = 'smartTree2_'+ID;
				this.nodestore = this.cookie.get(this.cookie_id);
				this.nodestore = (this.nodestore == null) ? [] : $A(this.nodestore);
				//console.log(this.nodestore);
			}catch(e){
				this.cookie = false;
				this.cookie_id = false;
				this.nodestore = [];
			}

      this.element = $(ID);
      this.options = options || {ajaxURL: false}; // Merge with default Options
      if (this.options.forceNodeDisplay)
      {
        this.options.forceNodeDisplay.each(function(add_id){
          this.nodestore.push(add_id);
        }.bind(this));
      }

			var span = Builder.node( 'span', {className: 'icon'} );
			span.innerHTML = '&nbsp;';

			this.initializeChildNodes($(ID), this);

			if (!this.options.ajaxLoading){ // HIde Options for AJAX Menus
	      if ((!this.options.hide_context_menu) && (!(navigator.appVersion.indexOf('MSIE')>0)))
	      {
	          var myMenuItems = [
	            { name: 'Expand all', callback: function(ev) {this.expand_all();}.bind(this)},
	            { name: 'Collapse all', callback: function(ev) {this.collapse_all();}.bind(this)}
	          ];
	          new Proto.Menu({
	            selector: '#'+ID, // context menu will be shown when element with id of "contextArea" is clicked
	            menuItems: myMenuItems // array of menu items
	          });
	      }
			}

      if(this.options.expandAll){
        this.expand_all();
      }
    },

    initializeChildNodes: function(parentNode, treeNode){
      //parentNode.down('ul').childElements().each(function(el){console.log(el)});

			if (!parentNode.is_initialized){
	      parentNode.select('li.has_childs').each(function(el){
	        if (!el.down('ul')){
	          el.insert({bottom: Builder.node( 'ul', {className: 'ajax_not_loaded'})});
	          el.removeClassName('has_childs');
	        }
	      });
	      parentNode.is_initialized = true;


    		this.elements =  $(parentNode).select('*:not(ul) ul');
	      this.elements.each(function(el)
	      {
					new smartTreeNode(el, parentNode, treeNode);
	      }.bind(this));
			}
    },
    
    enableDragDrop: function(){
        if (!this.options.ajaxURL) return false;
        if (typeof(SortableTree) == "undefined") return false;
        var tree = new SortableTree(
            this.element.down('ul'), 
            {
              draggable: {
                handle: 'move_handle'
              }
              ,
              droppable: {
                container: ':not(.file)'
              },
              onDrop: function(drag, drop, event){
                if (drag.element.up('li')) parentid = drag.element.up('li').getAttribute('rel'); else parentid = 0;
                var parent_item_id = drag.element.up('ul').identify();
                var subitem_list = [];
                drag.element.up('ul').up().select('#'+parent_item_id+'>li').each(function(el){
                  subitem_list.push(el.getAttribute('rel'));
                });
                params = ({action: 'move', parent: parentid, 'subitems[]': subitem_list});
                new Ajax.Request(this.options.ajaxURL, {parameters: params});
              }.bind(this)
            });
         tree.setSortable();
    },

    saveVisibility: function(ul_element, visibility)
    {
       try
       {
       		var id_value = ul_element.readAttribute('rel');
       		if (id_value){
	          if (visibility == 'show') {
	            this.nodestore.push(id_value);
	          } else {
	            this.nodestore = this.nodestore.without(id_value);
	          }
	          this.cookie.put(this.cookie_id,this.nodestore);
					}
       }catch(e){};
    },
    expand_all: function()
    {
      this.elements.each(function(el)
      {
        if(el && el.style.display=='none')
        {
          el.up().addClassName('expanded');
          el.up().removeClassName('closed');
          Effect.BlindDown(el,{duration: 0.2});
          this.saveVisibility(el,'show');
        }
      }.bind(this))
    },
    collapse_all: function()
    {
      this.elements.each(function(el)
      {
        if(el && el.style.display!='none')
        {
          el.up().removeClassName('expanded');
          el.up().addClassName('closed');
          Effect.BlindUp(el,{duration: 0.2});
          this.saveVisibility(el,'hide');
        }
      }.bind(this))
    }
  };
XF_JS.smartTree = smartTree;

/*
* Create A Editor Form to save serialized inputs
* (c) by blueend web:applications
*/
var serializeEditor = Class.create();
serializeEditor.prototype = {
	initialize:function(editorPane,options){
		this.editorID = 'SEP'+new Date().getTime()+Math.ceil(Math.random()*10000);

 		this.options = Object.extend({
				afterAdd: Prototype.emptyFunction,
				beforeAdd: Prototype.emptyFunction,
				fieldTitles: [],
				fieldSeparator: ';',
				rowSeparator: '\n',
				editorTitle: 'Editor'
	    }, options || {});

		this.editorPane = $(editorPane);
		this.initEditorForm();
	},
	showEditor:function(container){
		if (container && typeof(container)!=undefined){
			$(container).appendChild(this.editor);
		}else{
		this.editorPane.up().insertBefore(Builder.node('div',{className:'xf_dialog'},this.editor),this.editorPane);
		}
	},
	initEditorForm:function(){
		var editorForm = Builder.node('form',{id:this.editorID});

		this.options.fieldTitles.each(function(title){
			new Insertion.Bottom(editorForm,'<div class="form_row"><label>'+title+'</label><input type="text" name="record[]" value=""></div>');
			});
		var b = Builder.node('a',{href:'javascript:void(0)',className:'btn'},'Add Record');
		b.onclick = function(){this.addRecord(editorForm.serialize(true));}.bindAsEventListener(this);
		editorForm.appendChild(b);
		this.editor = editorForm;
	},
	clearEditorForm:function(){
		this.editor.getInputs('text').each(function(i){i.value='';});
	},
	addRecord:function(record){
		var flatRecord = Object.values(record).flatten().join(String(this.options.fieldSeparator));
		switch(this.editorPane.tagName.toLowerCase()){
			case 'textarea':
			case 'input':
				this.editorPane.value+=flatRecord+this.options.rowSeparator;
				break;

			default:
			 	this.editorPane.innerHTML+=flatRecord+this.options.rowSeparator;
				break;
		}
		this.clearEditorForm();
	}
}

/**
* Confirm Dialog
* (c) by blueend web:applications
*/

var xconfirm = Class.create();
xconfirm.prototype = {
 	initialize:function(dialog_text,actionHandler,confirmAnswers, postLink, confirmIcons){
		this.actionHandler = actionHandler;
    if (typeof(confirmIcons)=='undefined') var confirmIcons = [];
    
		if (confirmAnswers==undefined){
			confirmAnswers = ['Yes','No'];
      confirmIcons = ['icon_ok', 'icon_remove'];
			this.confirmAnswersDefault = true;
		}
    this.post = (postLink===true);
    this.defaultAnswer = confirmAnswers[0]; //First Answer is Default Answer
		this.confirmAnswers = confirmAnswers;

		//Spawn the dialog
    this.container = document.createElement('div');

		var title = document.createElement('div');
		title.className = 'title';
		title.appendChild(document.createTextNode("Confirm"));
		this.container.appendChild(title);

    var content = document.createElement('div');
    content.className = 'content';
    var inner = document.createElement('div');
    inner.className = 'xfconfirm_content';
    inner.appendChild(document.createTextNode(dialog_text))
    content.appendChild(inner);
    this.container.appendChild(content);
    
		var answers = document.createElement('div');
		answers.className = 'buttons';
    var i = 0;
		confirmAnswers.each(function(answer) {
			var link = document.createElement('a');
			link.href = 'javascript:void(0);';
			link.className='btn large answer ' + answer.toLowerCase();
      if (confirmIcons[i]){
        link.innerHTML = '<span class="'+confirmIcons[i]+'">'+answer+'</span>';
      } else {
			  link.innerHTML = answer;
      }
			link.onclick = function(e,a){
						this.handle_response(e,a);
					}.bindAsEventListener(this,answer);
			answers.appendChild(link);
      i++;
		}.bind(this));
		content.appendChild(answers);
		Element.addClassName(this.container,'xf_dialog');
		this.modal = new Control.Modal.open(this.container,{opacity: 0.5, width: 500, overlayCloseOnClick: false});
	},

	handle_response:function(e,a){
		Control.Modal.close();
		if (typeof this.actionHandler == 'function')
			if (this.confirmAnswersDefault) {
				var answer = (a == this.defaultAnswer);
				return this.actionHandler(answer);
			}else{
				return this.actionHandler(a);
			}
		else if(Object.isElement(this.actionHandler)){
			this.actionHandler = $(this.actionHandler);
			var href = this.actionHandler.readAttribute('href');
			if (this.actionHandler.actionHandler != undefined){
				href = this.actionHandler.actionHandler;
			}else if (href!=''){
				this.actionHandler.href = 'javascript:void(0);';
				this.actionHandler.actionHandler = href;
			}
			if(a == this.defaultAnswer){
        XF_JS.View.linkTo(href, this.post);
      }
		}else if(a == this.defaultAnswer)
      return XF_JS.View.linkTo(this.actionHandler, this.post);
	}
}
XF_JS.confirmDialog = xconfirm;

/**
* Add Special AutoUpdater to selects
*
*/
Element.addMethods({
  ajaxUpdate: function(element, url, options){
    element = $(element);
    element.addClassName('ajax_loader_small_right');
    var options = Object.extend({
    				evalScripts: true, // By default only enabled in Ajax.Request
						onFailure:function(){
						},
						onSuccess:function(){
							XF_JS.ajaxContainer.create(this, url); // Save URL to DOM Element --> Used by other AJAX Functions
							this.removeClassName('ajax_loader_small_right');
						}.bind(element)
					}, arguments[2] || {});
		if (url == 'undefined') url = element.ajaxContainerCurrentURL; // Use previous URL
    new Ajax.Updater(element, url, options);
    return element;
  }
});

Element.addMethods({
  ajaxReplace: function(element, url){
    element = $(element);
    var options = Object.extend(
    		{
    			onSuccess:function(response,json){
              var ajaxContainerCopy = this.ajaxContainer;
    				 	this.replace(response.responseText);//Assumes you have decent HTML here ;)
              this.ajaxContainer = ajaxContainerCopy;
    				 	XF_JS.ajaxContainer.create(this, url); // Save URL to DOM Element --> Used by other AJAX Functions
    				}.bind(element)
    		}
    		, arguments[2] || {});
    if (url == undefined) url = element.ajaxContainerCurrentURL; // Use previous URL
		new Ajax.Request(url, options);
    return element;
  }
});

/**
* Format Number in desired float format
* @param int Minimum Float Count, if no max is set the max will be the same as min causing a fixed decimal length, e.g. 2 results always in 2 digits, set to false for auto precision
* @param string Thousand Sep (use false for current local setting)
* @param string Decimal Sep (use false for current local setting)
* @param int Max Float Count
*/

var maxdecimals=2;
Number.prototype.number_format = function(decimals, ts, ds, maxdecimals)
{
   if((ts == undefined) || (ts==false)) ts = XF_JS.i18n.thousandSep;
   if((ds == undefined) || (ds==false)) ds = XF_JS.i18n.decimalPoint;
   if(isNaN(this)) return undefined;
   if(decimals === false){ decimals = 0; maxdecimals=99; }
   if(decimals < 0) return undefined;
   if(decimals == undefined) decimals = false;
   if(maxdecimals == undefined) maxdecimals = decimals;
   //   ------------------
   //   thousand separator
   //   ------------------
   var returned = this;

   var nkcount = returned.toString().split('.');
   if (nkcount && nkcount[1])
   	nkcount = nkcount[1].length;
	else
		nkcount = 0;

   if (decimals > 0 && maxdecimals > 0 && nkcount > maxdecimals)
   returned = returned.toFixed(maxdecimals);
   returned = returned.toString().split('.');

   var str_begin = returned[0];
   var str_after = returned[1];
   if (str_after == undefined)
   {
   	str_after = new String();
   }
   var temp_str = new String();
   var i = 0;
   while(i <= str_begin.length)
   {
   		if(i%3==0 && i!=0 && i < str_begin.length)
      	temp_str += str_begin.substr(str_begin.length-i,1) + ts ;
      else
      	temp_str += str_begin.substr(str_begin.length-i,1);
      i++;
   }
   if(maxdecimals > 0)
   {
      str_after = str_after.substr(0,maxdecimals);
      if(str_after.length < decimals)
      {
         while(str_after.length < decimals)
         {
            str_after += '0';
         }
      }
      if (str_after.length>0)
        str_after = ds + str_after;
   }
   else if (maxdecimals == 0)
   {
   	str_after = '';
   }
   i = temp_str.length;
   returned = new String();
   while(i > 0)
   {
   	i--;
		returned += temp_str.substr(i,1);
   }
   if(maxdecimals>0)
   {
      return (returned + str_after);
   }
   return returned;
}


Element.addMethods({
  modalOpen: function(element, options){
    element = $(element);

      // Open Link as AJAX Modal
      var options = Object.extend(
      {
			  loading: true,
			  width: 400,
			  onFailure: function(url){
				  window.location = url;
				  this.href = url;
			  }.bind(element,element.href),
			  onSuccess: function(url){
				  this.href = url;
			  }.bind(element,element.href)
      }
      , arguments[1] || {});
      var modal = new Control.Modal(element, options);
      modal.open();
      element.href = 'javascript:void(0);';
  
    return element;
  }
});

Element.addMethods({
  smartMenu: function(element, event, link_container, css_class){
  		var options = Object.extend({
	      tag: "a",
	      position: "element"
	    }, arguments[3] || {});

  		if (!element.menu)
  		{
    		var items = [];
		    if ($(link_container))
		    	var element_container = $(link_container).getElementsBySelector(options.tag);
		    else
		      var element_container =  $$('#'+link_container+' '+options.tag);

		   element_container.each(function(el){
	    		$(el).addClassName('enabled');
					var item = {content: el};
					items.push(item);
		    })
		    var parent_el = element.up(); // Parent Element always gets class if menu is visible
		    element.menu = new Proto.Menu({selector: '#nononoonono', menuItems: items, position: options.position, delayedhide: true, className: 'xf_menu desktop '+css_class,
		    																beforeShow: function(parent_el){if (parent_el){parent_el.addClassName('smartMenuVisible')};}.bind(this,parent_el),
		    																beforeHide: function(parent_el){if (parent_el){parent_el.removeClassName('smartMenuVisible')};}.bind(this,parent_el)
		    															});
		    element.menu
			}
	    element.menu.show(event);
	    return element;
	}
});


/**
* Mouse-Attached AJAX Loader
* new XF_JS.ajaxLoader('ajax_loader');
*/
XF_JS.ajaxLoader = Class.create();
XF_JS.ajaxLoader.prototype = {
 initialize:function(el,options){
    this.el = $(el);
    this.offX = 15;
    this.offY = 15;
    Ajax.xfRequestCount = 0;//make sure this is zero when we start..
    document.onmousemove = this.follow.bindAsEventListener(this);
    Ajax.Responders.register({
      onCreate: function() {
      	Ajax.xfRequestCount++;
        if(this.el && Ajax.xfRequestCount>0) {
          Effect.Appear(this.el,{duration:0.2});
        }
      }.bind(this),
      onLoaded: function() {
      	Ajax.xfRequestCount--;
        if(this.el && Ajax.xfRequestCount==0)
          Effect.Fade(this.el,{duration:0.2});
      }.bind(this)
    });
  },
  mouseX: function(evt)
  {
    if (!evt) evt = window.event;
    if (evt.pageX) return evt.pageX;
    else if (evt.clientX)
    return evt.clientX + (document.documentElement.scrollLeft ?  document.documentElement.scrollLeft : document.body.scrollLeft);
    else return 0;
  },
  mouseY: function(evt)
  {
    if (!evt) evt = window.event;
    if (evt.pageY) return evt.pageY;
    else if (evt.clientY)return evt.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
    else return 0;
  },
  follow: function(evt)
  {
   this.el.style.visibility = 'visible';
   this.el.style.left = (parseInt(this.mouseX(evt))+this.offX) + 'px';
   this.el.style.top = (parseInt(this.mouseY(evt))+this.offY) + 'px';
  }
}

XF_JS.FSLoader = {
	show:function(message){
		try{
			window.scroll(0,0);
			Effect.Appear('loading-mask',{duration:0.5,to:0.7});
			if (message == undefined)
				message = 'Loading';
			$$('#loading .loading-indicator')[0].innerHTML = message+'...'+'<div class="upload_status" style="display: none;"></div>';
			$('loading').show();
		}catch(e){

		}
	},
	hide:function(){
		try{
			Effect.Fade('loading-mask',{duration:0.5});
			$('loading').hide();
		}catch(e){

		}
	},
  isVisible: function(){
    return $('loading').visible();  
  },
	setUploadStatus:function(message){
		try{
			if ($$('#loading .loading-indicator .upload_status')){
				$$('#loading .loading-indicator .upload_status')[0].show();
				$$('#loading .loading-indicator .upload_status')[0].update(message);
			}
		} catch(e){}
	}

};

/**
*  @desc    SelectList - Adds a select class to a list of elements on mouse click, supports multi selects (using CTRL)
*           Usage: new XF_JS.SelectList('IDofOuterElement');
*  @author  dw
*/
XF_JS.selectList = Class.create();
XF_JS.selectList.prototype = {
  initialize:function(el,options)
  {
    // Set Options
    this.options = options || { };
    this.select_class = this.options.select_class || 'select';
    this.select_cb_class = this.options.select_cb_class || 'select_cb'; // Checkbox class
    this.detail_class = this.options.detail_class || 'detail';
    this.detail_target = this.options.detail_target || false;
    this.multi_select = this.options.multi_select || false;
    this.onSelect = this.options.onSelect || Prototype.emptyFunction;

    // Initialize
	  if (Prototype.Browser.IE){document.onselectstart = function(){return false;}} // Prevent IE to mark text elements
    this.select_elements = $(el).select('.'+this.select_class);
    this.select_elements.each(
      function(el){
        el.onclick = this.onclick.bindAsEventListener(this,el);
        el.select('input.'+this.select_cb_class).each(
					function(checkbox)
					{
						checkbox.onclick = this.toggleElement.bindAsEventListener(this,el,checkbox);
						this.toggleElement(this,el,checkbox);
					}.bind(this)
        );
      }.bind(this)
    );
  },

  onclick: function(e, el)
  {
	  var evt = navigator.appName=="Netscape" ? e:event;
	  ctrlPressed = evt.ctrlKey;
	  shiftPressed = evt.shiftKey;
	  this.selectElement(el,ctrlPressed, shiftPressed);
  },

  selectElement: function(el, addToSelection, rangeSelect)
  {
    if (addToSelection == undefined) addToSelection = false;

    if (!this.multi_select || !addToSelection) {
      this.select_elements.each(
        function(el){
          el.removeClassName('selected');
        }
      );
    };

    if (rangeSelect){
	    // Handle SHIFT Range Select
    	this.in_range = false;
      this.select_elements.each(
        function(e){
        	if (!this.in_range && (e==this.last_select_el || e==el)){ this.in_range = 1}// Start Range Select
          if (this.in_range){e.addClassName('selected'); this.in_range++;}
          if (this.in_range>2 && (e==this.last_select_el || e==el)) this.in_range = false; // End Range Select
        }.bind(this)
      );
		}
    else
    {
    	// Handle Single Item Select
	    $(el).toggleClassName('selected');
		}

    if (this.detail_target) {
      if (this.detail_container)
      {
        this.moveChilds($(this.detail_target),this.detail_container);
      }
      this.detail_container = $(el).select('.'+this.detail_class).first();
      if (this.detail_container)
      {
        this.moveChilds(this.detail_container, $(this.detail_target));
      } else {
        //$(this.detail_target).innerHTML = '';
      }
    }
		if (!rangeSelect) this.last_select_el = $(el);
    if (this.onSelect) this.onSelect(el);
  },

  toggleElement: function(event, el,checkbox)
  {
		if (checkbox.checked)
		{
			el.removeClassName('disabled');
			el.addClassName('enabled');
		}
		else
		{
			el.removeClassName('enabled');
			el.addClassName('disabled');
		}
  },

  moveChilds: function(source_node, target_node)
  {
    var el = source_node.childNodes[0];
    while (el)
    {

        try{
          target_node.appendChild(el);
        } catch(e)
        {}
        el = $(el).next();
    }
  }
}


/* FOREIGN FUNCTIONS -------------------------------------------------------------------------------------------- */

/**
* http://www.openjs.com/scripts/events/keyboard_shortcuts/
* 	shortcut("Ctrl+Shift+X", function() {
*        alert("Hi there!");
* 	});
*/
function shortcut(shortcut,callback,opt) {
	//Provide a set of default options
	var default_options = {
		'type':'keydown',
		'propagate':false,
		'target':document
	}
	if(!opt) opt = default_options;
	else {
		for(var dfo in default_options) {
			if(typeof opt[dfo] == 'undefined') opt[dfo] = default_options[dfo];
		}
	}

	var ele = opt.target
	if(typeof opt.target == 'string') ele = document.getElementById(opt.target);
	var ths = this;

	//The function to be called at keypress
	var func = function(e) {
		e = e || window.event;

		//Find Which key is pressed
		if (e.keyCode) code = e.keyCode;
		else if (e.which) code = e.which;
		var character = String.fromCharCode(code).toLowerCase();

		var keys = shortcut.toLowerCase().split("+");
		//Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked
		var kp = 0;

		//Work around for stupid Shift key bug created by using lowercase - as a result the shift+num combination was broken
		var shift_nums = {
			"`":"~",
			"1":"!",
			"2":"@",
			"3":"#",
			"4":"$",
			"5":"%",
			"6":"^",
			"7":"&",
			"8":"*",
			"9":"(",
			"0":")",
			"-":"_",
			"=":"+",
			";":":",
			"'":"\"",
			",":"<",
			".":">",
			"/":"?",
			"\\":"|"
		}
		//Special Keys - and their codes
		var special_keys = {
			'esc':27,
			'escape':27,
			'tab':9,
			'space':32,
			'return':13,
			'enter':13,
			'backspace':8,

			'scrolllock':145,
			'scroll_lock':145,
			'scroll':145,
			'capslock':20,
			'caps_lock':20,
			'caps':20,
			'numlock':144,
			'num_lock':144,
			'num':144,

			'pause':19,
			'break':19,

			'insert':45,
			'home':36,
			'delete':46,
			'end':35,

			'pageup':33,
			'page_up':33,
			'pu':33,

			'pagedown':34,
			'page_down':34,
			'pd':34,

			'left':37,
			'up':38,
			'right':39,
			'down':40,

			'f1':112,
			'f2':113,
			'f3':114,
			'f4':115,
			'f5':116,
			'f6':117,
			'f7':118,
			'f8':119,
			'f9':120,
			'f10':121,
			'f11':122,
			'f12':123
		}


		for(var i=0; k=keys[i],i<keys.length; i++) {
			//Modifiers
			if(k == 'ctrl' || k == 'control') {
				if(e.ctrlKey) kp++;

			} else if(k ==  'shift') {
				if(e.shiftKey) kp++;

			} else if(k == 'alt') {
					if(e.altKey) kp++;

			} else if(k.length > 1) { //If it is a special key
				if(special_keys[k] == code) kp++;

			} else { //The special keys did not match
				if(character == k) kp++;
				else {
					if(shift_nums[character] && e.shiftKey) { //Stupid Shift key bug created by using lowercase
						character = shift_nums[character];
						if(character == k) kp++;
					}
				}
			}
		}

		if(kp == keys.length) {
			callback(e);

			if(!opt['propagate']) { //Stop the event
				//e.cancelBubble is supported by IE - this will kill the bubbling process.
				e.cancelBubble = true;
				e.returnValue = false;

				//e.stopPropagation works only in Firefox.
				if (e.stopPropagation) {
					e.stopPropagation();
					e.preventDefault();
				}
				return false;
			}
		}
	}

	//Attach the function with the event
	if(ele.addEventListener) ele.addEventListener(opt['type'], func, false);
	else if(ele.attachEvent) ele.attachEvent('on'+opt['type'], func);
	else ele['on'+opt['type']] = func;
}

/**
 * @author Ryan Johnson <ryan@livepipe.net>
 * @copyright 2007 LivePipe LLC
 * @package Control.Modal
 * @license MIT
 * @url http://livepipe.net/projects/control_modal/
 * @version 2.2.1
 * blueend modifications:
 * - Added position: 'top' property
 */
if(typeof(Control) == "undefined")
	Control = {};
Control.Modal = Class.create();
Object.extend(Control.Modal,{
	loaded: false,
	loading: false,
	loadingTimeout: false,
	overlay: false,
	container: false,
	current: false,
	ie: false,
	effects: {
		containerFade: false,
		containerAppear: false,
		overlayFade: false,
		overlayAppear: false
	},
	targetRegexp: /#(.+)$/,
	imgRegexp: /\.(jpe?g|gif|png|tiff?)$/i,
	overlayStyles: {
		position: 'fixed',
		top: 0,
		left: 0,
		width: '100%',
		height: '100%',
		zIndex: 9998
	},
	overlayIEStyles: {
		position: 'absolute',
		top: 0,
		left: 0,
		zIndex: 9998
	},
	disableHoverClose: false,
	load: function(){
		if(!Control.Modal.loaded){
			Control.Modal.loaded = true;
			Control.Modal.ie = !!(window.attachEvent && !window.opera);
			Control.Modal.overlay = $(document.createElement('div'));
			Control.Modal.overlay.id = 'modal_overlay';
			Object.extend(Control.Modal.overlay.style,Control.Modal['overlay' + (Control.Modal.ie ? 'IE' : '') + 'Styles']);
			Control.Modal.overlay.hide();
			Control.Modal.container = $(document.createElement('div'));
			Control.Modal.container.id = 'modal_container';
			Control.Modal.container.hide();
			Control.Modal.loading = $(document.createElement('div'));
			Control.Modal.loading.id = 'modal_loading';
			Control.Modal.loading.hide();
			var body_tag = document.getElementsByTagName('body')[0];
			body_tag.appendChild(Control.Modal.overlay);
			body_tag.appendChild(Control.Modal.container);
			body_tag.appendChild(Control.Modal.loading);
			Control.Modal.container.observe('mouseout',function(event){
				if(!Control.Modal.disableHoverClose && Control.Modal.current && Control.Modal.current.options.hover && !Position.within(Control.Modal.container,Event.pointerX(event),Event.pointerY(event)))
					Control.Modal.close();
			});
		}
	},
	open: function(contents,options){
		options = options || {};
		if(!options.contents)
			options.contents = contents;
		var modal_instance = new Control.Modal(false,options);
		modal_instance.open();
		return modal_instance;
	},
  openAjax: function(url,options){
    options = options || {};
    element = Builder.node('a', {href:url});
    var modal_instance = new Control.Modal(element,options);
    modal_instance.open();
    return modal_instance;
  },
	close: function(force){
		if(typeof(force) != 'boolean')
			force = false;
		if(Control.Modal.current)
			Control.Modal.current.close(force);
	},
	attachEvents: function(){
		Event.observe(window,'load',Control.Modal.load);
		//Event.observe(window,'unload',Event.unloadCache,false);
	},

  position_top: function(){ 					// DW
      	element = this.container;
 	      if(!element._centered){
 	              this.container.setStyle({
 	                      position: 'absolute'
 	              });
 	              this.container._centered = true;
 	      }
 	      dimensions = Control.Modal.container.getDimensions();
 	      Position.prepare();
 	      offset_left = (Position.deltaX + Math.floor((Control.Modal.getWindowWidth() - dimensions.width) / 2));
 	      offset_top = (Position.deltaY + Math.floor((Control.Modal.getWindowHeight() - dimensions.height) / 2));
 	      modal_dimensions = Control.Modal.container.getDimensions();
 	      Control.Modal.container.setStyle({
 	              top: ('25px'),
 	              left: ((modal_dimensions.width <= Control.Modal.getWindowWidth()) ? ((offset_left != null && offset_left > 0) ? offset_left : '0') + 'px' : 0)
 	      });
  },
	center: function(element){
		if(!element._absolutized){
			element.setStyle({
				position: 'absolute'
			});
			element._absolutized = true;
		}
		var dimensions = element.getDimensions();
		//document.viewport.getScrollOffsets();
		Position.prepare();
		var offset_left = (Position.deltaX + Math.floor((Control.Modal.getWindowWidth() - dimensions.width) / 2));
		var offset_top = (Position.deltaY + Math.floor((Control.Modal.getWindowHeight() - dimensions.height) / 2));
		element.setStyle({
			top: ((dimensions.height <= Control.Modal.getDocumentHeight()) ? ((offset_top != null && offset_top > 0) ? offset_top : '0') + 'px' : 0),
			left: ((dimensions.width <= Control.Modal.getDocumentWidth()) ? ((offset_left != null && offset_left > 0) ? offset_left : '0') + 'px' : 0)
		});
	},
	getWindowWidth: function(){
		return (self.innerWidth || document.documentElement.clientWidth || document.body.clientWidth || 0);
	},
	getWindowHeight: function(){
		return (self.innerHeight ||  document.documentElement.clientHeight || document.body.clientHeight || 0);
	},
	getDocumentWidth: function(){
		return Math.min(document.body.scrollWidth,Control.Modal.getWindowWidth());
	},
	getDocumentHeight: function(){
		return Math.max(document.body.scrollHeight,Control.Modal.getWindowHeight());
	},
	onKeyDown: function(event){
		if(event.keyCode == Event.KEY_ESC)
			Control.Modal.close();
	}
});
Object.extend(Control.Modal.prototype,{
	mode: '',
	html: false,
	href: '',
	element: false,
	src: false,
	imageLoaded: false,
	ajaxRequest: false,
	initialize: function(element,options){
		this.element = $(element);
		this.options = {
			beforeOpen: Prototype.emptyFunction,
			afterOpen: Prototype.emptyFunction,
			beforeClose: Prototype.emptyFunction,
			afterClose: Prototype.emptyFunction,
			onSuccess: Prototype.emptyFunction,
			onFailure: Prototype.emptyFunction,
			onException: Prototype.emptyFunction,
			beforeImageLoad: Prototype.emptyFunction,
			afterImageLoad: Prototype.emptyFunction,
			autoOpenIfLinked: true,
			contents: false,
			title: this.element ? (this.element.title?this.element.title:this.element.readAttribute('_title')) : false,
			loading: false, //display loading indicator
			fade: (Prototype.Browser.Gecko),
			fadeDuration: 0.5,
			image: false,
			imageCloseOnClick: true,
			hover: false,
			iframe: false,
			iframeTemplate: new Template('<div class="xf_dialog iframe"><div class="title"><a class="xf_modal_close_btn" href="JavaScript:Control.Modal.close();"><span>[X]</span></a>#{title}</div><div width="#{width}" height="#{height}" class="iframe_outer ajax_loader_large"><iframe src="#{href}" width="100%" height="#{height}" frameborder="0" id="#{id}"></iframe></div></div>'),
			ajaxTemplate: new Template('<div class="xf_dialog ajax"><div class="title"><a class="xf_modal_close_btn" href="JavaScript:Control.Modal.close();"><span>[X]</span></a>#{title}</div><div class="content">#{content}</div></div>'),
			evalScripts: true, //for Ajax, define here instead of in requestOptions
			requestOptions: {}, //for Ajax.Request
			overlayDisplay: true,
			overlayClassName: '',
			overlayCloseOnClick: true,
			containerClassName: '',
      contentClassName: 'content', //DW: Used to set the height/width to the correct div within the template
			opacity: 0.7,
			zIndex: 9998,
			width: null,
			height: null,
			offsetLeft: 0, //for use with 'relative'
			offsetTop: 0, //for use with 'relative'
			position: 'absolute', //'absolute' or 'relative'
			fullScreen: false, //fullscreen switch
			customClass: ''
		};
		Object.extend(this.options,options || {});
		var target_match = false;
		var image_match = false;
		if(this.element){
			target_match = Control.Modal.targetRegexp.exec(this.element.href);
			image_match = Control.Modal.imgRegexp.exec(this.element.href);
		}
		if(this.options.position == 'mouse')
			this.options.hover = true;
		if(this.options.contents){
			this.mode = 'contents';
		}else if(this.options.image || image_match){
			this.mode = 'image';
			this.src = this.element.href;
		}else if(target_match){
			this.mode = 'named';
			var x = $(target_match[1]);
			this.html = x.innerHTML;
			x.remove();
			this.href = target_match[1];
		}else{
			this.mode = (this.options.iframe) ? 'iframe' : 'ajax';
			if (this.element)
        this.href = this.element.href;
		}
		if(this.element){
			if(this.options.hover){
				this.element.observe('mouseover',this.open.bind(this));
				this.element.observe('mouseout',function(event){
					if(!Position.within(Control.Modal.container,Event.pointerX(event),Event.pointerY(event)))
						this.close();
				}.bindAsEventListener(this));
			}else{
				this.element.onclick = function(event){
					this.open();
					Event.stop(event);
					return false;
				}.bindAsEventListener(this);
			}
		}
		var targets = Control.Modal.targetRegexp.exec(window.location);
		this.position = function(event){		
			if(this.options.position == 'absolute'){
				Control.Modal.center(Control.Modal.container);
			}else if(this.options.position == 'top'){
				Control.Modal.position_top(); // DW
			}else{
				var xy = (event ? [Event.pointerX(event),Event.pointerY(event)] : Position.cumulativeOffset(this.element));
				Control.Modal.container.setStyle({
					position: 'absolute',
					top: xy[1] + (typeof(this.options.offsetTop) == 'function' ? this.options.offsetTop() : this.options.offsetTop) + 'px',
					left: xy[0] + (typeof(this.options.offsetLeft) == 'function' ? this.options.offsetLeft() : this.options.offsetLeft) + 'px'
				});
			}
			if(Control.Modal.ie){
				Control.Modal.overlay.setStyle({
					height: Control.Modal.getDocumentHeight() + 'px',
					width: Control.Modal.getDocumentWidth() + 'px'
				});
			}
		}.bind(this);
		
		//add custom class (MG)
		/**/
		if (Control.Modal.container) {	
			if (this.options.customClass.length > 0) {
				Control.Modal.container.addClassName(this.options.customClass);
			} else {
				Control.Modal.container.writeAttribute('class','');
			}
		}
		/**/
		if(this.mode == 'named' && this.options.autoOpenIfLinked && targets && targets[1] && targets[1] == this.href)
			this.open();
	},
	showLoadingIndicator: function(){
		if(this.options.loading){
			Control.Modal.loadingTimeout = window.setTimeout(function(){
				var modal_image = $('modal_image');
				if(modal_image)
					modal_image.hide();
				Control.Modal.loading.style.zIndex = this.options.zIndex + 1;
				//Control.Modal.loading.update('<img id="modal_loading" src="' + this.options.loading + '"/>');
				Control.Modal.loading.show();
				Control.Modal.center(Control.Modal.loading);
			}.bind(this),250);
		}
	},
	hideLoadingIndicator: function(){
		if(this.options.loading){
			if(Control.Modal.loadingTimeout)
				window.clearTimeout(Control.Modal.loadingTimeout);
			var modal_image = $('modal_image');
			if(modal_image)
				modal_image.show();
			Control.Modal.loading.hide();
		}
	},
	showcontent:function(c,t){
		this.update(this.options.ajaxTemplate.evaluate({title: t, content: c}));
		this.mode = 'showcontent';
		this.open();
	},
	openiFrame:function(url,t) {
		this.mode = 'iframe';
		this.href = url;
		this.options.title = t;
		this.open();
	},
	open: function(force){
		if(!force && this.notify('beforeOpen') === false)
			return;
		if(!Control.Modal.loaded)
			Control.Modal.load();
		Control.Modal.close();
		if(!this.options.hover)
			Event.observe($(document.getElementsByTagName('body')[0]),'keydown',Control.Modal.onKeyDown);
		Control.Modal.current = this;
		if(!this.options.hover)
			Control.Modal.overlay.setStyle({
				zIndex: this.options.zIndex,
				opacity: this.options.opacity
			});

		//Fullscreen (MG)
//		if (this.options.fullScreen == true) {
//			dimensions = document.viewport.getDimensions();
			
//			this.options.width = dimensions.width-50;
//			this.options.height = dimensions.height-50;
//		}
		
		Control.Modal.container.setStyle({
			zIndex: this.options.zIndex + 1,
			width: (this.options.width ? (typeof(this.options.width) == 'function' ? this.options.width() : this.options.width) + 'px' : null),
			height: (this.options.height ? (typeof(this.options.height) == 'function' ? this.options.height() : this.options.height) + 'px' : null),
			overflow: 'hidden' /* Otherwise positioning currently messes up*/
		});
		

    //DW: Disabled as it hides all select input fields in non ajax modal dialogs in IE
		if(false && Control.Modal.ie && !this.options.hover){
        $$('select').each(function(select){
            select.style.visibility = 'hidden';
			  });
		}
		Control.Modal.overlay.addClassName(this.options.overlayClassName);
		Control.Modal.container.addClassName(this.options.containerClassName);
		switch(this.mode){
			case 'image':
				this.imageLoaded = false;
				this.notify('beforeImageLoad');
				this.showLoadingIndicator();

				var div = document.createElement('div');
				var img = document.createElement('img');
				var close_a = document.createElement('a');
				close_a.id = 'xf_modal_image_close_btn';
				close_a.innerHTML = '<span>X</span>';
				close_a.href='javascript:void(0);';
				close_a.onclick = Control.Modal.close.bindAsEventListener();
				div.appendChild(close_a);
				div.appendChild(img);
				div.id = 'modal_image_container';
				img.onload = function(img, div){
					this.hideLoadingIndicator();
					this.update([div]);
					if(this.options.imageCloseOnClick)
						$(img).observe('click',Control.Modal.close);
					this.position();
					this.notify('afterImageLoad');
					img.onload = null;
				}.bind(this,img, div);
				img.src = this.src;
				img.id = 'modal_image';
				break;
			case 'ajax':
				this.notify('beforeLoad');
				var options = {
					method: 'get',
					onSuccess: function(request,json){
						this.hideLoadingIndicator();
						//Modification SP
						//this.update(request.responseText);
						var title = (json != undefined) ? json.title : this.options.title;
            if (!title) title = '&nbsp;';
						this.update(this.options.ajaxTemplate.evaluate({title: title, content: request.responseText}));
						this.notify('onSuccess',request);
						this.ajaxRequest = false;
					}.bind(this),
					onFailure: function(){
						this.notify('onFailure');
					}.bind(this),
					onException: function(){
						this.notify('onException');
					}.bind(this)
				};
				Object.extend(options,this.options.requestOptions);
				this.showLoadingIndicator();
				this.ajaxRequest = new Ajax.Request(this.href,options);
				break;
			case 'iframe':
				this.update(this.options.iframeTemplate.evaluate({href: (this.href.indexOf('?')) ? this.href+'&a_iframe=1' : this.href+'?a_iframe=1', id: 'modal_iframe', title: this.options.title, width: this.options.width, height: this.options.height}));
				break;
			case 'contents':
				this.update((typeof(this.options.contents) == 'function' ? this.options.contents() : this.options.contents));
				break;
			case 'named':
				this.update(this.html);
				break;
		}


		if(!this.options.hover){
			if(this.options.overlayCloseOnClick && this.options.overlayDisplay)
				Control.Modal.overlay.observe('click',Control.Modal.close);
			if(this.options.overlayDisplay){
				if(this.options.fade){
					if(Control.Modal.effects.overlayFade)
						Control.Modal.effects.overlayFade.cancel();
					Control.Modal.effects.overlayAppear = new Effect.Appear(Control.Modal.overlay,{
						queue: {
							position: 'front',
							scope: 'Control.Modal'
						},
						to: this.options.opacity,
						duration: this.options.fadeDuration / 2
					});
				}else
					Control.Modal.overlay.show();
			}
		}
    $$('body').first().addClassName('modalIsVisible'); /* Used to hide Java Applets via CSS */
		if(this.options.position == 'mouse'){
			this.mouseHoverListener = this.position.bindAsEventListener(this);
			this.element.observe('mousemove',this.mouseHoverListener);
		}
		this.notify('afterOpen');
	},
	update: function(html){
		if(typeof(html) == 'string')
			Control.Modal.container.update(html);
		else{
			Control.Modal.container.update('');
			(html.each) ? html.each(function(node){
				Control.Modal.container.appendChild(node);
			}) : Control.Modal.container.appendChild(html);
		}

		if(true && this.options.fade){
			(

			function(){
				with (Control.Modal.container)
				{
				  this.position();
					setStyle({'visibility':'hidden'});
					show();
					this.update_size();
					hide();
					setStyle({'visibility':'visible'});
				}
        if(Control.Modal.effects.containerFade)
					Control.Modal.effects.containerFade.cancel();
				Control.Modal.effects.containerAppear = new Effect.Appear(Control.Modal.container,{
					to: 1,
					duration: this.options.fadeDuration / 2
				});
			}).bind(this).defer();
		}
		else
		{
			(function(){
				Control.Modal.container.show();
        this.update_size();
			}).bind(this).defer();
		}
		this.position();
			
		Event.observe(window,'resize',this.position,false);
		Event.observe(Control.Modal.container,'click',this.update_height,false);
		Event.observe(Control.Modal.container,'mouseover',this.update_height,false);
		//Event.observe(window,'scroll',this.position,false);
	},
	update_height: function(){
    //Resize Height SP
    if (Control.Modal.current.options){
      if(!Control.Modal.current.options.fullScreen){

        var b = Control.Modal.container.down('.xf_dialog>div.buttons');  
        var c = Control.Modal.container.down('.xf_dialog>div.content');
        if (b) {c = b;} 
        if (c){
          /* [DW 29.7.2011: Support shrinking e.g. with tabbed content] */
          var newHeight = c.offsetTop + c.getHeight()+parseInt(c.getStyle('margin-bottom'));
        } else {
          var newHeight = Control.Modal.container.scrollHeight;
        }

			  Control.Modal.container.setStyle({
				  height: (newHeight + 0) + 'px' //2 
			  });
       //console.log(Control.Modal.container.scrollHeight);
		  }
    }
		//this.position();
	},
	update_size: function(){
		
		if (this.options.fullScreen == true) {
			
			//added iframe + fullscreen workaround, but fullScreen will still not work with iframe=true [MG 20.01.11]
			var c;
			if (this.options.iframe == true) {
				c = Control.Modal.container.down('iframe.modal_iframe'); 
			} else {
				//does not exist if iframe=true
			  c = Control.Modal.container.down('div.content'); 
		  }
			var d = c.positionedOffset(), vp = document.viewport.getDimensions();
			var w = vp.width - 50 ,h=vp.height -50;//Max width and height with 50px space
			
			var h1 = c.getHeight();//Incl. Padding Top+Bottom
			c.setStyle({paddingTop:0});
			var h2 = c.getHeight();//Incl. Padding Bottom
			c.setStyle({paddingBottom:0});
			var h3 = c.getHeight();//Incl. no padding
			
			var margin_bottom = (Control.Modal.container.getHeight() - c.getHeight() - d.top);

			c.setStyle({
				height: (h-(h1-h3)-d.top-margin_bottom)+'px',
				paddingTop: (h1-h2) + 'px',
				paddingBottom: (h2-h3) + 'px'
			});
			
			Control.Modal.container.setStyle({
				width: (w) + 'px',  //10
				height: (h) + 'px' //2
			});			

		}
		else
		{    
			//Resize Again SP
			Control.Modal.container.setStyle({
				width: (Control.Modal.container.scrollWidth + 0) + 'px',  //10
				height: (Control.Modal.container.scrollHeight + 0) + 'px' //2
			});
		}
		
		this.position();
    this.update_height();
	},
	close: function(force){
		if(!force && this.notify('beforeClose') === false)
			return;
		if(this.ajaxRequest)
			this.ajaxRequest.transport.abort();
		this.hideLoadingIndicator();
		if(this.mode == 'image'){
			var modal_image = $('modal_image');
			if(this.options.imageCloseOnClick && modal_image)
				modal_image.stopObserving('click',Control.Modal.close);
		}
		if(Control.Modal.ie && !this.options.hover){
			$A(document.getElementsByTagName('select')).each(function(select){
				select.style.visibility = 'visible';
			});
		}
		if(!this.options.hover)
			Event.stopObserving(window,'keyup',Control.Modal.onKeyDown);
		Control.Modal.current = false;
		Event.stopObserving(window,'resize',this.position,false);
		Event.stopObserving(window,'scroll',this.position,false);
		if(!this.options.hover){
			if(this.options.overlayCloseOnClick && this.options.overlayDisplay)
				Control.Modal.overlay.stopObserving('click',Control.Modal.close);
			if(this.options.overlayDisplay){
				if(this.options.fade){
					if(Control.Modal.effects.overlayAppear)
						Control.Modal.effects.overlayAppear.cancel();
					Control.Modal.effects.overlayFade = new Effect.Fade(Control.Modal.overlay,{
						from: this.options.opacity,
						to: 0,
						duration: this.options.fadeDuration / 2
					});
				}else
					Control.Modal.overlay.hide();
			}
		}
		if(this.options.fade){
			if(Control.Modal.effects.containerAppear)
				Control.Modal.effects.containerAppear.cancel();
			Control.Modal.effects.containerFade = new Effect.Fade(Control.Modal.container,{
				from: 1,
				to: 0,
				duration: this.options.fadeDuration / 2,
				afterFinish: function(){
					Control.Modal.container.update('');
					this.resetClassNameAndStyles();
          $$('body').first().removeClassName('modalIsVisible'); /* Used to hide Java Applets via CSS */
				}.bind(this)
			});
		}else{
			Control.Modal.container.hide();
			Control.Modal.container.update('');
			this.resetClassNameAndStyles();
      $$('body').first().removeClassName('modalIsVisible'); /* Used to hide Java Applets via CSS */
		}
		if(this.options.position == 'mouse')
			this.element.stopObserving('mousemove',this.mouseHoverListener);
      

      
		this.notify('afterClose');
	},
	resetClassNameAndStyles: function(){
		Control.Modal.overlay.removeClassName(this.options.overlayClassName);
		Control.Modal.container.removeClassName(this.options.containerClassName);
		Control.Modal.container.setStyle({
			height: null,
			width: null,
			top: null,
			left: null
		});
	},
	notify: function(event_name){
		try{
			if(this.options[event_name])
				return [this.options[event_name].apply(this.options[event_name],$A(arguments).slice(1))];
		}catch(e){
			if(e != $break)
				throw e;
			else
				return false;
		}
	}
});

//if(typeof(Object.Event) != 'undefined')
//	Object.Event.extend(Control.Modal);
Control.Modal.attachEvents();


/**
* Prototype based beTooltip
* http://blog.innerewut.de/files/tooltip/tooltip-v0.2.js
* DW: Added support for tooltip caption
*/
var Tooltip = Class.create();
Tooltip.prototype = {
  initialize: function(element, tool_tip, tool_caption, delay) {  //DW: Modified
    var options = Object.extend({
      default_css: "tooltip",
      margin: "0px",
      padding: "5px",
      backgroundColor: false,
      min_distance_x: 5,
      min_distance_y: 5,
      delta_x: 5,
      delta_y: 5,
      zindex: 1000
    }, arguments[2] || {});

    this.options = options;
    this.element = $(element);
    if (this.element){

	    this.tool_tip = document.createElement("div");
      Element.extend(this.tool_tip);
      document.body.appendChild(this.tool_tip);
	    this.tool_tip.addClassName("tooltip");

	    // DW: Handle Caption
	    if (tool_caption)
	    {
	      tool_tip_caption = document.createElement("div");
	      Element.extend(tool_tip_caption);
        this.tool_tip.appendChild(tool_tip_caption);
	      tool_tip_caption.addClassName("caption");
	      tool_tip_caption.appendChild(document.createTextNode(tool_caption));
	    }

	    tool_tip_content = document.createElement("span");
	    Element.extend(tool_tip_content);
      tool_tip_content.innerHTML = tool_tip;
	    this.tool_tip.appendChild(tool_tip_content);

	    // hide the tool-tip by default
	    this.tool_tip.hide();
	    this.delay = delay;
	    if (false && !Prototype.Browser.IE && delay>0)
	      this.eventMouseOver = this.showTooltipDelayed.bindAsEventListener(this);
	    else
	      this.eventMouseOver = this.showTooltip.bindAsEventListener(this);

	    this.eventMouseOut   = this.hideTooltip.bindAsEventListener(this);
	    this.eventMouseMove  = this.moveTooltip.bindAsEventListener(this);
	    this.registerEvents();
		}
  },

  destroy: function() {
    Event.stopObserving(this.element, "mouseover", this.eventMouseOver);
    Event.stopObserving(this.element, "mouseout", this.eventMouseOut);
    Event.stopObserving(this.element, "mousemove", this.eventMouseMove);
  },

  registerEvents: function() {
    Event.observe(this.element, "mouseover", this.eventMouseOver);
    Event.observe(this.element, "mouseout", this.eventMouseOut);
    Event.observe(this.element, "mousemove", this.eventMouseMove);
  },

  moveTooltip: function(event){
    Event.stop(event);
    // get Mouse position
    var mouse_x = Event.pointerX(event);
    var mouse_y = Event.pointerY(event);

    // decide if wee need to switch sides for the tooltip
    var dimensions = Element.getDimensions( this.tool_tip );
    var element_width = dimensions.width;
    var element_height = dimensions.height;

    if ( (element_width + mouse_x) >= ( this.getWindowWidth() - this.options.min_distance_x) ){ // too big for X
      mouse_x = mouse_x - element_width;
      // apply min_distance to make sure that the mouse is not on the tool-tip
      mouse_x = mouse_x - this.options.min_distance_x;
    } else {
      mouse_x = mouse_x + this.options.min_distance_x;
    }

    if ( (element_height + mouse_y) >= ( this.getWindowHeight() - this.options.min_distance_y) ){ // too big for Y
      mouse_y = mouse_y - element_height;
      // apply min_distance to make sure that the mouse is not on the tool-tip
      mouse_y = mouse_y - this.options.min_distance_y;
    } else {
      mouse_y = mouse_y + this.options.min_distance_y;
    }

    // now set the right styles
    this.setStyles(mouse_x, mouse_y);
  },

  showTooltip: function(event) {
    window.clearTimeout(this.delay_timer);
    Event.stop(event);
    this.moveTooltip(event);
    new Element.show(this.tool_tip);
  },

  showTooltipDelayed: function(event) {
    this.delay_timer = window.setTimeout(function(event){this.showTooltip(event)}.bind(this),this.delay);
  },

  setStyles: function(x, y){
    // set the right styles to position the tool tip
    Element.setStyle(this.tool_tip, { position:'absolute',
                       top:y + this.options.delta_y + "px",
                       left:x + this.options.delta_x + "px",
                      zindex:this.options.zindex
                     });

    // apply default theme if wanted
    if (this.options.default_css){
        Element.setStyle(this.tool_tip, { margin:this.options.margin,
                                           padding:this.options.padding,
                                          backgroundColor:this.options.backgroundColor,
                                          zindex:this.options.zindex
                         });
    }
  },

  hideTooltip: function(event){
    window.clearTimeout(this.delay_timer);
    new Element.hide(this.tool_tip);
  },

  getWindowHeight: function(){
    var innerHeight;
    if (navigator.appVersion.indexOf('MSIE')>0) {
      innerHeight = document.body.clientHeight;
    } else {
      innerHeight = window.innerHeight;
    }
    return innerHeight;
  },

  getWindowWidth: function(){
    var innerWidth;
    if (navigator.appVersion.indexOf('MSIE')>0) {
      innerWidth = document.body.clientWidth;
    } else {
      innerWidth = window.innerWidth;
    }
    return innerWidth;
  }

}


// parseUri 1.2.2
// (c) Steven Levithan <stevenlevithan.com>
// MIT License

function parseUri (str) {
	var	o   = parseUri.options,
		m   = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
		uri = {},
		i   = 14;

	while (i--) uri[o.key[i]] = m[i] || "";

	uri[o.q.name] = {};
	uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
		if ($1) uri[o.q.name][$1] = $2;
	});

	return uri;
};

parseUri.options = {
	strictMode: false,
	key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
	q:   {
		name:   "queryKey",
		parser: /(?:^|&)([^&=]*)=?([^&]*)/g
	},
	parser: {
		strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
		loose:  /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
	}
};


/**
 * @description		prototype.js based context menu
 * @author				Juriy Zaytsev; kangax [at] gmail [dot] com; http://thinkweb2.com/projects/prototype
 * @version				0.6
 * @date					10/29/07
 * @requires			prototype.js 1.6.0_rc1
*/

if (Object.isUndefined(Proto)) { var Proto = { } }

Proto.Menu = Class.create({
	initialize: function() {
		var e = Prototype.emptyFunction;
		this.ie = Prototype.Browser.IE;
		this.options = Object.extend({
			selector: '.contextmenu',
			className: 'xf_menu desktop',
			pageOffset: 25,
			fade: false,
			zIndex: 100,
			beforeShow: e,
			beforeHide: e,
			beforeSelect: e,
			position: 'mouse',
			delayedhide: false
		}, arguments[0] || { });

		this.shim = new Element('iframe', {
			style: 'position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);display:none',
			src: 'javascript:false;',
			frameborder: 0
		});

		this.options.fade = this.options.fade && !Object.isUndefined(Effect);
		this.container = new Element('div', {style: 'display:none'});
		this.container.addClassName(this.options.className);
		var list = new Element('ul');
		this.options.menuItems.each(function(item) {
			list.insert(
				new Element('li', {className: item.separator ? 'separator' : ''}).insert(
					item.content
					   ? item.content
					   :
							item.separator
								? new Element('span')
								: Object.extend(new Element('a', {
									href: '#',
									title: item.name,
									className: (item.className || '') + (item.disabled ? ' disabled' : ' enabled')
								}), { _callback: item.callback })
								.observe('click', this.onClick.bind(this))
								.observe('contextmenu', Event.stop)
								.update(item.name)
				)
			)
		}.bind(this));
		$(document.body).insert(this.container.insert(list).observe('contextmenu', Event.stop));
		if (this.ie) { $(document.body).insert(this.shim) }

		document.observe('click', function(e) {
			if (this.container.visible() && !Event.isRightClick(e)) {
				this.options.beforeHide();
				if (this.ie) this.shim.hide();
				this.container.hide();
			}
		}.bind(this));

		$$(this.options.selector).invoke('observe', Prototype.Browser.Opera ? 'click' : 'contextmenu', function(e){
			if (Prototype.Browser.Opera && !e.ctrlKey) {
				return;
			}
			this.show(e);
		}.bind(this));
	},
	delayedhide: function(e,delay){
		delay = (typeof delay == 'undefined')?300:delay;
		if (this.container.visible() && !Event.isRightClick(e)) {
			if(this.hide_timer){
				window.clearTimeout(this.hide_timer);
			};
			this.hide_timer = window.setTimeout(function(){
					this._hide();
					this.hide_timer = false;
				}.bind(this),delay);
			this.container.onmouseover = function(){
				window.clearTimeout(this.hide_timer);
			}.bind(this);
		};
	},
	hide: function(e){
		if (this.container.visible() && !Event.isRightClick(e)) {
			this._hide();
		}
	},
	_hide: function(){
		this.options.beforeHide();
		if (this.ie) this.shim.hide();
		this.container.hide();
	},
	show: function(e) {
		Event.stop(e);

		// Close all existing popups
		if (document.createEvent)
		{
	    var clickevent=document.createEvent("MouseEvents");
			clickevent.initEvent("click", true, true);
			document.dispatchEvent(clickevent);
		}
		//Element.extend(e);
		//alert($(e).inspect());
		//e.stop();
		this.options.beforeShow();
		var x = (this.options.position=='element') ? Event.element(e).cumulativeOffset()[0] : Event.pointer(e).x,
			y = (this.options.position=='element') ? Event.element(e).cumulativeOffset()[1] + Event.element(e).getHeight() : Event.pointer(e).y,
			vpDim = document.viewport.getDimensions(),
			vpOff = document.viewport.getScrollOffsets(),
			elDim = this.container.getDimensions(),
			elOff = {
				left: ((x + elDim.width + this.options.pageOffset) > vpDim.width
					? (vpDim.width - elDim.width - this.options.pageOffset) : x) + 'px',
				top: ((y - vpOff.top + elDim.height) > vpDim.height && (y - vpOff.top) > elDim.height
					? (y - elDim.height) : y) + 'px'
			};
		this.container.setStyle(elOff).setStyle({zIndex: this.options.zIndex});
		if (this.ie) {
			this.shim.setStyle(Object.extend(Object.extend(elDim, elOff), {zIndex: this.options.zIndex - 1})).show();
		}
		this.options.fade ? Effect.Appear(this.container, {duration: 0.25}) : this.container.show();
		this.event = e;
		if (this.options.delayedhide){
			if(this.options.position=='element'){
				Event.element(e).onmouseout = function(e){this.delayedhide(e,1000);}.bindAsEventListener(this);
			}else{
				this.delayedhide(e,1000);
			}
			this.container.onmouseout = function(e){
	    																			this.delayedhide(e);
	    																		}.bindAsEventListener(this);
		}
	},
	onClick: function(e) {
		Event.stop(e);
		if (e.target._callback && !e.target.hasClassName('disabled')) {
			this.options.beforeSelect();
			if (this.ie) this.shim.hide();
			this.container.hide();
			e.target._callback(this.event);
		}
	}
})



String.prototype.pad = function(l, s, t){ //v1.0
    return s || (s = " "), (l -= this.length) > 0 ? (s = new Array(Math.ceil(l / s.length)
        + 1).join(s)).substr(0, t = !t ? l : t == 1 ? 0 : Math.ceil(l / 2))
        + this + s.substr(0, l - t) : this;
};

var colorPicker = Class.create();
colorPicker.prototype = {
	initialize: function(el){
		this.el = $(el);
		var currentBG = this.splitColors(($F(this.el).match(/\d/)) ? $F(this.el) : Element.getStyle(this.el,'background-color'));
		try
		{
      this.el.style.backgroundColor = this.joinColors(currentBG[0],currentBG[1],currentBG[2]);
      var color_brightness = ((currentBG[0] * 299) + (currentBG[1] * 587) + (currentBG[2] * 114))/1000;
      var text_color = (color_brightness > 130) ? "#000" : "#FFF";
      this.el.style.color=text_color;
    }
		catch(e)
		{
		}
		this.customPalette = [];
		this.generatePalette();
		this.el.onfocus = this.displayPalette.bindAsEventListener(this);
		this.el.onclick = this.displayPalette.bindAsEventListener(this);
    this.el.onblur = this.hidePalette.bindAsEventListener(this);
		this.el.onchange = this.updateInput.bindAsEventListener(this);
	},
	displayPalette: function(evt)
	{
		if (Prototype.Browser.IE) this.el.absolutize();/* better for IE */
    this.el.previousSibling.style.left = (this.el.offsetLeft+this.el.offsetWidth+2) + 'px';
		this.el.previousSibling.style.top = this.el.offsetTop + 'px';
		new Effect.Appear(this.el.previousSibling,{duration:0.2});
	},
	hidePalette: function(evt)
	{
		//alert('hide palette');
		new Effect.Fade(this.el.previousSibling,{duration:0.2});
	},
	generatePalette: function()
	{
		var steps = 6;
		var step_size = Math.ceil(255/(steps-1));
		var pc = document.createElement('div');
		pc.className = 'CP_palette';
		pc.style.display = 'none';
		pc.style.left = (this.el.offsetLeft+this.el.offsetWidth+2) + 'px';
		pc.style.top = this.el.offsetTop + 'px';

		var p = document.createElement('div');
		p.className = 'title';
		p.innerHTML = '◄ Color Picker';
		pc.appendChild(p);

		var p = document.createElement('div');
		p.className='standard';
		for(i=0;i<9;i++)
		{
			var cp = document.createElement('a');
			inc = (i * 34)>255 ? 255 : (i * 34);
			cp.style.backgroundColor = this.joinColors(inc,inc,inc);
			cp.onclick = this.assignColor.bindAsEventListener(this);
			p.appendChild(cp);
		}
		pc.appendChild(p);

		var c = ['0','0','0'];
		for(r=0;r<steps;r++)
		{
			var p = document.createElement('div');

			c[0] = r*step_size;
			for(g=0;g<steps;g++)
			{
				c[2] = g*step_size;
				for(b=0;b<steps;b++)
				{
					c[1] = b*step_size;

					c[0] = (c[0]>255) ? 255 : c[0];
					c[1] = (c[1]>255) ? 255 : c[1];
					c[2] = (c[2]>255) ? 255 : c[2];
					var cp = document.createElement('a');
					cp.style.backgroundColor = this.joinColors(c[0],c[1],c[2]);
					cp.onclick = this.assignColor.bindAsEventListener(this);
					if (clear_left)
					 cp.style.clear = 'left';

					cp.title = this.joinColors(c[0],c[1],c[2]);
					p.appendChild(cp);
					var clear_left = false;
				}
				clear_left = true;
			}
			pc.appendChild(p);
		}

		var p = document.createElement('div');
		p.className='custom';
		this.customPalette.each(function(color,ind)
			{
				var cp = document.createElement('a');
				cp.style.backgroundColor = color;
				cp.onclick = this.assignColor.bindAsEventListener(this);
				p.appendChild(cp);
			}.bind(this));
		pc.appendChild(p);

		this.el.parentNode.insertBefore(pc,this.el);
	},
  updateInput:function(){
    var currentBG = this.splitColors(this.el.value);
    try
    {
      this.el.style.backgroundColor = this.joinColors(currentBG[0],currentBG[1],currentBG[2]);
      var color_brightness = ((currentBG[0] * 299) + (currentBG[1] * 587) + (currentBG[2] * 114))/1000;
      var text_color = (color_brightness > 130) ? "#000" : "#FFF";
      this.el.style.color=text_color;
    }catch(e){}
  },
	assignColor:function(evt)
	{
		var color = Event.element(evt).style.backgroundColor;
		var c = this.splitColors(color);
		color = this.joinColors(c[0],c[1],c[2]);
    var color_brightness = ((c[0] * 299) + (c[1] * 587) + (c[2] * 114))/1000;
    var text_color = (color_brightness > 130) ? "#000" : "#FFF";
		this.el.value = color;
		this.el.style.backgroundColor = color;
    this.el.style.color=text_color;
		this.hidePalette();
	},
	splitColors:function(mixed){
		if(mixed.match(/rgb/))
		{
			mixed_array = mixed.replace(/\)|rgb\(/g,'').split(',');
		}
		else
		{
			if(mixed.match(/#/))
				mixed = mixed.replace(/#/,'');
			mixed_array = [];
			mixed_array.push(this.h2d(mixed.slice(0,2)));
			mixed_array.push(this.h2d(mixed.slice(2,4)));
			mixed_array.push(this.h2d(mixed.slice(4,6)));
		}

		return mixed_array;
	},
	joinColors:function(r,g,b){
			return '#' + this.d2h(r).pad(2,'0',0) + this.d2h(g).pad(2,'0',0) + this.d2h(b).pad(2,'0',0);
	},
	d2h:function(d)
	{
		if (isNaN(d))
			d = parseInt(d);
		d=Number(d);
		return d.toString(16);
	},
	h2d:function(h)
	{
		return parseInt(h,16);
	}
}

/* -----------------------------------*/
/* --->>> onDOMReady Extension http://snipplr.com/view/2337/ondomready/ <<<----*/
/* -----------------------------------*/


Object.extend(Event, {
  _domReady : function() {
    if (arguments.callee.done) return;
    arguments.callee.done = true;

    if (this._timer)  clearInterval(this._timer);

    this._readyCallbacks.each(function(f){ if (typeof f == 'function') f(); });
    this._readyCallbacks = 'done';
},
  onDOMReady : function(f) {
    if (Event._readyCallbacks == 'done' &&  typeof f == 'function'){
    	f();
    	return;
		}

    if (!this._readyCallbacks) {
      var domReady = this._domReady.bind(this);

      if (document.addEventListener)
        document.addEventListener("DOMContentLoaded", domReady, false);

        /*@cc_on @*/
        /*@if (@_win32)
        		var dummy = location.protocol == "https:" ?  "https://javascript:void(0)" : "javascript:void(0)";
            document.write("<script id=__ie_onload defer src='" + dummy + "'><\/script>");
            document.getElementById("__ie_onload").onreadystatechange = function() {
                if (this.readyState == "complete") domReady();
            };
        /*@end @*/

        if (/WebKit/i.test(navigator.userAgent)) {
          this._timer = setInterval(function() {
            if (/loaded|complete/.test(document.readyState)) domReady();
          }, 10);
        }

        Event.observe(window, 'load', domReady);
        Event._readyCallbacks =  [];
    }
    Event._readyCallbacks.push(f);
  }
});
Event.onDOMReady(function(){
	XF_JS.windowActive = new XF_JS.windowActive();
}); // Call DomReady at least once


/* simple popup */

function popup(obj,w,h,t,l,name) {
  var url = (obj.getAttribute) ? obj.getAttribute('href') : obj.href;
  if (!url) return true;
  w = (w) ? w += 20 : 150;  // 150px*150px is the default size
  h = (h) ? h += 25 : 150;
  t = (t) ? t : 100;  // top 100px as default
  l = (l) ? l : 100;  // left 100px as default
  var args = 'width='+w+',height='+h+',resizable,scrollbars,top='+t+',left='+l+'';
  pop = window.open(url,name,args);
  pop.focus();
  return (pop) ? false : true;
}


/* PORTAL CODE */

var portlet = Class.create();
portlet.prototype = {
	initialize:function(portlet_id,portlet_url){
		this.portlet_id = portlet_id;
		this.portlet_url = portlet_url;
	},
	updateContent:function(){
		this.content.ajaxUpdate(this.portlet_url);
	}
};

var portalLayout = Class.create();
portalLayout.prototype = {
	initialize:function(layoutPanes){
		this.layoutPanes = layoutPanes;
		this.options = Object.extend(
			{
				startPane: layoutPanes[0],
				update_url: window.location,
				portlet_load_url: window.location,
				portletTemplate: new Template('<h3 class="handle">#{title}</h3><div class="content"><div class="ajax_loader_small_left" style="padding-left: 25px;">Loading...</div></div>')
			}
			, arguments[1] || {});
		this.counters = [];
		layoutPanes.each(function(el){this.createSortable(el)}.bind(this));
	},
	addPortlet:function(pid,ptitle,left,el){
		if (left && this.counters[pid] == undefined){
			this.counters[pid] = left-1;
		}else if (left){
			this.counters[pid] = this.counters[pid]-1;
		}
		var portlet = document.createElement('div');
		Element.extend(portlet);
		portlet.className = 'portlet block-sortable';
		portlet.update(this.options.portletTemplate.evaluate({title: ptitle}));
		this.options.startPane.down('div').insert({after: portlet});
		portlet.ajaxReplace(this.options.portlet_load_url,
				{
					postBody: '&portlet_id='+pid,
					onComplete: function(){
							this.createSortable(this.options.startPane);
						}.bind(this)
				});
		if (this.counters[pid] < 1){
			new Effect.Fade($(el).up('.portlet_info'),{duration:0.4});
			new Effect.Appear($('portal_refresh'));
		}
	},
	removePortlet:function(pid,dupe,el){
		if (this.counters[pid]){
			this.counters[pid]++;
		}
		new Ajax.Request(this.options.update_url,
			{
				parameters: { action: 'removePortlet', portlet_id: pid, dupe_id: dupe }
			});
		if ($(el)){
			new Effect.Fade($(el),{duration:0.3});
			new Effect.Appear($('portal_refresh'));
		}
	},
	createSortable:function(sortable){
		var containment = this.layoutPanes;
		Sortable.create(sortable, {
			containment: containment,
			constraint: false,
			tag: 'div',
			only: 'block-sortable',
			dropOnEmpty: true,
			handle: 'handle',
			hoverclass: 'block-hover',
			scroll: window,
			onUpdate:function(el){
				this.updateOrder(el);
				}.bind(this)
		})
	},
	updateOrder:function(el){
		this.saveSettings([el]);
	},
	saveSettings:function(panes){
		var postParams = [];
		panes.each(function(pane){
			postParams.push(Sortable.serialize(pane,{tag: 'div', name: pane.id}));
		});
		new Ajax.Request(this.options.update_url,{parameters: postParams.join('&'),onSuccess:function(r){this.log(r.responseText)}.bind(this)});
	},
	toggleLib:function(){
		//Element.toggle('portal-lib');
    $$('span.portal_layout').invoke('toggle');
		$$('#portal div.portal-column').invoke('toggleClassName','add-portlets');
	},
	clearPane:function(pane){
		var paneto = Number(pane) - 1;
		this.layoutPanes[pane].select('.portlet').each(function(el){
			this.layoutPanes[paneto].insert(el);
		}.bind(this));
		this.saveSettings([this.layoutPanes[pane], this.layoutPanes[paneto]]);
	}
}

/**
* JS Cookie
*/

/**
 * Javascript code to store data as JSON strings in cookies.
 * It uses prototype.js 1.5.1 (http://www.prototypejs.org)
 *
 * Author : Lalit Patel
 * Website: http://www.lalit.org/lab/jsoncookies
 * License: Creative Commons Attribution-ShareAlike 2.5
 *          http://creativecommons.org/licenses/by-sa/2.5/
 * Version: 0.4
 * Updated: Aug 11, 2007 10:09am
 *
 * Chnage Log:
 *   v 0.4
 *   -  Removed a extra comma in options (was breaking in IE and Opera). (Thanks Jason)
 *   -  Removed the parameter name from the initialize function
 *   -  Changed the way expires date was being calculated. (Thanks David)
 *   v 0.3
 *   -  Removed dependancy on json.js (http://www.json.org/json.js)
 *   -  empty() function only deletes the cookies set by CookieJar
 */

var CookieJar = Class.create();
CookieJar.prototype = {
	/**
	 * Append before all cookie names to differntiate them.
	 */
	appendString: "_XF_",

	/**
	 * Initializes the cookie jar with the options.
	 */
	initialize: function(options) {
		this.options = {
			expires: 3600,		// seconds (1 hr)
			path: '',			// cookie path
			domain: '',			// cookie domain
			secure: ''			// secure ?
		};
		Object.extend(this.options, options || {});


		if (this.options.expires != '') {
			var date = new Date();
			date = new Date(date.getTime() + (this.options.expires * 1000));
			this.options.expires = '; expires=' + date.toGMTString();
		}
		if (this.options.path != '') {
			this.options.path = '; path=' + escape(this.options.path);
		}
		if (this.options.domain != '') {
			this.options.domain = '; domain=' + escape(this.options.domain);
		}
		if (this.options.secure == 'secure') {
			this.options.secure = '; secure';
		} else {
			this.options.secure = '';
		}
	},

	/**
	 * Adds a name values pair.
	 */
	put: function(name, value) {
		name = this.appendString + name;
		cookie = this.options;
		var type = typeof value;
		switch(type) {
		  case 'undefined':
		  case 'function' :
		  case 'unknown'  : return false;
		  case 'boolean'  :
		  case 'string'   :
		  case 'number'   : value = String(value.toString());
		}
		var cookie_str = name + "=" + escape(Object.toJSON(value));
		try {
			document.cookie = cookie_str + cookie.expires + cookie.path + cookie.domain + cookie.secure;
		} catch (e) {
			return false;
		}
		return true;
	},

	/**
	 * Removes a particular cookie (name value pair) form the Cookie Jar.
	 */
	remove: function(name) {
		name = this.appendString + name;
		cookie = this.options;
		try {
			var date = new Date();
			date.setTime(date.getTime() - (3600 * 1000));
			var expires = '; expires=' + date.toGMTString();
			document.cookie = name + "=" + expires + cookie.path + cookie.domain + cookie.secure;
		} catch (e) {
			return false;
		}
		return true;
	},

	/**
	 * Return a particular cookie by name;
	 */
	get: function(name) {
		name = this.appendString + name;
		var cookies = document.cookie.match(name + '=(.*?)(;|$)');
		if (cookies) {
			return (unescape(cookies[1])).evalJSON();
		} else {
			return null;
		}
	},

	/**
	 * Empties the Cookie Jar. Deletes all the cookies.
	 */
	empty: function() {
		keys = this.getKeys();
		size = keys.size();
		for(i=0; i<size; i++) {
			this.remove(keys[i]);
		}
	},

	/**
	 * Returns all cookies as a single object
	 */
	getPack: function() {
		pack = {};
		keys = this.getKeys();

		size = keys.size();
		for(i=0; i<size; i++) {
			pack[keys[i]] = this.get(keys[i]);
		}
		return pack;
	},

	/**
	 * Returns all keys.
	 */
	getKeys: function() {
		keys = $A();
		keyRe= /[^=; ]+(?=\=)/g;
		str  = document.cookie;
		CJRe = new RegExp("^" + this.appendString);
		while((match = keyRe.exec(str)) != undefined) {
			if (CJRe.test(match[0].strip())) {
				keys.push(match[0].strip().gsub("^" + this.appendString,""));
			}
		}
		return keys;
	}
};

XF_JS.Form.lockForm = Class.create();
XF_JS.Form.lockForm.prototype = {
	messages: {
    lose_message: 'You will lose all unsaved changes!'
  },
  initialize:function(formEl){
		this.form = $(formEl);
		window.onbeforeunload = function(){
      if (this.hasUnsavedChanges()){
				return XF_JS.Form.lockForm.prototype.messages.lose_message;
			}
		}.bindAsEventListener(this);

//		this.form.select('input[type=submit]').each(function(el){
//			el.onclick = function(){this.setSaveStatus(true);}.bindAsEventListener(this);
//		}.bind(this));
		Event.observe(this.form,'submit',function(){
			this.setSaveStatus(true);
    }.bindAsEventListener(this));

		new Form.Observer(this.form, 0.9, function(){this.setSaveStatus(false)}.bind(this));
		this.form_saved = true;
  },
  setSaveStatus:function(state){
   	this.form_saved = state;
	},
	hasUnsavedChanges:function(){
		return (!this.form_saved);
	}
};

XF_JS.userLink = {
	templates: [],
	userlinks: [],
	show:function(el, user_id, name, email, extra_url){
		this.hide();
		this.firstTime = true;
		if (!this.observer){
	    this.observer = document.observe('click', function(e) {
				if (!Event.isRightClick(e) && !this.firstTime) {
					this.hide();
				}
				this.firstTime = false;
			}.bind(this));
		}
		var pos = $(el).cumulativeOffset(),
				links = this.templates.invoke('evaluate',{user_id: user_id, name: name, email: email, xf_user_id: XF_JS.User.ID}),
		 		container = new Element('div',{'class': 'xf_menu desktop useroptions',style: 'left:'+pos[0] +'px;top:'+ (Number(pos[1]) + $(el).getHeight()) +'px;'});
		 		if (extra_url){
		 			var extra_container = new Element('div',{'class': 'extra_container'}).ajaxUpdate(extra_url);
		 			container.insert(extra_container);
				}
				container.insert('<ul><li>'+links.join('</li><li>')+'</li></ul>');
		 		container.select('a').invoke('addClassName','enabled');
		//container.onmouseout = function(){this.hide();}.bindAsEventListener(container);
		$(document.body).insert(container);
		this.userlinks.push(container);
		return false;
	},
	addTemplate:function(template, tid){
		//only add if not already added
		if (!this.templates[tid]) {
			this.templates[tid] = new Template(template);
		}
	},
	hide:function(){
		this.userlinks.invoke('remove');
		this.userlinks.clear();
	}
};

XF_JS.docLink = {
	templates: [],
	doclinks: [],
	ajaxurl: '/doclink/api/',
	show:function(el){
		this.hide();
		this.firstTime = true;
		if (!this.observer){
	    this.observer = document.observe('click', function(e) {
	    	if(Event.element(e).up('.xf_menu')){
	    	}else
				if (!Event.isRightClick(e) && !this.firstTime) {
					this.hide();
				}
				this.firstTime = false;
			}.bind(this));
		}
		var vpw = document.viewport.getWidth(),
				pos = $(el).cumulativeOffset(),
		 		container = new Element('div',{'class': 'xf_menu desktop doclinks',style: 'left:'+(((Number(pos[0])+150)>vpw)?(Number(pos[0])-150):pos[0]) +'px;top:'+ (Number(pos[1]) + $(el).getHeight()) +'px;'});
		var ajax_container = new Element('div',{'class': ''}).ajaxUpdate(this.ajaxurl+el.readAttribute('rel'),{onComplete:this.register_actions.bind(this)});
		container.insert(ajax_container);
		$(document.body).insert(container);
		this.doclinks.push(container);
		return false;
	},
	hide:function(){
		this.doclinks.invoke('remove');
		this.doclinks.clear();
	},
	register_actions:function(){
		this.doclinks[0].select('a.doclink_action').each(function(el){
			el.onclick = this.doclink_action.bindAsEventListener(this,el);
		}.bind(this));
	},
	doclink_action:function(e,el){
		Event.stop(e);
		new Ajax.Request(el.href,{
			onSuccess: this.doclink_response.bind(this)
		});
	},
	doclink_response:function(r){
		switch(r.headerJSON.error_code){
			case -3:
			case 2:
			//Modal
			 var cm = new Control.Modal(false, {width:800});
			 cm.showcontent(r.responseText,r.headerJSON.title);
			break;
			
			case 3:
			//Redirect
			XF_JS.FSLoader.show();
			window.location = r.headerJSON.url;
			break;
			
			case 4:
			// open url in iframe modal
			var cm = new Control.Modal(false, {width: r.headerJSON.width, height: r.headerJSON.height});
			cm.openiFrame(r.headerJSON.url, r.headerJSON.title);
			break;
			
			default:
				//Evaluate JS in response
				r.responseText.evalScripts();
			break;
		}
		this.hide();
	},
	register_single_actions:function(el){
		if(el) {
			el.onclick = this.doclink_action.bindAsEventListener(this,el);
		}
	}
};

/* Mouse Out Hover Function */
XF_JS.hoverMenu = {
	delay_in: 0.3,
	delay_out: 0.3,
  over:function(id,all){
    window.clearTimeout(this.to);
    if (all != undefined){
    	all.without(id).invoke('hide');
      all.each(function(el){ if (el.previous()) el.previous().removeClassName('hover'); })
		}
		if (XF_JS.hoverMenu.delay_in>0){
    	new Effect.Appear(id,{duration:XF_JS.hoverMenu.delay_in});
		}else{
			Element.show(id);
		}
    if ($(id).previous()){ $(id).previous().addClassName('hover');}

	},
  out:function(id){
  	if(XF_JS.hoverMenu.delay_out>0){
    	this.to = function(){
                  Element.hide(id);
                  if ($(id).previous()){ $(id).previous().removeClassName('hover');}          
                }.delay(XF_JS.hoverMenu.delay_out);
		}else{
			Element.hide(id);
      if ($(id).previous()){ $(id).previous().removeClassName('hover');}  
		}
    
	}
};


/* Scriptacolous Autocompleter Page Jump Fix - http://blog.gilluminate.com/2009/01/20/scriptaculous-autocomplete-page-jump-using-arrow-keys/ */
Ajax.Autocompleter = Class.create();
Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype), {
	initialize: function(element, update, url, options) {
		this.baseInitialize(element, update, options);
		this.options.asynchronous = true;
		this.options.onComplete = this.onComplete.bind(this);
		this.options.defaultParams = this.options.parameters || null;
		this.url = url;
		this.cache = {};
	},

	getUpdatedChoices: function() {
		var t = this.getToken();
		if (this.cache[t]) {
			this.updateChoices(this.cache[t]);
		} else {
			entry = encodeURIComponent(this.options.paramName) + '=' +
			encodeURIComponent(t);

			this.options.parameters = this.options.callback ?
			this.options.callback(this.element, entry) : entry;

			if(this.options.defaultParams)
				this.options.parameters += '&' + this.options.defaultParams;

			new Ajax.Request(this.url, this.options);
		}
	},

	onComplete: function(request) {
		this.updateChoices(this.cache[this.getToken()] = request.responseText);
	},

	// Page jump fix
	markPrevious: function() {
		if (this.index > 0) {
			this.index--;
		} else {
			this.index = this.entryCount-1;
			this.update.scrollTop = this.update.scrollHeight;
		}

		selection = this.getEntry(this.index);
		selection_top = selection.offsetTop;

		if (selection_top < this.update.scrollTop) {
			this.update.scrollTop = this.update.scrollTop - selection.offsetHeight;
		}
	},

	markNext: function() {
		if(this.index < this.entryCount-1) {this.index++;}
		else {
			this.index = 0;
			this.update.scrollTop = 0;
		}
		selection = this.getEntry(this.index);
		selection_bottom = selection.offsetTop+selection.offsetHeight;
		if(selection_bottom > this.update.scrollTop+this.update.offsetHeight){
			this.update.scrollTop = this.update.scrollTop+selection.offsetHeight;
		}
	},

	updateChoices: function(choices) {
		if (!this.changed && this.hasFocus) {
			this.update.innerHTML = choices;
			Element.cleanWhitespace(this.update);
			Element.cleanWhitespace(this.update.down());

			if (this.update.firstChild && this.update.down().childNodes) {
				this.entryCount =
				this.update.down().childNodes.length;
				for (var i = 0; i < this.entryCount; i++) {
					var entry = this.getEntry(i);
					entry.autocompleteIndex = i;
					this.addObservers(entry);
				}
			} else {
				this.entryCount = 0;
			}

			this.stopIndicator();
			this.update.scrollTop = 0;
			this.index = -1;

			if (this.entryCount==1 && this.options.autoSelect) {
				this.selectEntry();
				this.hide();
			} else {
				this.render();
			}
		}
	}
});

/*
 Scroll within divs
*/
Element.addMethods({
  scrollTo: function(element, left, top){
    var element = $(element);
    if (arguments.length == 1){
      var pos = element.cumulativeOffset();
      window.scrollTo(pos[0], pos[1]);
    } else {
      element.scrollLeft = left;
      element.scrollTop  = top;
    }
    return element;
  }
});
Effect.Scroll = Class.create();
Object.extend(Object.extend(Effect.Scroll.prototype, Effect.Base.prototype), {
  initialize: function(element) {
    this.element = $(element);
    if(!this.element){
    	throw(Effect._elementDoesNotExistError);
		}
    var params = Object.extend({x: 0, y: 0, mode: 'relative'}, arguments[1] || {});
    if (params.mode === 'absolute'){
    	params.x = params.x - this.element.offsetLeft;
    	params.y = params.y - this.element.offsetTop;
		}
    this.start(params);
  },
  setup: function() {
    var scrollOffsets = (this.element == window)
                ? document.viewport.getScrollOffsets()
                : Element._returnOffset(this.element.scrollLeft, this.element.scrollTop) ;
    this.originalScrollLeft = scrollOffsets.left;
    this.originalScrollTop  = scrollOffsets.top;
  },
  update: function(pos) {
  	var x = Math.round(this.options.x * pos + this.originalScrollLeft);
  	var y = Math.round(this.options.y * pos + this.originalScrollTop);
    this.element.scrollTo(x,y);
  }
});


/**
* Flash Message Popup Notifier -------------------------------------------------------------------------------------
*/
XF_JS.FlashMessenger = Class.create();
XF_JS.FlashMessenger.prototype = {
	initialize:function(el, options){
		this.options = Object.extend({
				duration: 5,
				displayContainer: false
	  }, options || {});

	  if (this.options.displayContainer){
	  	// Use existing container
	  	this.flashContainer = $(this.options.displayContainer);
	  } else {
			this.flashContainer = Builder.node('div', {id:'flash_messenger_wrap'});
			$$('body').first().appendChild(this.flashContainer);
		}
	},
	// Collect messages from an static container containing div elements with messages
	collectFlashMessages: function(flash_container){
	  if ($(flash_container)){
			$(flash_container).select('div').each(function(el){
				this.showMessage(el.innerHTML, el.className);
			}.bind(this));
		}
	},
	showMessage: function(msg, type, duration){
		return new XF_JS.FlashMessageItem(msg, type, duration);
	}
}

XF_JS.FlashMessageItem = Class.create();
XF_JS.FlashMessageItem.prototype = {
	initialize:function(msg, type, duration){
		type = type || 'note';
		duration = duration || XF_JS.FlashMessenger.options.duration;
		this.wrap = Builder.node('div', {'class': 'flash_message_wrap', style: 'display: none;'});
		this.wrap.onclick = this.close.bindAsEventListener(this);
		XF_JS.FlashMessenger.flashContainer.appendChild(this.wrap);
		this.container = Builder.node('div', {'class': 'flash_message_container '+type}, msg);
		this.wrap.appendChild(this.container);
		new Effect.Appear(this.wrap, {duration: 0.4});

		if (type.trim()!='error') this.enableAutoClose(duration); else new Effect.Shake(this.wrap,{duration: 1, distance:10});
	},
	close: function(){
		if (this.periodicExecuter) this.periodicExecuter.stop();
		new Effect.Fade(this.container, {to: 0.01, duration: 0.2, afterFinish: function(){
			new Effect.BlindUp(this.wrap, {duration: 0.2, afterFinish: function(){
				if (this.wrap) this.wrap.remove();
			}});
		}.bind(this)});
	},
	enableAutoClose: function(duration){
		if (duration && duration>0){
			this.periodicExecuter = new PeriodicalExecuter(this.close.bindAsEventListener(this), duration);
		}
	}
}

// Inspect all AJAX responses for possible flash messages being delivered
Ajax.Responders.register({
  onComplete:	function(a,b,jsonHeader) {
  	if (jsonHeader && jsonHeader.flash){
  		jsonHeader.flash.each(function(message){
				XF_JS.flashMessage(message.msg, message.type);
  		});
  	}
  }
});

// Auto-Tooltip for all a links with title property
XF_JS.enableAutoTooltip = function(){
   $$('a[title]').invoke('observe', 'mouseover', function(evt){
    var el = evt.findElement('a'), text = el.getAttribute('title');
    var t = new Tooltip(el,text);
    t.showTooltip(evt);
    el.setAttribute('title',''); el.setAttribute('_title', text);
   
   }).invoke('observe', 'mouseout', function(evt){
     var el = evt.findElement('a'), text = el.getAttribute('_title');
     el.removeAttribute('_title'); el.setAttribute('title', text);
   });
};

// Initialize Flash Message System
document.observe('dom:loaded',function(){
	try {
		XF_JS.FlashMessenger = new XF_JS.FlashMessenger();
	}
	catch (e){
		
	}
	XF_JS.FlashMessenger.collectFlashMessages('flash_messages'); // Take existing static flash messages and display them
	XF_JS.flashMessage = XF_JS.FlashMessenger.showMessage;
  //XF_JS.enableAutoTooltip();
});

/* ----------------------------------------------------------------------------------------------------------------------------- */

XF_JS.FormCopy = Class.create({
	options: {url:'/custom/scripts/jscopypaste'},
	initialize:function(form){
		this.form = $(form);
		toolbar = new Element('div',{'class':'toolbar','align':'right'});
		button = new Element('a',{'class':'icon_edit','href':'javascript:void(0)'}).update('Copy');
		button.onclick = this.copy.bindAsEventListener(this);
		toolbar.insert({top:button});
		
		button = new Element('a',{'class':'icon_paste','href':'javascript:void(0)'}).update('Paste');
		button.onclick = this.paste.bindAsEventListener(this);
		toolbar.insert({top:button});
		this.form.insert({top:toolbar});
	},
	copy:function(){
		new Ajax.Request(this.options.url, {
        method: 'post',
        postBody: this.form.serialize(),
        onSuccess: function(r){
					XF_JS.flashMessage(r.responseText,'success');
        },
        onFailure: function(){alert('error');}
      });
	},
	paste:function(){
		new Ajax.Request(this.options.url, {
        method: 'get',
        parameters: '&name='+this.form.name,
        onSuccess: this.populateData.bind(this),
        onFailure: function(){alert('error');}
      });
	},
	populateData:function(r){
		if (!r.headerJSON.form_copy_found){
			XF_JS.flashMessage("No valid form values found",'error');
			return;
		}
		var formdata = r.responseText.evalJSON();
		try {
			var fcks = $H(FCKeditorAPI.__Instances).keys();
		}catch(e){
			var fcks = [];
		}
		this.form.getElements().each(function(el){
			form_value = formdata[el.name] ? formdata[el.name] : '';
			switch(el.type){
				case 'hidden':
				//skip hidden fields
				break;
				
				case 'textbox':
				case 'text':
				 el.value = form_value;
				 new Effect.Highlight(el,{duration:3});
				break;
				
				case 'textarea':
					if(fcks.indexOf(el.id) > -1){
						FCKeditorAPI.Instances[el.id].SetHTML(form_value);
					}else{
						el.value = form_value;
						new Effect.Highlight(el,{duration:3});
					}
				break;
				
				case 'select':
				case 'select-one':
					var options = $A(el.options).pluck('value')
					el.selectedIndex = options.indexOf(form_value);
					new Effect.Highlight(el,{duration:3});
				break;
				
				default:
					//console.log(formdata[el.type]);
				break;
			}
		}.bind(this));
		XF_JS.flashMessage("Form populated",'success');
	}
	
});


/* ----------------------------------------------------------------------------------------------------------------------------- */

XF_JS.Bubbles = Class.create({
	apiUrl:'/system_bubbles/api/',
	overviewUrl:'/system_bubbles/overview/',
	bubbleNode:false,
	_inprogress:false,
	pollInfo:{},
	initialize:function(){
		this.bubbles = $$('.bubble');
		this.bubbleNode = new Element('span').addClassName('c').update('0');
		if(this.bubbles && this.bubbles.length>0){
			this.init();
			this.checkForNotifications();
			this.pe = new PeriodicalExecuter(this.checkForNotifications.bind(this),30);
			this.timer = false;
		}
	},
	init:function(){
		this.bubbles.each(function(el,k){
			var rel = el.readAttribute('rel');
			if(rel){
				el.addClassName('read');
				var bubble = this.bubbleNode.cloneNode(1);
				bubble.onmouseover = this.moreInfoOpen.bindAsEventListener(this);
				bubble.onmouseout = this.moreInfoTimeout.bindAsEventListener(this);
				el.insert({bottom: bubble});
				if(!this.pollInfo[rel]) this.pollInfo[rel] = [];
				this.pollInfo[rel].push(el);
			}
		}.bind(this));
		this.overlayDIV = new Element('div').addClassName('bubbleInfo').update('<div class="unreadDocs"></div><div class="actions"></div>').hide();
		var hideBTN = new Element('a',{'href':'javascript:void(0)'}).addClassName('hide').update('Hide');
		hideBTN.onclick = function(){this.overlayDIV.hide();}.bind(this);
		this.overlayDIV.insert({top:hideBTN})
		
		var markRead = new Element('a',{'href':'javascript:void(0)'}).addClassName('markread').update('Mark as read');
		markRead.onclick = this.markRead.bindAsEventListener(this);
		this.overlayDIV.down('div.actions').insert({bottom:markRead});
		document.body.appendChild(this.overlayDIV);
	},
	checkForNotifications:function(){
		if(this._inprogress){return;}
		else {this._inprogress = true;}
		new Ajax.Request(this.apiUrl,{
			postBody:'pollInfo='+Object.keys(this.pollInfo).toJSON(),
			onSuccess:this.updateBubbles.bind(this),
			onFailure:function(){this.pe.stop();},
			evalJSON:'force'
		});
	},
	updateBubbles:function(r){
		if(r.responseJSON && r.responseJSON.pollInfo){
			var rels = Object.keys(r.responseJSON.pollInfo);
			rels.each(function(rel){
				var count = r.responseJSON.pollInfo[rel];
				if(this.pollInfo[rel]){
					this.pollInfo[rel].each(function(el){
						if(parseInt(el.down('span.c').innerHTML) > 0 && parseInt(el.down('span.c').innerHTML) < parseInt(count)){
							el.addClassName('new');el.addClassName('unread');
							el.removeClassName('read');
						}else if(parseInt(count) > 0){
							el.addClassName('unread');
							el.removeClassName('read');
						}else {
							el.addClassName('read');
							el.removeClassName('unread');
						}
						el.down('span.c').update(count);
					}.bind(this));
				}
			}.bind(this));
			this._inprogress = false;
		}else{
			this.pe.stop();
		}
	},
	moreInfo:function(el){
		this.overlayDIV.down('div.unreadDocs').update('<div class="loading">Loading</div>');
		new Ajax.Request(this.apiUrl,{
				postBody:'moreInfo='+el.readAttribute('rel'),
				onSuccess:function(r){this.overlayDIV.down('div.unreadDocs').update(r.responseText);}.bind(this)
			});
		var pos = el.down('span.c').cumulativeOffset();
		var dim = el.down('span.c').getDimensions();
		var dimb = this.overlayDIV.getDimensions();
		this.overlayDIV.setStyle({left:(pos.left-dimb.width+30)+'px',top:(pos.top+dim.height+5)+'px'});
		new Effect.Appear(this.overlayDIV,{duration:0.2});
    $$('body').first().observe('click', function(el){this.overlayDIV.hide();}.bind(this));
	},
	moreInfoOpen:function(e){
		this.last_el = Event.element(e).up('a.bubble');
		if(this.timer){	window.clearTimeout(this.timer);}
		this.timer = window.setTimeout(function(el){this.moreInfo(el);}.bind(this,this.last_el),400);
	},
	moreInfoClose:function(e){
		if(this.timer){window.clearTimeout(this.timer);}
		this.overlayDIV.hide();
	},
	moreInfoTimeout:function(e){
		if(this.timer){window.clearTimeout(this.timer);}
	},
	markRead:function(e){
		var rel = this.last_el.readAttribute('rel');
		if(rel){
			new Ajax.Request(this.apiUrl,{
				postBody:'markRead='+rel
			});
			this.pollInfo[rel].each(function(el){
				el.addClassName('read');
				el.removeClassName('unread');
			});
		}
		this.moreInfoClose();
	}
});

XF_JS.windowActive = Class.create({
	initialize:function(){
		window.onfocus = function(){
			XF_JS.windowActive = true;
		};
		window.onblur  = function(){
			XF_JS.windowActive = false;
		};
	}
});
