

/*
   Behaviour v1.0 by Ben Nolan, June 2005. Based largely on the work
   of Simon Willison (see comments by Simon below).

   Description:
   	
   	Uses css selectors to apply javascript behaviours to enable
   	unobtrusive javascript in html documents.
   	
   Usage:   
   
	var myrules = {
		'b.someclass' : function(element){
			element.onclick = function(){
				alert(this.innerHTML);
			}
		},
		'#someid u' : function(element){
			element.onmouseover = function(){
				this.innerHTML = "BLAH!";
			}
		}
	);
	
	Behaviour.register(myrules);
	
	// Call Behaviour.apply() to re-apply the rules (if you
	// update the dom, etc).

   License:
   
   	My stuff is BSD licensed. Not sure about Simon's.
   	
   More information:
   	
   	http://ripcord.co.nz/behaviour/
   
*/   

var Behaviour = {
	list : new Array,
	
	register : function(sheet){
		Behaviour.list.push(sheet);
	},
	
	start : function(){
		Behaviour.addLoadEvent(function(){
			Behaviour.apply();
		});
	},
	
	apply : function(){
		for (h=0;sheet=Behaviour.list[h];h++){
			for (selector in sheet){
				list = document.getElementsBySelector(selector);
				
				if (!list){
					continue;
				}

				for (i=0;element=list[i];i++){
					sheet[selector](element);
				}
			}
		}
	},
	
	addLoadEvent : function(func){
		var oldonload = window.onload;
		
		if (typeof window.onload != 'function') {
			window.onload = func;
		} else {
			window.onload = function() {
				oldonload();
				func();
			}
		}
	}
}

Behaviour.start();

/*
   The following code is Copyright (C) Simon Willison 2004.

   document.getElementsBySelector(selector)
   - returns an array of element objects from the current document
     matching the CSS selector. Selectors can contain element names, 
     class names and ids and can be nested. For example:
     
       elements = document.getElementsBySelect('div#main p a.external')
     
     Will return an array of all 'a' elements with 'external' in their 
     class attribute that are contained inside 'p' elements that are 
     contained inside the 'div' element which has id="main"

   New in version 0.4: Support for CSS2 and CSS3 attribute selectors:
   See http://www.w3.org/TR/css3-selectors/#attribute-selectors

   Version 0.4 - Simon Willison, March 25th 2003
   -- Works in Phoenix 0.5, Mozilla 1.3, Opera 7, Internet Explorer 6, Internet Explorer 5 on Windows
   -- Opera 7 fails 
*/

function getAllChildren(e) {
  // Returns all children of element. Workaround required for IE5/Windows. Ugh.
  return e.all ? e.all : e.getElementsByTagName('*');
}

document.getElementsBySelector = function(selector) {
  // Attempt to fail gracefully in lesser browsers
  if (!document.getElementsByTagName) {
    return new Array();
  }
  // Split selector in to tokens
  var tokens = selector.split(' ');
  var currentContext = new Array(document);
  for (var i = 0; i < tokens.length; i++) {
    token = tokens[i].replace(/^\s+/,'').replace(/\s+$/,'');;
    if (token.indexOf('#') > -1) {
      // Token is an ID selector
      var bits = token.split('#');
      var tagName = bits[0];
      var id = bits[1];
      
      var element = document.getElementById(id);
      if (tagName && element.nodeName.toLowerCase() != tagName) {
        // tag with that ID not found, return false
        return new Array();
      }
      // Set currentContext to contain just this element
      currentContext = new Array(element);
      continue; // Skip to next token
    }
    if (token.indexOf('.') > -1) {
      // Token contains a class selector
      var bits = token.split('.');
      var tagName = bits[0];
      var className = bits[1];
      if (!tagName) {
        tagName = '*';
      }
      // Get elements matching tag, filter them for class selector
      var found = new Array;
      var foundCount = 0;
      for (var h = 0; h < currentContext.length; h++) {
        var elements;
        if (tagName == '*') {
            elements = getAllChildren(currentContext[h]);
        } else {
            elements = currentContext[h].getElementsByTagName(tagName);
        }
        for (var j = 0; j < elements.length; j++) {
          found[foundCount++] = elements[j];
        }
      }
      currentContext = new Array;
      var currentContextIndex = 0;
      for (var k = 0; k < found.length; k++) {
        if (found[k].className && found[k].className.match(new RegExp('\\b'+className+'\\b'))) {
          currentContext[currentContextIndex++] = found[k];
        }
      }
      continue; // Skip to next token
    }
    // Code to deal with attribute selectors
    if (token.match(/^(\w*)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/)) {
      var tagName = RegExp.$1;
      var attrName = RegExp.$2;
      var attrOperator = RegExp.$3;
      var attrValue = RegExp.$4;
      if (!tagName) {
        tagName = '*';
      }
      // Grab all of the tagName elements within current context
      var found = new Array;
      var foundCount = 0;
      for (var h = 0; h < currentContext.length; h++) {
        var elements;
        if (tagName == '*') {
            elements = getAllChildren(currentContext[h]);
        } else {
            elements = currentContext[h].getElementsByTagName(tagName);
        }
        for (var j = 0; j < elements.length; j++) {
          found[foundCount++] = elements[j];
        }
      }
      currentContext = new Array;
      var currentContextIndex = 0;
      var checkFunction; // This function will be used to filter the elements
      switch (attrOperator) {
        case '=': // Equality
          checkFunction = function(e) { return (e.getAttribute(attrName) == attrValue); };
          break;
        case '~': // Match one of space seperated words 
          checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('\\b'+attrValue+'\\b'))); };
          break;
        case '|': // Match start with value followed by optional hyphen
          checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('^'+attrValue+'-?'))); };
          break;
        case '^': // Match starts with value
          checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) == 0); };
          break;
        case '$': // Match ends with value - fails with "Warning" in Opera 7
          checkFunction = function(e) { return (e.getAttribute(attrName).lastIndexOf(attrValue) == e.getAttribute(attrName).length - attrValue.length); };
          break;
        case '*': // Match ends with value
          checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) > -1); };
          break;
        default :
          // Just test for existence of attribute
          checkFunction = function(e) { return e.getAttribute(attrName); };
      }
      currentContext = new Array;
      var currentContextIndex = 0;
      for (var k = 0; k < found.length; k++) {
        if (checkFunction(found[k])) {
          currentContext[currentContextIndex++] = found[k];
        }
      }
      // alert('Attribute Selector: '+tagName+' '+attrName+' '+attrOperator+' '+attrValue);
      continue; // Skip to next token
    }
    
    if (!currentContext[0]){
    	return;
    }
    
    // If we get here, token is JUST an element (not a class or ID selector)
    tagName = token;
    var found = new Array;
    var foundCount = 0;
    for (var h = 0; h < currentContext.length; h++) {
      var elements = currentContext[h].getElementsByTagName(tagName);
      for (var j = 0; j < elements.length; j++) {
        found[foundCount++] = elements[j];
      }
    }
    currentContext = found;
  }
  return currentContext;
}

/* That revolting regular expression explained 
/^(\w+)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/
  \---/  \---/\-------------/    \-------/
    |      |         |               |
    |      |         |           The value
    |      |    ~,|,^,$,* or =
    |   Attribute 
   Tag
*/


/****************************************************
 * Funciones de submit
 ****************************************************/

function FormSubmitter(formName, formCbs)
{
	this.formName = formName;
	this.form = document[formName];
	this.formCbs = formCbs;
}

function bloqueaWindow(){
	Dialog.info(MENSAJES['enviando_datos'],
               {windowParameters: {className:"alphacube",width:250, height:100},showEffectOptions:{duration:0.2}, showProgress: true});
}
/**
 * Comproba los datos antes de ejecutar la acción.
 * Se suele utilizar para modificar un registro desde la ficha.
 */
FormSubmitter.prototype.valida_busca = function(accion)
{
	
	this.form.accion.value = accion;
	this.form.issearch.value = 1;
	oFormCallbacks.validateInServerForm();
	return false;
	
	if (this.formCbs.isValidAlert() && this.formCbs.isCompleteAlert()) {
		this.form.accion.value = accion;
		this.form.issearch.value = 1;
		this.formCbs.submit();
		this.form.submit();
		//return true;
	}
	return false;
}

/**
 * Comproba los datos antes de ejecutar la acción.
 * Se suele utilizar para modificar un registro desde la ficha.
 */
FormSubmitter.prototype.valida_ejecuta = function(accion)
{
	bloqueaWindow();
	this.form.accion.value = accion;
	oFormCallbacks.validateInServerForm();
	return false;
}

/**
 * Comproba los datos antes de ejecutar la acción.
 * Se suele utilizar para modificar un registro desde la ficha.
 */
FormSubmitter.prototype.valida_ejecuta_tab = function(accion,regMatch)
{
	this.form.accion.value = accion;
	oFormCallbacks.validateInServerForm(regMatch);
	return false;
}


/**
 * Ejecuta la acción sin confirmación ni comprobación.
 * Sin pasar el id: se suele utilizar para volver al listado.
 * Pasando el id: Se suele utilizar para ir del listado a una ficha.
 */
FormSubmitter.prototype.ejecuta = function(accion, id)
{
	this.form.accion.value = accion;
	this.form.id.value = id;
	this.form.submit();
	return false;
}

FormSubmitter.prototype.ejecutaInNewWindow = function(accion, id)
{
	var odlAccion = this.form.accion.value;
	var oldId = this.form.id.value;

	this.form.target = "_blank";
	this.form.accion.value = accion;
	this.form.id.value = id;
	this.form.submit();
	this.form.target = "_self";

	this.form.accion.value = odlAccion;
	this.form.id.value = oldId;
	return false;
}


FormSubmitter.prototype.ejecutaInNewWindowNewDest = function(accionNew, id, newUrl)
{
	var odlAccion = this.form.accion.value;
	var oldId = this.form.id.value;
	
	this.form.action = newUrl;
	this.form.target = "_blank";
	this.form.accion.value = accionNew;
	this.form.id.value = id;
	this.form.submit();
	this.form.target = "_self";
	this.form.action = '';
	
	this.form.accion.value = odlAccion;
	this.form.id.value = oldId;
	return false;
}

/**
 * Cambia el target del form.
 */
FormSubmitter.prototype.setTarget = function(dest)
{
	this.form.action = dest;
	
}

/**
 * Pide una confirmación antes de ejecutar la acción.
 * Sin pasar id: Se suele utilizar para eliminar un registro desde la ficha.
 * Pasando un id: Se suele utilizar para eliminar un registro desde el listado.
 */
FormSubmitter.prototype.confirma = function(accion, id)
{
	var accionTest = accion;
	if (accion.indexOf('.') > 0) {
		accionTest = accion.split('.');
		accionTest = accionTest[1];
	}
	
	if (accionTest.substr(0,3) == "del") {
		//"Confirme que desea eliminar el registro.";
		msg = MENSAJES['confirmDel'];
	}
	
	if (accionTest.substr(0,4) == "send") {
		//"Confirme que desea enviar el registro";
		msg = MENSAJES['confirmSend'];
	}
	
	Dialog.confirm(msg, 
		{windowParameters: {className:"alphacube",width:300}, okLabel: "OK", 
		buttonClass: "myButtonClass",
		id: "msgAlert",
		showEffectOptions:{duration:0.2},
		cancel:function(win) {return false;},
		ok:function(win) {s.ejecuta(accion, id); return true;}
		});
	return false;
}


FormSubmitter.prototype.autoSave = function(accion, id)
{

	msg = MENSAJES['confirmAutoSave'];
	
	Dialog.confirm(msg, 
		{windowParameters: {className:"alphacube",width:300}, okLabel: "OK", 
		buttonClass: "myButtonClass",
		id: "msgAlert",
		showEffectOptions:{duration:0.2},
		cancel:function(win) {return false;},
		ok:function(win) {s.valida_ejecuta(accion, id); return true;}
		});
	return false;
}


/**
 * Pide una confirmación antes de eliminar una foto.
 */
FormSubmitter.prototype.eliminar_foto = function(memname)
{
	if ( confirm(MENSAJES['confirmDelFile']) ) {
		this.form.accion.value = "delfoto:" + memname;
		this.form.submit();
	}
}

FormSubmitter.prototype.eliminar_fotoAjax = function(memname)
{
	var msg = MENSAJES['confirmDelFile'];
	var formu = this.form;
	Dialog.confirm(msg, 
		{windowParameters: {className:"alphacube",width:300}, okLabel: "OK", 
		buttonClass: "myButtonClass",
		id: "msgAlert",
		showEffectOptions:{duration:0.2},
		cancel:function(win) {return false;},
		ok:function(win) {
				var oldAccion = formu.accion.value;
				formu.accion.value = "ajaxDelfoto:" + memname;
				var valsForm = Form.serialize(document.f);
				valsForm = valsForm.split('accion_').join('boton_');
				formu.accion.value = oldAccion;
				var opt = {
						method: 'post',
						asynchronous:true,
						postBody: valsForm,
						onSuccess: function(t) {
							document.f.elements[memname].value = 0;
							new Effect.BlindUp('contenedor_' + memname, {duration:0.3});
							new Insertion.Bottom(document.body,t.responseText);
							}
					};
				new Ajax.Request(formu.action, opt);
				return true;
			}
		});
	return false;
}

/**
 * Pide una confirmación antes de eliminar una foto.
 */
FormSubmitter.prototype.eliminar_file = function(memname)
{
	if ( confirm(MENSAJES['confirmDelFile']) ) {
		this.form.accion.value = "delfile:" + memname;
		this.form.submit();
	}
}

FormSubmitter.prototype.eliminar_fileAjax = function(memname)
{
	var msg = MENSAJES['confirmDelFile'];
	var formu = this.form;
	Dialog.confirm(msg, 
		{windowParameters: {className:"alphacube",width:300}, okLabel: "OK", 
		buttonClass: "myButtonClass",
		id: "msgAlert",
		showEffectOptions:{duration:0.2},
		cancel:function(win) {return false;},
		ok:function(win) {
				var oldAccion = formu.accion.value;
				formu.accion.value = "ajaxDelfile:" + memname;
				var valsForm = Form.serialize(document.f);
				valsForm = valsForm.split('accion_').join('boton_');
				formu.accion.value = oldAccion;
				var opt = {
						method: 'post',
						asynchronous:true,
						postBody: valsForm,
						onSuccess: function(t) {
							document.f.elements['F_' + memname].value = '';
							new Effect.BlindUp('contenedor_' + memname);
							
							if($('contenedor_' + memname + '_imgprev')){
								new Effect.BlindUp('contenedor_' + memname + '_imgprev');
							}
						}
					};
				new Ajax.Request(formu.action, opt);
				return true;
			}
		});
	return false;
}

/**
 * Recarga la página ajustando el orden de la columna 'by'.
 */
FormSubmitter.prototype.paginate = function(by)
{
	var currBy = this.form.orderBy.value;
	if (currBy == by) {
		this.form.orderDir.value =
			(this.form.orderDir.value == 'DESC') ? 'ASC' : 'DESC';
	} else {
		this.form.orderDir.value = 'ASC';
	}
	this.form.orderBy.value = by;
	
	this.form.submit();
}

// pone a 0 el formulario dejando los hidden sin resetear
function resetForm(objForm)
{
	for(var i = 0;i < objForm.elements.length;i ++){
		var obj = objForm.elements[i];
		switch(obj.type){
			case "select-one":
				if(obj.name != 'regsPerPage'){
					obj.selectedIndex = 0;
				}
				break;
			case "select-multiple":
				obj.selectedIndex = -1;
				break;
			case "checkbox":
				obj.checked = false;
				break;
			case "text":
				var hiddenId = obj.id.substr(5,100);
				if($(hiddenId)){
					$(hiddenId).value = '';
				}
				obj.value = "";
				break;
			case "file":
			case "textarea":
				obj.value = "";
				break;
		}
		
	}
	return false;
}


/**
 * Event Handler para los cambios
 *
 * Se añade a cada elemento del formulario con el código:
 * <input ... onchanged='changed(this)' />
 */
function changed(el)
{
	el = $(el);
	
	var arr = el.name.split("[");
	var	formElementName = arr[0];
	formElementName = formElementName.replace('Out','In');
	if(oFormCallbacks.configMembers[formElementName]){
		oFormCallbacks.configMembers[formElementName].validateInServer();
	}
}

function multiselSelect(elName,onOff)
{
	if(!$(elName)) return;
	if(onOff !== false) onOff = true;
	var selFrom = document.f[elName + "[]"];
	var optFrom = selFrom.options;
	for(var f=0; f<optFrom.length; f++) {
		optFrom[f].selected = onOff;
	}
}


// Associated functions
/**
 * Shows a popup window with a calendar in flash
 *
 * @param string name of the form
 * @param string name of the field to receive the selected date
 */
function showCalendar(form,campo)
{
	var f = (document.forms[form].elements[campo].value);
	fecha = f.split("-");
	d = fecha[0];
	m = fecha[1]-1;
	y = fecha[2];
	win = newWindow('../inc/base/miniCal.php?y='+y+'&m='+m+'&d='+d+'&form='+form+'&campo='+campo,'Calendario',150,150,'');
}

/**
 * Fills the field with a given date
 *
 * @param string name of the form
 * @param string name of the field to receive the date
 * @param mixed date to put into field
 */
function setDate(form,campo,fecha)
{
	elInput = (document.forms[form].elements[campo]);
	
	fecha = fecha.split("-");
	var d = eval(fecha[0]);
	var m = eval(fecha[1]);
	var y = fecha[2];
	if(d<10) d = '0'+d;
	if(m<10) m = '0'+m;
 	elInput.value = d + '-' + m + '-' + y;
	elInput.focus();
	
	if(elInput.onchange){
		elInput.onchange();
	}
}

var MemberDedoLib = Class.create();
MemberDedoLib.prototype = {
   initialize: function(formElementName, pTipo, pFormat, pRequired, pTitle, pEnabled, pValidateFunc) {
		this.a_name = this.getMemberName(formElementName);
		
		this.element = $(this.a_name);
		this.a_tipo = pTipo;
		this.a_format = pFormat;
		this.a_required = pRequired;
		this.a_title = pTitle;
		this.a_enabled = false;
		
		this.a_accesibleVal = '';
		if(Element.hasClassName(this.element,'accesibleVal')){
			this.a_accesibleVal = this.element.value;
		}
		if(pEnabled == '1') this.a_enabled = true;
	
		var validateFunc = '';
		if(pValidateFunc) validateFunc = pValidateFunc;
		this.a_validateFunc = validateFunc;
		
		this.hasError = false;
		// extras
		this.setLabel(this.a_name);
		
		this.addHelpers();
		//this.setSpanError(this.a_name);
		this.setElToInsert(this.a_name);
   },
   
   getMemberName: function(formElementName) {
		var arr = formElementName.split("[");
		formElementName = arr[0];
		formElementName = formElementName.replace('Out','In');
		return formElementName;
   },
   
   addHelpers: function() {
   		if($(this.a_name) && $(this.a_name).hasClassName('noApplyJS')) return;
		if(this.a_tipo == 'date'){
			if(!$('H_'+this.a_name)) return;
			if($('H_'+this.a_name) && $('H_'+this.a_name).hasClassName('noApplyJS')) return;
			if($('H_'+this.a_name).type == 'hidden') return;
			var calIcon = '&nbsp;<span class="calIconFechas"><a id="cal_icon_'+this.a_name+'" href="#arriba" onclick="showDivDateChoose(\'f\',\''+this.a_name+'\');\">';
			calIcon += '<img src="../images/dedolib/bt_hoy.gif" alt="Opciones Fechas" />';
			calIcon += '<\/a><\/span>';
			new Insertion.After($('H_'+this.a_name), calIcon);
		}
		
		if(this.a_tipo == 'text'){
			if(!$(this.a_name)) return;
			if(!$(this.label)) return;
			var calIcon = '<div class="clear_both"></div>';
			calIcon += '<div style="text-align:right;">';
			calIcon += '<a href="#arriba" onclick="changeHeightTextArea(\''+this.a_name+'\',30);return false;">';
			calIcon += '<img src="../images/dedolib/icon_notes_inc.gif" alt="Aumentar altura del campo" width="16" height="16" />';
			calIcon += '</a>&nbsp;&nbsp;';
			calIcon += '<a href="#arriba" onclick="changeHeightTextArea(\''+this.a_name+'\',-30);return false;">';
			calIcon += '<img src="../images/dedolib/icon_notes_dec.gif" alt="Disminuir altura del campo" width="16" height="16" />';
			calIcon += '</a>&nbsp;&nbsp;';
			calIcon += '</div>';
			new Insertion.After(this.label, calIcon);
		}
   },
   
   setLabel: function(nameMember) {
		this.label = $('L__' + nameMember);
   },
   
   setSpanError: function(nameMember) {
		this.spanError = $('err_' + nameMember);
   },
   getSpanError: function(nameMember) {
   		var idSpanError = 'err_' + nameMember;
		if((this.a_tipo == 'password')) idSpanError = 'err_' + this.elToInsert.id;
		
		if(!$(idSpanError)){
			var spanError = '<span id="' + idSpanError + '" class="errorField" style="display:none;"><\/span>';
			
			if(oFormCallbacks.config.errorPosition == 'after'){
				var anchoLabel = 0;
				if(this.label && this.a_tipo != 'foto' && this.a_tipo != 'check'){
					anchoLabel = Element.getDimensions(this.label).width;
				}
				spanError = '<div id="' + idSpanError + '" class="errorField" style="clear:left;display:none;padding-left:'+ anchoLabel + 'px;"><\/div>';
				new Insertion.After(this.elToInsert, spanError);
			}
			
			if(oFormCallbacks.config.errorPosition == 'before'){
				new Insertion.Before(this.elToInsert, spanError);
			}
			if(oFormCallbacks.config.errorPosition == 'top'){
				new Insertion.Top(this.elToInsert, spanError);
			}
			if(oFormCallbacks.config.errorPosition == 'bottom'){
				new Insertion.Bottom(this.label, spanError);
			}
		}
		
		this.spanError = $(idSpanError);
   },
   
   setElToInsert: function(member) {
		this.elToInsert = this.element;
		
		if(this.a_tipo == 'date'){
			this.elToInsert = $('cal_icon_' + member);
		}
		if(this.a_tipo == 'dateLimited'){
			this.elToInsert = $('cal_icon_' + member);
		}
		if(this.a_tipo == 'daterange'){
			this.elToInsert = $('H_' + member + '_1');
		}
		if(this.a_format == 'radio' || this.a_format == 'checks'){
			this.elToInsert = $('ul_' + member);
		}
		if(this.a_format == 'template'){
			this.elToInsert = $('template_' + member);
		}
		if(this.a_format == 'select' && (this.a_tipo == 'multienum' || this.a_tipo == 'multiforkey')){
			this.elToInsert = $('ins_' + member);
			this.setLabel(member.substr(0,member.length-2));
		}
		if(this.a_tipo == 'foto' || this.a_tipo == 'file' || this.a_tipo == 'video'){
			this.elToInsert = $('ins_' + member);
		}
		if(this.a_format == 'autocomplete'){
			this.elToInsert = $('auto_' + member);
		}
		if(this.a_tipo == 'check'){
			this.elToInsert = $('L__' + member);
		}
		if(this.a_tipo == 'text' && this.a_format == 'FCK'){
			if($(member + '___Frame')){
				this.elToInsert = $(member + '___Frame');
			}
		}
		
		if((this.a_tipo == 'password')){
		
			var isRepassw = (this.a_name.substr(0,3) == 're_');
			if(isRepassw){
				this.elToInsert = this.element;
				this.label = $('L__' + this.a_name.substr(3,100));
			}else{
				var haveRepassw = $('re_'+this.a_name);
				if(haveRepassw){
					this.elToInsert = $('re_' + this.a_name);
				}else{
					this.elToInsert = this.element;
				}
			}
			// var spanError = $('err_' + elToInsert.id);
		}
   },
   
   onSubmitMember: function() {
		var valSerialize = '';
		var member = this.a_name;
		if(this.a_accesibleVal && $(member).value == this.a_accesibleVal){
			$(member).value = '';
		}
		if((this.a_tipo=='multienum' || this.a_tipo=='multiforkey') && this.a_format == 'select'){
			multiselSelect(member);
		}		
		if((this.a_tipo == 'foto' || this.a_tipo == 'file' || this.a_tipo == 'video')){
			valSerialize = '&valSer_' + member + '=' + (this.element.value);
		}
		
		if((this.a_tipo=='text') && this.a_format == 'RTE'){
			// puede que este asi definido pero el navegador no soporte el RTE
			if($('hdn' + member)){
				updateRTE(member);
				var textoRte = $('hdn' + member).value;
				valSerialize += '&valSer_' + member + '=' + (textoRte);
			}
		}
		
		if((this.a_tipo=='text') && this.a_format == 'FCK'){
			// puede que este asi definido pero el navegador no soporte el RTE
			if(!(isSafari)){ 
					if(FCKeditorAPI.GetInstance(member).GetXHTML() != ''){
						this.element.value = 'OK';
						var textoRte = $(member).value;
					}
				}else{
					var textoRte = document.f.elements[member].value;
				}
			
			valSerialize += '&valSer_' + member + '=' + (textoRte);
			
		}
		
		return valSerialize;
   },
   
   validateInServer: function() {
   		if(this.a_enabled == false) return;
   		var member = this.a_name;
		var valSerialize = this.onSubmitMember();
		
		var valsForm = Form.serialize(document.f);
		
		var dataMember = {};
		['a_tipo','a_format','a_required','a_title','a_accesibleVal','a_validateFunc'].each( function(k) {
			dataMember[k] = this[k];
		}.bind(this));
			
		
		var params = $H(dataMember);
		var paramsMember = params.toQueryString();
		
		//parameters: params.toQueryString(), 
		
		var opt = {
				method: 'post',
				asynchronous:true,
				parameters: 'accionJS=validaMember&member='+member + '&' + paramsMember + valSerialize + '&' + valsForm,
				onSuccess: function(t) {
					this.showResponse(t.responseText);
				}.bind(this)
			};
		new Ajax.Request('../utilidades/validator.php', opt);	
   },
   
    showResponse: function(responseText) {
    		
		this.hasError = false;
		if(responseText == 'OKY'){
			if(this.spanError){
				new Effect.BlindUp(this.spanError,
				{ duration: 0.2, afterFinish: function(element){ Element.remove($(this.spanError.id));this.spanError = null;}.bind(this) });
			}
		}else{
			responseText = responseText.gsub("##alert##","");
			this.hasError = true;
			if(oFormCallbacks.config.showErrorsText){
				
				
				if(oFormCallbacks.config.errorPosition == 'alert'){
					alert(responseText.stripTags());
				}else{
					
					this.getSpanError(this.a_name);
					
					var newSpan = document.createElement('span');
					newSpan.innerHTML = responseText;
					
					this.spanError.update('');
					this.spanError.appendChild(newSpan);
					
					new Effect.Appear(this.spanError);
					
				}		
			}
			
		}
		
		// falta asignar el label
		this.assignLabel();
   },
   
   assignLabel: function() {
   		var tipoLabel = (this.hasError == false) ? 'complete' : 'problem';
   		if(!this.label) return;
   		var elImg = this.label.down('img');
   		
   		if(!elImg) return;
		elImg.alt = MENSAJES[tipoLabel];
		elImg.src = '../images/dedolib/'+tipoLabel+'.gif';
   }
};

/****************************************************
 * FormCallbacks
 ****************************************************/

/**
 * FormCallbacks
 * 
 * @param string nombre del formulario
 */
var FormCallbacks = Class.create();

// definimos la clase
FormCallbacks.prototype = {

   initialize: function(formName) {
		this.formName = formName;
		this.configMembers = {};
		this.config = {};
   },

   setConfig: function(pShowErrorsText,pErrorPosition) {
		this.config.showErrorsText = false;
		if(pShowErrorsText == '1') this.config.showErrorsText = true;
		this.config.errorPosition = pErrorPosition;
   },
   
   addValidateCallback: function(formElementName, pTipo, pFormat, pRequired, pTitle, pEnabled, pValidateFunc) {
		this.configMembers[formElementName] = new MemberDedoLib(formElementName, pTipo, pFormat, pRequired, pTitle, pEnabled, pValidateFunc);
   },
   
   enable: function(formElementName) {
		this.configMembers[formElementName].a_enabled = true;
   },
   
   disable: function(formElementName) {
		this.configMembers[formElementName].a_enabled = false;
   },
   
   observeForm: function() {
		var els = Form.getElements(document[this.formName]);
		
		for(var i = 0; i < els.length; i++)
		{
			
			if(els[i].type == 'hidden') continue;
			
			if(els[i].type == 'radio' || els[i].type == 'checkbox'){
				//Event.observe(els[i], "click", changed, false);
				els[i].onclick = function(){changed(this);};
			}else{
				if(els[i].type == 'select-multiple'){
					// en los multiples el changed se aplicara al mover de uno a otro en el script moveSelectBox.js
					continue;
				}
				if(els[i].id.substr(0, 9) == 'fontsize_'){
					continue;
				}
				//Event.observe(els[i], "change", changed, false);
				
				els[i].onchange = function(){changed(this);};
			}
		}
   },
   validateInServerForm: function(regMatch) {
		var valSerialize = '';
		
		var isTab = false;
		if(regMatch){
			var re = new RegExp(regMatch,"gm");
			isTab = true;
		}
		var serStr = '';
		var result = {};
		
		for(var i in this.configMembers){
			if(isTab){
				if (!(i.match(re))) continue;
			}
			
			member = this.configMembers[i];
			if(!member.a_enabled) continue;
			
			valSerialize += member.onSubmitMember();
			
			var dataMember = {};
			['a_tipo','a_format','a_required','a_title','a_accesibleVal','a_validateFunc'].each( function(k) {
				dataMember[k] = this.configMembers[i][k];
			}.bind(this));
			
			result[i] = dataMember;
		}
		
		var valsForm = Form.serialize(document.f,true);
		var vals = Object.toJSON(result); //JSON.stringify(result);
		var params = Form.serialize(document.f,true);
		params.accionJS = 'validaForm';
		params.config = vals;
		params = $H(params).toQueryString();
		params += valSerialize;
		var opt = {
					method: 'post',
					asynchronous:true,
					parameters: params, 
					onSuccess: function(t) {
						this.showResponseForm(t.responseText);
					}.bind(this)
				};
		new Ajax.Request('../utilidades/validator.php', opt);	
   },
   
   showResponseForm: function (res){
		var hasError = false;
		var focusFirst = '';
		//var myObject = JSON.parse(res);		
		var myObject = res.evalJSON();
		for (var i in myObject) {
			var res = myObject[i];
					   

			if(this.configMembers[i]){
				if(this.configMembers[i].a_format == 'radio'){
					if(document.f.elements[i].type == 'hidden'){ continue;}
					var el = document.f.elements[i][0];
				}else{
					var el = document.f.elements[i];
				}
				
			}else{
				continue;
				alert(i + ' no esta en la config');
			}
			this.configMembers[i].showResponse(res);
			if(res != 'OKY' && res.substr(0,9) != "##alert##"){
				if(focusFirst == '') focusFirst = el;
				hasError = true;
			}
		}

		if(hasError){

			Dialog.closeInfo();
			var msg = MENSAJES['error_form'];
			Dialog.alert(msg, 
				 {windowParameters: {className:"alphacube",width:300, height:100}, okLabel: "OK", 
				  ok:function(win) { return true;}});
		}else{
			if(typeof(updateRTEs) == 'function') updateRTEs();
			s.form.submit();
		}
	},

   submit: function() {
		var oForm = document[this.formName];
		for(i in this.cbOnSubmit) {
			if (this.enabled[i])
				var msg = this.cbOnSubmit[i](i, oForm);
		}
   }
};	
// creamos el objeto
var oFormCallbacks = new FormCallbacks('f');

var isSafari = (/Konqueror|Safari|KHTML/.test(navigator.userAgent));

var myrulesINIT = {
		'#contPageListJS' : function(element){
			var selPerPage = '<select id="regsPerPage" name="regsPerPage">';
			selPerPage += '<option value="5">5 p.p.<\/option>';
			selPerPage += '<option value="10">10 p.p.<\/option>';
			selPerPage += '<option value="20" selected="selected">20 p.p.<\/option>';
			selPerPage += '<option value="40">40 p.p.<\/option>';
			selPerPage += '<option value="300000">'+MENSAJES['todos']+'<\/option>';
			selPerPage += '<\/select>';
			
			new Insertion.After(element, selPerPage);
			
			$('regsPerPage').value = $F('perPage');
			
			$('regsPerPage').onmouseover = function(){showToolTip(MENSAJES['registros_por_pagina']);}
			$('regsPerPage').onmouseout = function(){hideToolTip();}
			$('regsPerPage').onchange = function(){$('perPage').value=this.value;document.f.submit();}
		}
	};
	
Behaviour.register(myrulesINIT);

function goPaginatorPage(regNum)
{
	if(document.f){
		document.f['regIni'].value = regNum;
		document.f.submit();
		return false;
	}
}
/****************************************************
 * MISC
 ****************************************************/


/**
 * Gets the value of the specified parameter in the cookie.
 *
 * @param string name of the desired parameter.
 * @return string value of that parameter or null if cookie does not exist.
 */
function getCookie(name)
{
    var dc = document.cookie;
    var prefix = name + "=";
    var begin = dc.indexOf("; " + prefix);
    if (begin == -1)
    {
        begin = dc.indexOf(prefix);
        if (begin != 0) return null;
    }
    else
    {
        begin += 2;
    }
    var end = document.cookie.indexOf(";", begin);
    if (end == -1)
    {
        end = dc.length;
    }
    return unescape(dc.substring(begin + prefix.length, end));
}


function newWindow(mypage, myname, w, h, scroll) {
     var winLeft = (screen.width - w) / 2;
     var winTop = (screen.height - h) / 2;
     winProps = "height=" + h + ",width=" + w + ",top=" + winTop + ",left=" + winLeft + "," + scroll;
     win = window.open(mypage, myname, winProps);
     if (parseInt(navigator.appVersion) >= 4) { win.window.focus(); }
     return win;
}

var posicX =0;
var posicY =0;

Event.observe(document, 'mousemove', get_mouse_xy);

function get_mouse_xy(e) {
	posicX = Event.pointerX(e) + 10;
	posicY = Event.pointerY(e) + 12;
	return true;
}

function showToolTip(text){
	idToolTip = "toolTip";
	w = Math.min((text.length * 5),250);
	//w = 300;
	if(!document.getElementById(idToolTip)){
		divholder = document.createElement("div");
		divholder.id = idToolTip;
		divholder.style.display = 'none';
		divholder.style.width = w + 'px';
		divholder.style.height = "auto";
		divholder.style.border = "1px solid #CCCCCC";
		divholder.style.backgroundColor = "#FCFCBD";
		divholder.style.position = "absolute";
		divholder.style.color = "#222222";
		divholder.style.padding = "2px";
		divholder.style.fontSize = "10px";
		divholder.style.zIndex = "200";
		document.body.appendChild(divholder);
	}else{
		divholder = document.getElementById(idToolTip);
		divholder.style.width = w + 'px';
	}
	x = posicX;
	y = posicY;
	if(document.body.offsetWidth < posicX+w+20){
		x = document.body.offsetWidth - (w+20);
	}

	divholder.style.left = x+"px";
	divholder.style.top = y+"px";
	document.getElementById(idToolTip).innerHTML = ""+text+"";
	document.getElementById(idToolTip).style.visibility = "visible";
	document.getElementById(idToolTip).style.display = "";
}


function hideToolTip(){
	document.getElementById("toolTip").style.visibility = "hidden";
}

function showDivDateChoose(form,campo){
	idDiv = "DateChoose";
	w = 300;
	if(!document.getElementById(idDiv)){
		divholder = document.createElement("div");
		divholder.id = idDiv;
		divholder.style.width = "auto";
		divholder.style.height = "auto";
		divholder.style.position = "absolute";
		divholder.style.zIndex = "200";
		document.body.appendChild(divholder);
	}else{
		divholder = document.getElementById(idDiv);
	}

	arr = Position.cumulativeOffset(document.f.elements[campo]);
	x = arr[0] + 110;
	y = arr[1] - 40;
	divholder.style.left = x+"px";
	divholder.style.top = y+"px";

	var texts = getTextsDateChooser();
 	content = 	"<div id='dateChooseContent'>";
 	content += 	"<ul>";
	content += 	"<li class='sigue hand'><a href='javascript:showCalendar(\""+form+"\",\""+campo+"\");javascript:hideDivDateChoose();'>"+texts[0]+"</a></li>";
	content += 	"<li class='sigue hand'><a href='javascript:hideDivDateChoose();'>"+texts[1]+"</a></li>";
	content += 	"</ul>";

	content += 	"<ul>";
	content += 	"<li class='sign'><a href='javascript:addDayToDate(-1,\""+form+"\",\""+campo+"\");'><b>-</b></a></li>";
	content += 	"<li><a href='javascript:calculateDate(0,\""+form+"\",\""+campo+"\");javascript:hideDivDateChoose();'>"+texts[2]+"</a></li>";
	content += 	"<li class='sign'><a href='javascript:addDayToDate(1,\""+form+"\",\""+campo+"\");'><b>+</b></a></li>";
	content += 	"</ul>";

	content += 	"<ul>";
	content += 	"<li class='sign'><a href='javascript:addDayToDate(-7,\""+form+"\",\""+campo+"\");'><b>-</b></a></li>";
	content += 	"<li class='semana'>"+texts[3]+"</li>";
	content += 	"<li class='sign'><a href='javascript:addDayToDate(7,\""+form+"\",\""+campo+"\");'><b>+</b></a></li>";
	content += 	"</ul>";
	content += 	"<div style='clear:both;'></div>";
	content += 	"</div>";
	content += 	"";
	document.getElementById(idDiv).innerHTML = ""+content+"";
	if(Effect){
		Effect.Appear(idDiv);
	}else{
		document.getElementById(idDiv).style.visibility = "visible";
	}
}

function getTextsDateChooser(){
	var lang = getCookie('lang');
	if (lang == '' || lang == undefined){
		lang = 'es';
	}
	if (lang == 'es'){
		texts = new Array('Elegir','Cerrar','Hoy','Semana');
	}else if (lang == 'eu'){
		texts = new Array('Aukeratu','Itxi','Gaur','Astea');
	}else if (lang == 'en'){
		texts = new Array('Choose','Close','Today','Week');
	}else {
		texts = new Array('Choose','Close','Today','Week');
	}
	return texts;
}


function hideDivDateChoose(){
	if(!$('DateChoose')) return;
	if(Effect){
		Effect.DropOut("DateChoose");
	}else{
		document.getElementById("DateChoose").style.visibility = "hidden";
	}
}

function calculateDate(dif,form,campo){
	MINUTE = 60 * 1000;
 	HOUR = MINUTE * 60;
 	DAY = HOUR * 24;


	today = (new Date()).getTime();
 	newFecha = new Date(today + (DAY * (dif)));
 	newFechaFormat = newFecha.getDate() + '-' + (newFecha.getMonth()+1) + '-' + (newFecha.getFullYear());

	setDate(form,campo,newFechaFormat);
}

function addDayToDate(dif,form,campo){
	MINUTE = 60 * 1000;
 	HOUR = MINUTE * 60;
 	DAY = HOUR * 24;

	elInputVal = eval("document." + form + "['" + campo + "'].value");
	if (elInputVal == ''){
		today = (new Date()).getTime();
	}else{
		fecha = elInputVal.split("-");
		d = fecha[0];
		m = fecha[1]-1;
		y = fecha[2];
		today = (new Date(y,m,d)).getTime();
	}
 	newFecha = new Date(today + (DAY * (dif)));
 	newFechaFormat = newFecha.getDate() + '-' + (newFecha.getMonth()+1) + '-' + (newFecha.getFullYear());

	setDate(form,campo,newFechaFormat);
}

function changeHeightTextArea(elName,inc)
{
	if(document.getElementById(elName +'___Frame')){
		var oEditor = FCKeditorAPI.GetInstance(elName).EditorWindow.parent;
		
		var actualHeight = oEditor.innerHeight;		
		
		document.getElementById(elName + '___Frame').style.height = actualHeight + inc +'px';
		return;
		
	}else{
		var tArea = document.getElementById(elName);
		var actualHeight = parseInt(tArea.getHeight());
	
		if(actualHeight <= 60 && inc < 0) return;
		if((actualHeight + inc) < 60) inc = 60 - actualHeight;
		if(Effect){
			// cual es el porcentaje de los pixeles a mover?
			var porcentaje = 100 + ((inc * 100) / (Math.max(50,actualHeight)));
			
			var test = new Effect.Scale(tArea, porcentaje, Object.extend({ scaleContent: false, scaleX: false, scaleMode: 'contents'}, {duration:0.2}));
		}else{
			tArea.style.height = actualHeight + inc +'px';
		}
	}
	
	
}

function setActiveStyleSheet(title) {
  var i, a, main;
  for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
    if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title")) {
      a.disabled = true;
      if(a.getAttribute("title") == title) a.disabled = false;
    }
  }
}

var detect = navigator.userAgent.toLowerCase();

function checkItDedolib(string)
{
	place = detect.indexOf(string) + 1;
	return place;
}

function clickDiaCalMini(idTd){
	s.ejecuta('agenda');
}
function clickDiaCalSearch(idTd){
	document.f.fechaCal.value = idTd;
	s.ejecuta('buscarPublic');
}


var idEnRoll = -1;
var classEnRoll = '';

function rollOverDiaCalMini(idTd){
	return;
}


var isExplorer=checkItDedolib('msie');
function validaMouseOut(elem){
		if(isExplorer){
			if (!e) var e = window.event;
			if (e.target) tg = e.target;
			else if (e.srcElement) tg = e.srcElement;
			var reltg = (e.relatedTarget) ? e.relatedTarget : e.toElement;
			if(!reltg) return false;
			while (reltg.className != elem.className && reltg.nodeName != 'BODY'){
					if(reltg.parentNode==null) return false;
					reltg= reltg.parentNode;
			}
			if (reltg.className == elem.className) return false;
		}
		return true;
}

///////////////////////////////////////////////////////////////////////////
// MOVESELECTBOX
///////////////////////////////////////////////////////////////////////////
function moveFromTo(fbox,tbox){
	for(var i=0; i<fbox.options.length; i++) {
		if(fbox.options[i].selected && fbox.options[i].value != "") {
			var no = new Option();
			no.value = fbox.options[i].value;
			no.text = fbox.options[i].text;
			tbox.options[tbox.options.length] = no;
			fbox.options[i] = null;
      		i--;
   		}
	}
	SortD(tbox);
	if(fbox.name.substr(fbox.name.length-5,100) == 'Out[]'){
		changed(tbox);
	}else{
		changed(fbox);
	}
}


function SortD(box)  {
	var temp_opts = new Array();
	var temp = new Object();
	for(var i=0; i<box.options.length; i++)  {
		temp_opts[i] = box.options[i];
	}
	
	temp_opts.sort(function (a,b) {
				if((a.text.toUpperCase()) < (b.text.toUpperCase())){
					return -1;
				}
				if((a.text.toUpperCase()) > (b.text.toUpperCase())){
					return 1;
				}
				return 0;
		});
	
	box.options.length = 0;
	for(var i=0; i<temp_opts.length; i++)  {
		box.options[i] = temp_opts[i];
	}
}

///////////////////////////////////////////////////////////////////////////
// END MOVESELECTBOX
///////////////////////////////////////////////////////////////////////////


function showDialog(texto)
{
	Dialog.alert(texto,{windowParameters: {className:'alphacube',showEffectOptions:{duration:0.2},width:300, height:100}, okLabel: 'OK',ok:function(win) { return true;}});
}


/* PROTOTYPE EXTENDS */

Object.extend(Ajax.Autocompleter.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.options.onNoresults = this.options.onNoresults || function(element, update){ return; };
  },

  onObserverEvent: function() {
    this.changed = false;

    if(this.getToken().length>=this.options.minChars) {
      this.startIndicator();
      this.getUpdatedChoices();
    } else {
      //this.options.onNoResults(this.element,this.update);
      this.active = false;
      this.hide();
    }
  },

  updateChoices: function(choices) {
    if(!choices || choices == '' || choices.indexOf('no_results') != -1) this.options.onNoresults(this.element,this.update);
  	if(!this.changed && this.hasFocus) {
      this.update.innerHTML = choices;
      Element.cleanWhitespace(this.update);
      Element.cleanWhitespace(this.update.firstChild);

      if(this.update.firstChild && this.update.firstChild.childNodes) {
        this.entryCount =
          this.update.firstChild.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.index = 0;
      this.render();
    }
  },
  onBlur: function(event) {
    // needed to make click events working
    setTimeout(this.hide.bind(this), 250);
    this.hasFocus = false;
    this.active = false;
    if(this.element.value == ''){
    	this.options.onNoresults(this.element,this.update);
    }
  },
  onComplete: function(request) {
    //alert(request.responseText);
    this.updateChoices(request.responseText);
  }
});



document.getElementsByAttribute = function(attribute, value, tagName, parentElement) {
	var children = ($(parentElement) || document.body).getElementsByTagName((tagName || '*'));
	return $A(children).inject([], function(elements, child) {
		var attributeValue = child.getAttribute(attribute);
		if(attributeValue != null) {
			if(!value || attributeValue == value) {
				elements.push(child);
			}
		}
		return elements;
	});
}

function procesaAccesibleValuesForm()
{
	var els = $$('.accesibleVal');
	els.each(function(value, index) {
      var element = els[index];
      
      element.startValue = element.value;
      Element.addClassName(element,'accesibleValFocus');
		element.onfocus = function(){
			if (element.value == element.startValue){
				element.value = "";
				//element.style.color='#000000';
				Element.removeClassName(element,'accesibleValFocus');
			}
		};
		element.onblur = function(){
			if (element.value == ''){
				element.value = element.startValue;
				//element.style.color='#747373';
				Element.addClassName(element,'accesibleValFocus');
			}
		};
    });
}

function initMap(lat, lon, dirOverlay, mapId,showScala,showTipoMapa)
{
	if (GBrowserIsCompatible()) {
		var map = new GMap2(document.getElementById(mapId));
	
		map.setCenter(new GLatLng(lat, lon), 14);
		if(showScala){
			map.addControl(new GLargeMapControl());
		}else{
			map.addControl(new GSmallMapControl());
		}
		if(showTipoMapa){
			map.addControl(new GMapTypeControl());
		}
		
		var point = new GLatLng(lat, lon);
	
		var marker = new GMarker(point);
		GEvent.addListener(marker, "click", function() {
			marker.openInfoWindowHtml(dirOverlay);
		});
		map.addOverlay(marker);
		marker.openInfoWindowHtml(dirOverlay);
	}
}


var ZebraTable = {
	bgcolor: '',
	classname: '',
	stripe: function(el) {
		if (!$(el)) return;
		
		var rows = $(el).getElementsByTagName('tr');
		for (var i=1,len=rows.length;i<len;i++) {
			rows[i].className = 'impar';
			if (i % 2 == 0) rows[i].className = 'par';
			Event.observe(rows[i], 'mouseover', function() { ZebraTable.mouseover(this); });
			Event.observe(rows[i], 'mouseout', function() { ZebraTable.mouseout(this); });
		}
	},
	mouseover: function(row) {
		this.bgcolor = row.style.backgroundColor;
		this.classname = row.className;
		row.addClassName('ruled');
	},
	mouseout: function(row) {
		row.removeClassName('ruled');
		row.addClassName(row,this.classname);
		row.style.backgroundColor = this.bgcolor;
	}
}

Event.observe(window, 'load', function() { procesaAccesibleValuesForm();});


// Copyright (c) 2006 SÃƒÂ©bastien Gruhier (http://xilinus.com, http://itseb.com)
// 
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// VERSION 1.0

Position.windowInfo = function() {
  var windowWidth, windowHeight;
  var pageWidth, pageHeight;
  
  if (window.innerHeight && window.scrollMaxY) {  
    pageWidth = document.body.scrollWidth;
    pageHeight = window.innerHeight + window.scrollMaxY;
  } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
    pageWidth = document.body.scrollWidth;
    pageHeight = document.body.scrollHeight;
  } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
    pageWidth = document.body.offsetWidth;
    pageHeight = document.body.offsetHeight;
  }
  
  if (self.innerHeight) { // all except Explorer
    windowWidth = self.innerWidth;
    windowHeight = self.innerHeight;
  } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
    windowWidth = document.documentElement.clientWidth;
    windowHeight = document.documentElement.clientHeight;
  } else if (document.body) { // other Explorers
    windowWidth = document.body.clientWidth;
    windowHeight = document.body.clientHeight;
  } 
  var xScroll = document.documentElement.scrollLeft || document.body.scrollLeft;
  var yScroll = document.documentElement.scrollTop || document.body.scrollTop;

  // for small pages with total height less then height of the viewport
  pageHeight = Math.max(windowHeight, pageHeight);

  // for small pages with total width less then width of the viewport
  pageWidth = Math.max(windowWidth, pageWidth);
  return { width: windowWidth, height: windowHeight, pageWidth: pageWidth, pageHeight: pageHeight, xScroll: xScroll, yScroll: yScroll};
}

var TransparentMenu = Class.create();

TransparentMenu.DefaultOptions = {
  top: null,
  left: null,
  showEffect: Effect.Appear,
  showEffectOptions: {duration: 0.2}, 
  hideEffect: Effect.Fade,
  hideEffectOptions: {duration: 0.2},
  showMode: "onload",
  hideMode: "timeout",
  hideDelay: 2,
  insideElement: {id: null, width: "auto", height: "auto"},
  afterElement: null,
  fullscreen: false
}
TransparentMenu.instances = $H();

TransparentMenu.hide = function(id) {
  if (TransparentMenu.instances[id])
    TransparentMenu.instances[id].hide();
}

TransparentMenu.show = function(id) {
  if (TransparentMenu.instances[id]) 
    TransparentMenu.instances[id].show();
  else 
    new TransparentMenu(id,  arguments[1]);
}

TransparentMenu.prototype = {
	initialize: function(id) {
	  this.options  = Object.extend(Object.extend({},TransparentMenu.DefaultOptions), arguments[1] || {});   
	  this.options.insideElement =  Object.extend(Object.extend({},TransparentMenu.DefaultOptions.insideElement), this.options.insideElement || {});   
		this.id = id;

		if (this.options.displayMode == "onload")
	    Event.observe(window, "load", this._init.bindAsEventListener(this));
	  else
	    this._init(null);
	  TransparentMenu.instances[id] = this;
  },
  
  show: function() {
    new this.options.showEffect(this.element, this.options.showEffectOptions);

    // Safari bug fix
    if (navigator.appVersion.match(/Konqueror|Safari|KHTML/))
      setTimeout(this._setPostion.bindAsEventListener(this), 10)

	
    if (this.options.hideMode == "timeout") {
      setTimeout(this.hide.bindAsEventListener(this), this.options.hideDelay*1000);
    }else if (this.options.hideMode == "click" || this.options.hideMode == "mousemove") {
      this.bindEvent = this._startHideEvent.bindAsEventListener(this);
      Event.observe(this.element, this.options.hideMode, this.bindEvent);      
    }    
  },
    
  hide: function() { 
    new this.options.hideEffect(this.element, this.options.hideEffectOptions);
  },
    
  _init: function(event) {
    this.element = $(this.id);
    this._setPostion();
    
    // Get opacity from css if not specify for Fade effect
    if (Element.getOpacity(this.element) && this.options.showEffect == Effect.Appear && ! this.options.showEffectOptions.to)
      this.options.showEffectOptions.to = Element.getOpacity(this.element);
     
    this.show(); 
  },
  
  _setPostion: function() {
    var windowInfo = Position.windowInfo();
    var dim = this.element.getDimensions();

    // Inside an element
    if (this.options.insideElement.id != null) {    
      var relativeElement = $(this.options.insideElement.id);
      var position = Position.cumulativeOffset(relativeElement);
      var dimension = relativeElement.getDimensions();
      this.element.style.left = position[0] + "px";
      this.element.style.top = position[1] + "px";

      if (this.options.insideElement.width == 'auto') {
        this.element.style.width =  dimension.width + "px";
      }
      if (this.options.insideElement.height == 'auto')
        this.element.style.height = dimension.height + "px";
    }
    // Else full screen message
    else if (this.options.fullscreen) { 
      this.element.style.left = "0px";
      this.element.style.top = "0px";
      this.element.style.width = windowInfo.pageWidth + "px";
      this.element.style.height = windowInfo.pageHeight + "px";
    }
    // Relative to body or element
    else {
      var dy = 0;  		
      // Relative to an element
      if (this.options.afterElement != null) {
        var position = Position.cumulativeOffset($(this.options.afterElement));
        dy =  position[1];
      }
      // Else to body, add yScroll to have it visible from anywhere
      else
        dy = windowInfo.yScroll;
        
      // Compute left position using user options
      if (this.options.left != null)
        this.element.style.left = windowInfo.xScroll + this.options.left + "px";
      else
        this.element.style.left = windowInfo.xScroll + ((windowInfo.width - dim.width) / 2 ) + "px";
      
      // Compute top position useing user options
      if (this.options.top != null)
        this.element.style.top = dy + this.options.top + "px";
      else
        this.element.style.top = dy + ((windowInfo.height - dim.height) / 2 ) + "px";
    }
  },
  
  _startHideEvent: function() {
    var dim = this.element.getDimensions();
    Event.stopObserving(window, this.options.hideMode, this.bindEvent);      
    setTimeout(this.hide.bindAsEventListener(this), 0);
  }
}


// Copyright (c) 2006 SÃ©bastien Gruhier (http://xilinus.com, http://itseb.com)
// 
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// VERSION 1.3

var Window = Class.create();

Window.keepMultiModalWindow = false;
Window.hasEffectLib = (typeof Effect != 'undefined');
Window.resizeEffectDuration = 0.4;

Window.prototype = {
  // Constructor
  // Available parameters : className, blurClassName, title, minWidth, minHeight, maxWidth, maxHeight, width, height, top, left, bottom, right, resizable, zIndex, opacity, recenterAuto, wiredDrag
  //                        hideEffect, showEffect, showEffectOptions, hideEffectOptions, effectOptions, url, draggable, closable, minimizable, maximizable, parent, onload
  //                        add all callbacks (if you do not use an observer)
  //                        onDestroy onStartResize onStartMove onResize onMove onEndResize onEndMove onFocus onBlur onBeforeShow onShow onHide onMinimize onMaximize onClose
  
  initialize: function() {
  
    var id;
    var optionIndex = 0;
    // For backward compatibility like win= new Window("id", {...}) instead of win = new Window({id: "id", ...})
    if (arguments.length > 0) {
      if (typeof arguments[0] == "string" ) {
        id = arguments[0];
        optionIndex = 1;
      }
      else
        id = arguments[0] ? arguments[0].id : null;
    }
    
    // Generate unique ID if not specified
    if (!id)
      id = "window_" + new Date().getTime();
      
    if ($(id))
      alert("Window " + id + " is already registered in the DOM! Make sure you use setDestroyOnClose() or destroyOnClose: true in the constructor");


    this.options = Object.extend({
      className:         "dialog",
      blurClassName:     null,
      minWidth:          100, 
      minHeight:         20,
      resizable:         true,
      closable:          true,
      minimizable:       true,
      maximizable:       true,
      draggable:         true,
      userData:          null,
      showEffect:        (Window.hasEffectLib ? Effect.Appear : Element.show),
      hideEffect:        (Window.hasEffectLib ? Effect.Fade : Element.hide),
      showEffectOptions: {},
      hideEffectOptions: {},
      effectOptions:     null,
      parent:            document.body,
      title:             "&nbsp;",
      url:               null,
      onload:            Prototype.emptyFunction,
      width:             200,
      height:            300,
      opacity:           1,
      recenterAuto:      true,
      wiredDrag:         false,
      closeCallback:     null,
      destroyOnClose:    false,
      gridX:             1, 
      gridY:             1      
    }, arguments[optionIndex] || {});
    if (this.options.blurClassName)
      this.options.focusClassName = this.options.className;
      
    if (typeof this.options.top == "undefined" &&  typeof this.options.bottom ==  "undefined") 
      this.options.top = this._round(Math.random()*500, this.options.gridY);
    if (typeof this.options.left == "undefined" &&  typeof this.options.right ==  "undefined") 
      this.options.left = this._round(Math.random()*500, this.options.gridX);

    if (this.options.effectOptions) {
      Object.extend(this.options.hideEffectOptions, this.options.effectOptions);
      Object.extend(this.options.showEffectOptions, this.options.effectOptions);
      if (this.options.showEffect == Element.Appear)
        this.options.showEffectOptions.to = this.options.opacity;
    }
    if (Window.hasEffectLib) {
      if (this.options.showEffect == Effect.Appear)
        this.options.showEffectOptions.to = this.options.opacity;
    
      if (this.options.hideEffect == Effect.Fade)
        this.options.hideEffectOptions.from = this.options.opacity;
    }
    if (this.options.hideEffect == Element.hide)
      this.options.hideEffect = function(){ Element.hide(this.element); if (this.options.destroyOnClose) this.destroy(); }.bind(this)
    
    if (this.options.parent != document.body)  
      this.options.parent = $(this.options.parent);
      
    this.element = this._createWindow(id);       
    this.element.win = this;
    
    // Bind event listener
    this.eventMouseDown = this._initDrag.bindAsEventListener(this);
    this.eventMouseUp   = this._endDrag.bindAsEventListener(this);
    this.eventMouseMove = this._updateDrag.bindAsEventListener(this);
    this.eventOnLoad    = this._getWindowBorderSize.bindAsEventListener(this);
    this.eventMouseDownContent = this.toFront.bindAsEventListener(this);
    this.eventResize = this._recenter.bindAsEventListener(this);
 
    this.topbar = $(this.element.id + "_top");
    this.bottombar = $(this.element.id + "_bottom");
    this.content = $(this.element.id + "_content");
    
    Event.observe(this.topbar, "mousedown", this.eventMouseDown);
    Event.observe(this.bottombar, "mousedown", this.eventMouseDown);
    Event.observe(this.content, "mousedown", this.eventMouseDownContent);
    Event.observe(window, "load", this.eventOnLoad);
    Event.observe(window, "resize", this.eventResize);
    Event.observe(window, "scroll", this.eventResize);
    Event.observe(this.options.parent, "scroll", this.eventResize);
    
    if (this.options.draggable)  {
      var that = this;
      [this.topbar, this.topbar.up().previous(), this.topbar.up().next()].each(function(element) {
        element.observe("mousedown", that.eventMouseDown);
        element.addClassName("top_draggable");
      });
      [this.bottombar.up(), this.bottombar.up().previous(), this.bottombar.up().next()].each(function(element) {
        element.observe("mousedown", that.eventMouseDown);
        element.addClassName("bottom_draggable");
      });
      
    }    
    
    if (this.options.resizable) {
      this.sizer = $(this.element.id + "_sizer");
      Event.observe(this.sizer, "mousedown", this.eventMouseDown);
    }  
    
    this.useLeft = null;
    this.useTop = null;
    if (typeof this.options.left != "undefined") {
      this.element.setStyle({left: parseFloat(this.options.left) + 'px'});
      this.useLeft = true;
    }
    else {
      this.element.setStyle({right: parseFloat(this.options.right) + 'px'});
      this.useLeft = false;
    }
    
    if (typeof this.options.top != "undefined") {
      this.element.setStyle({top: parseFloat(this.options.top) + 'px'});
      this.useTop = true;
    }
    else {
      this.element.setStyle({bottom: parseFloat(this.options.bottom) + 'px'});      
      this.useTop = false;
    }
      
    this.storedLocation = null;
    
    this.setOpacity(this.options.opacity);
    if (this.options.zIndex)
      this.setZIndex(this.options.zIndex)

    if (this.options.destroyOnClose)
      this.setDestroyOnClose(true);

    this._getWindowBorderSize();
    this.width = this.options.width;
    this.height = this.options.height;
    this.visible = false;
    
    this.constraint = false;
    this.constraintPad = {top: 0, left:0, bottom:0, right:0};
    
    if (this.width && this.height)
      this.setSize(this.options.width, this.options.height);
    this.setTitle(this.options.title)
    Windows.register(this);  
    
  },
  
  // Destructor
  destroy: function() {
    this._notify("onDestroy");
    Event.stopObserving(this.topbar, "mousedown", this.eventMouseDown);
    Event.stopObserving(this.bottombar, "mousedown", this.eventMouseDown);
    Event.stopObserving(this.content, "mousedown", this.eventMouseDownContent);
    
    Event.stopObserving(window, "load", this.eventOnLoad);
    Event.stopObserving(window, "resize", this.eventResize);
    Event.stopObserving(window, "scroll", this.eventResize);
    
    Event.stopObserving(this.content, "load", this.options.onload);

    if (this._oldParent) {
      var content = this.getContent();
      var originalContent = null;
      for(var i = 0; i < content.childNodes.length; i++) {
        originalContent = content.childNodes[i];
        if (originalContent.nodeType == 1) 
          break;
        originalContent = null;
      }
      if (originalContent)
        this._oldParent.appendChild(originalContent);
      this._oldParent = null;
    }

    if (this.sizer)
        Event.stopObserving(this.sizer, "mousedown", this.eventMouseDown);

    if (this.options.url) 
      this.content.src = null

     if(this.iefix) {
      Element.remove(this.iefix);
      this.iefix = null;
	}
    Element.remove(this.element);
    Windows.unregister(this);
  },
    
  // Sets close callback, if it sets, it should return true to be able to close the window.
  setCloseCallback: function(callback) {
    this.options.closeCallback = callback;
  },
  
  // Gets window content
  getContent: function () {
    return this.content;
  },
  
  // Sets the content with an element id
  setContent: function(id, autoresize, autoposition) {
    var element = $(id);
    if (null == element) throw "Unable to find element '" + id + "' in DOM";
    this._oldParent = element.parentNode;

    var d = null;
    var p = null;

    if (autoresize) 
      d = Element.getDimensions(element);
    if (autoposition) 
      p = Position.cumulativeOffset(element);

    var content = this.getContent();
    // Clear HTML (and even iframe)
    this.setHTMLContent("");
    content = this.getContent();
    
    content.appendChild(element);
    element.show();
    if (autoresize) 
      this.setSize(d.width, d.height);
    if (autoposition) 
      this.setLocation(p[1] - this.heightN, p[0] - this.widthW);    
  },
  
  setHTMLContent: function(html) {
    // It was an url (iframe), recreate a div content instead of iframe content
    if (this.options.url) {
      this.content.src = null;
      this.options.url = null;
      
  	  var content ="<div id=\"" + this.getId() + "_content\" class=\"" + this.options.className + "_content\"> </div>";
      $(this.getId() +"_table_content").innerHTML = content;
      
      this.content = $(this.element.id + "_content");
    }
      
    this.getContent().innerHTML = html;
  },
  
  setAjaxContent: function(url, options, showCentered, showModal) {
    this.showFunction = showCentered ? "showCenter" : "show";
    this.showModal = showModal || false;
  
    options = options || {};

    // Clear HTML (and even iframe)
    this.setHTMLContent("");
 
    this.onComplete = options.onComplete;
    if (! this._onCompleteHandler)
      this._onCompleteHandler = this._setAjaxContent.bind(this);
    options.onComplete = this._onCompleteHandler;

    new Ajax.Request(url, options);    
    options.onComplete = this.onComplete;
  },
  
  _setAjaxContent: function(originalRequest) {
    Element.update(this.getContent(), originalRequest.responseText);
    if (this.onComplete)
      this.onComplete(originalRequest);
    this.onComplete = null;
    this[this.showFunction](this.showModal)
  },
  
  setURL: function(url) {
    // Not an url content, change div to iframe
    if (this.options.url) 
      this.content.src = null;
    this.options.url = url;
    var content= "<iframe frameborder='0' name='" + this.getId() + "_content'  id='" + this.getId() + "_content' src='" + url + "' width='" + this.width + "' height='" + this.height + "'> </iframe>";
    $(this.getId() +"_table_content").innerHTML = content;
    
    this.content = $(this.element.id + "_content");
  },

  getURL: function() {
  	return this.options.url ? this.options.url : null;
  },

  refresh: function() {
    if (this.options.url)
	    $(this.element.getAttribute('id') + '_content').src = this.options.url;
  },
  
  // Stores position/size in a cookie, by default named with window id
  setCookie: function(name, expires, path, domain, secure) {
    name = name || this.element.id;
    this.cookie = [name, expires, path, domain, secure];
    
    // Get cookie
    var value = WindowUtilities.getCookie(name)
    // If exists
    if (value) {
      var values = value.split(',');
      var x = values[0].split(':');
      var y = values[1].split(':');

      var w = parseFloat(values[2]), h = parseFloat(values[3]);
      var mini = values[4];
      var maxi = values[5];

      this.setSize(w, h);
      if (mini == "true")
        this.doMinimize = true; // Minimize will be done at onload window event
      else if (maxi == "true")
        this.doMaximize = true; // Maximize will be done at onload window event

      this.useLeft = x[0] == "l";
      this.useTop = y[0] == "t";

      this.element.setStyle(this.useLeft ? {left: x[1]} : {right: x[1]});
      this.element.setStyle(this.useTop ? {top: y[1]} : {bottom: y[1]});
    }
  },
  
  // Gets window ID
  getId: function() {
    return this.element.id;
  },
  
  // Detroys itself when closing 
  setDestroyOnClose: function() {
    this.options.destroyOnClose = true;
  },
  
  setConstraint: function(bool, padding) {
    this.constraint = bool;
    this.constraintPad = Object.extend(this.constraintPad, padding || {});
    // Reset location to apply constraint
    if (this.useTop && this.useLeft)
      this.setLocation(parseFloat(this.element.style.top), parseFloat(this.element.style.left));
  },
  
  // initDrag event

  _initDrag: function(event) {
    // No resize on minimized window
    if (Event.element(event) == this.sizer && this.isMinimized())
      return;

    // No move on maximzed window
    if (Event.element(event) != this.sizer && this.isMaximized())
      return;
      
    if (Prototype.Browser.IE && this.heightN == 0)
      this._getWindowBorderSize();
    
    // Get pointer X,Y
    this.pointer = [this._round(Event.pointerX(event), this.options.gridX), this._round(Event.pointerY(event), this.options.gridY)];
    if (this.options.wiredDrag) 
      this.currentDrag = this._createWiredElement();
    else
      this.currentDrag = this.element;
      
    // Resize
    if (Event.element(event) == this.sizer) {
      this.doResize = true;
      this.widthOrg = this.width;
      this.heightOrg = this.height;
      this.bottomOrg = parseFloat(this.element.getStyle('bottom'));
      this.rightOrg = parseFloat(this.element.getStyle('right'));
      this._notify("onStartResize");
    }
    else {
      this.doResize = false;

      // Check if click on close button, 
      var closeButton = $(this.getId() + '_close');
      if (closeButton && Position.within(closeButton, this.pointer[0], this.pointer[1])) {
        this.currentDrag = null;
        return;
      }

      this.toFront();

      if (! this.options.draggable) 
        return;
      this._notify("onStartMove");
    }    
    // Register global event to capture mouseUp and mouseMove
    Event.observe(document, "mouseup", this.eventMouseUp, false);
    Event.observe(document, "mousemove", this.eventMouseMove, false);
    
    // Add an invisible div to keep catching mouse event over iframes
    WindowUtilities.disableScreen('__invisible__', '__invisible__', this.overlayOpacity);

    // Stop selection while dragging
    document.body.ondrag = function () { return false; };
    document.body.onselectstart = function () { return false; };
    
    this.currentDrag.show();
    Event.stop(event);
  },
  
  _round: function(val, round) {
    return round == 1 ? val  : val = Math.floor(val / round) * round;
  },

  // updateDrag event
  _updateDrag: function(event) {
    var pointer =  [this._round(Event.pointerX(event), this.options.gridX), this._round(Event.pointerY(event), this.options.gridY)];  
    var dx = pointer[0] - this.pointer[0];
    var dy = pointer[1] - this.pointer[1];
    
    // Resize case, update width/height
    if (this.doResize) {
      var w = this.widthOrg + dx;
      var h = this.heightOrg + dy;
      
      dx = this.width - this.widthOrg
      dy = this.height - this.heightOrg
      
      // Check if it's a right position, update it to keep upper-left corner at the same position
      if (this.useLeft) 
        w = this._updateWidthConstraint(w)
      else 
        this.currentDrag.setStyle({right: (this.rightOrg -dx) + 'px'});
      // Check if it's a bottom position, update it to keep upper-left corner at the same position
      if (this.useTop) 
        h = this._updateHeightConstraint(h)
      else
        this.currentDrag.setStyle({bottom: (this.bottomOrg -dy) + 'px'});
        
      this.setSize(w , h);
      this._notify("onResize");
    }
    // Move case, update top/left
    else {
      this.pointer = pointer;
      
      if (this.useLeft) {
        var left =  parseFloat(this.currentDrag.getStyle('left')) + dx;
        var newLeft = this._updateLeftConstraint(left);
        // Keep mouse pointer correct
        this.pointer[0] += newLeft-left;
        this.currentDrag.setStyle({left: newLeft + 'px'});
      }
      else 
        this.currentDrag.setStyle({right: parseFloat(this.currentDrag.getStyle('right')) - dx + 'px'});
      
      if (this.useTop) {
        var top =  parseFloat(this.currentDrag.getStyle('top')) + dy;
        var newTop = this._updateTopConstraint(top);
        // Keep mouse pointer correct
        this.pointer[1] += newTop - top;
        this.currentDrag.setStyle({top: newTop + 'px'});
      }
      else 
        this.currentDrag.setStyle({bottom: parseFloat(this.currentDrag.getStyle('bottom')) - dy + 'px'});

      this._notify("onMove");
    }
    if (this.iefix) 
      this._fixIEOverlapping(); 
      
    this._removeStoreLocation();
    Event.stop(event);
  },

   // endDrag callback
   _endDrag: function(event) {
    // Remove temporary div over iframes
     WindowUtilities.enableScreen('__invisible__');
    
    if (this.doResize)
      this._notify("onEndResize");
    else
      this._notify("onEndMove");
    
    // Release event observing
    Event.stopObserving(document, "mouseup", this.eventMouseUp,false);
    Event.stopObserving(document, "mousemove", this.eventMouseMove, false);

    Event.stop(event);
    
    this._hideWiredElement();

    // Store new location/size if need be
    this._saveCookie()
      
    // Restore selection
    document.body.ondrag = null;
    document.body.onselectstart = null;
  },

  _updateLeftConstraint: function(left) {
    if (this.constraint && this.useLeft && this.useTop) {
      var width = this.options.parent == document.body ? WindowUtilities.getPageSize().windowWidth : this.options.parent.getDimensions().width;

      if (left < this.constraintPad.left)
        left = this.constraintPad.left;
      if (left + this.width + this.widthE + this.widthW > width - this.constraintPad.right) 
        left = width - this.constraintPad.right - this.width - this.widthE - this.widthW;
    }
    return left;
  },
  
  _updateTopConstraint: function(top) {
    if (this.constraint && this.useLeft && this.useTop) {        
      var height = this.options.parent == document.body ? WindowUtilities.getPageSize().windowHeight : this.options.parent.getDimensions().height;
      
      var h = this.height + this.heightN + this.heightS;

      if (top < this.constraintPad.top)
        top = this.constraintPad.top;
      if (top + h > height - this.constraintPad.bottom) 
        top = height - this.constraintPad.bottom - h;
    }
    return top;
  },
  
  _updateWidthConstraint: function(w) {
    if (this.constraint && this.useLeft && this.useTop) {
      var width = this.options.parent == document.body ? WindowUtilities.getPageSize().windowWidth : this.options.parent.getDimensions().width;
      var left =  parseFloat(this.element.getStyle("left"));

      if (left + w + this.widthE + this.widthW > width - this.constraintPad.right) 
        w = width - this.constraintPad.right - left - this.widthE - this.widthW;
    }
    return w;
  },
  
  _updateHeightConstraint: function(h) {
    if (this.constraint && this.useLeft && this.useTop) {
      var height = this.options.parent == document.body ? WindowUtilities.getPageSize().windowHeight : this.options.parent.getDimensions().height;
      var top =  parseFloat(this.element.getStyle("top"));

      if (top + h + this.heightN + this.heightS > height - this.constraintPad.bottom) 
        h = height - this.constraintPad.bottom - top - this.heightN - this.heightS;
    }
    return h;
  },
  
  
  // Creates HTML window code
  _createWindow: function(id) {
    var className = this.options.className;
    var win = document.createElement("div");
    win.setAttribute('id', id);
    win.className = "dialog";

    var content;
    if (this.options.url)
      content= "<iframe frameborder=\"0\" name=\"" + id + "_content\"  id=\"" + id + "_content\" src=\"" + this.options.url + "\"> </iframe>";
    else
      content ="<div id=\"" + id + "_content\" class=\"" +className + "_content\"> </div>";

    var closeDiv = this.options.closable ? "<div class='"+ className +"_close' id='"+ id +"_close' onclick='Windows.close(\""+ id +"\", event)'> </div>" : "";
    var minDiv = this.options.minimizable ? "<div class='"+ className + "_minimize' id='"+ id +"_minimize' onclick='Windows.minimize(\""+ id +"\", event)'> </div>" : "";
    var maxDiv = this.options.maximizable ? "<div class='"+ className + "_maximize' id='"+ id +"_maximize' onclick='Windows.maximize(\""+ id +"\", event)'> </div>" : "";
    var seAttributes = this.options.resizable ? "class='" + className + "_sizer' id='" + id + "_sizer'" : "class='"  + className + "_se'";
    var blank = "../themes/default/blank.gif";
    
    win.innerHTML = "<div class='"+ className +"_butts_container'>"+ closeDiv + minDiv + maxDiv + "</div>\
      <table id='"+ id +"_row1' class=\"top table_window\">\
        <tr>\
          <td class='"+ className +"_nw'></td>\
          <td class='"+ className +"_n'><div id='"+ id +"_top' class='"+ className +"_title title_window'>"+ this.options.title +"</div></td>\
          <td class='"+ className +"_ne'></td>\
        </tr>\
      </table>\
      <table id='"+ id +"_row2' class=\"mid table_window\">\
        <tr>\
          <td class='"+ className +"_w'></td>\
            <td id='"+ id +"_table_content' class='"+ className +"_content' valign='top'>" + content + "</td>\
          <td class='"+ className +"_e'></td>\
        </tr>\
      </table>\
        <table id='"+ id +"_row3' class=\"bot table_window\">\
        <tr>\
          <td class='"+ className +"_sw'></td>\
            <td class='"+ className +"_s'><div id='"+ id +"_bottom' class='status_bar'><span style='float:left; width:1px; height:1px'></span></div></td>\
            <td " + seAttributes + "></td>\
        </tr>\
      </table>\
    ";
    Element.hide(win);
    this.options.parent.insertBefore(win, this.options.parent.firstChild);
    Event.observe($(id + "_content"), "load", this.options.onload);
    return win;
  },
  
  
  changeClassName: function(newClassName) {    
    var className = this.options.className;
    var id = this.getId();
    $A(["_close", "_minimize", "_maximize", "_sizer", "_content"]).each(function(value) { this._toggleClassName($(id + value), className + value, newClassName + value) }.bind(this));
    this._toggleClassName($(id + "_top"), className + "_title", newClassName + "_title");
    $$("#" + id + " td").each(function(td) {td.className = td.className.sub(className,newClassName); });
    this.options.className = newClassName;
  },
  
  _toggleClassName: function(element, oldClassName, newClassName) { 
    if (element) {
      element.removeClassName(oldClassName);
      element.addClassName(newClassName);
    }
  },
  
  // Sets window location
  setLocation: function(top, left) {
    top = this._updateTopConstraint(top);
    left = this._updateLeftConstraint(left);

    var e = this.currentDrag || this.element;
    e.setStyle({top: top + 'px'});
    e.setStyle({left: left + 'px'});

    this.useLeft = true;
    this.useTop = true;
  },
    
  getLocation: function() {
    var location = {};
    if (this.useTop)
      location = Object.extend(location, {top: this.element.getStyle("top")});
    else
      location = Object.extend(location, {bottom: this.element.getStyle("bottom")});
    if (this.useLeft)
      location = Object.extend(location, {left: this.element.getStyle("left")});
    else
      location = Object.extend(location, {right: this.element.getStyle("right")});
    
    return location;
  },
  
  // Gets window size
  getSize: function() {
    return {width: this.width, height: this.height};
  },
    
  // Sets window size
  setSize: function(width, height, useEffect) {    
    width = parseFloat(width);
    height = parseFloat(height);
    
    // Check min and max size
    if (!this.minimized && width < this.options.minWidth)
      width = this.options.minWidth;

    if (!this.minimized && height < this.options.minHeight)
      height = this.options.minHeight;
      
    if (this.options. maxHeight && height > this.options. maxHeight)
      height = this.options. maxHeight;

    if (this.options. maxWidth && width > this.options. maxWidth)
      width = this.options. maxWidth;

    
    if (this.useTop && this.useLeft && Window.hasEffectLib && Effect.ResizeWindow && useEffect) {
      new Effect.ResizeWindow(this, null, null, width, height, {duration: Window.resizeEffectDuration});
    } else {
      this.width = width;
      this.height = height;
      var e = this.currentDrag ? this.currentDrag : this.element;

      e.setStyle({width: width + this.widthW + this.widthE + "px"})
      e.setStyle({height: height  + this.heightN + this.heightS + "px"})

      // Update content size
      if (!this.currentDrag || this.currentDrag == this.element) {
        var content = $(this.element.id + '_content');
        content.setStyle({height: height  + 'px'});
        content.setStyle({width: width  + 'px'});
      }
    }
  },
  
  updateHeight: function() {
    this.setSize(this.width, this.content.scrollHeight, true);
  },
  
  updateWidth: function() {
    this.setSize(this.content.scrollWidth, this.height, true);
  },
  
  // Brings window to front
  toFront: function() {
    if (this.element.style.zIndex < Windows.maxZIndex)  
      this.setZIndex(Windows.maxZIndex + 1);
    if (this.iefix) 
      this._fixIEOverlapping(); 
  },
   
  getBounds: function(insideOnly) {
    if (! this.width || !this.height || !this.visible)  
      this.computeBounds();
    var w = this.width;
    var h = this.height;

    if (!insideOnly) {
      w += this.widthW + this.widthE;
      h += this.heightN + this.heightS;
    }
    var bounds = Object.extend(this.getLocation(), {width: w + "px", height: h + "px"});
    return bounds;
  },
      
  computeBounds: function() {
     if (! this.width || !this.height) {
      var size = WindowUtilities._computeSize(this.content.innerHTML, this.content.id, this.width, this.height, 0, this.options.className)
      if (this.height)
        this.width = size + 5
      else
        this.height = size + 5
    }

    this.setSize(this.width, this.height);
    if (this.centered)
      this._center(this.centerTop, this.centerLeft);    
  },
  
  // Displays window modal state or not
  show: function(modal) {
  
    this.visible = true;
    if (modal) {
      // Hack for Safari !!
      if (typeof this.overlayOpacity == "undefined") {
        var that = this;
        setTimeout(function() {that.show(modal)}, 10);
        return;
      }
      Windows.addModalWindow(this);
      
      this.modal = true;      
      this.setZIndex(Windows.maxZIndex + 1);
      Windows.unsetOverflow(this);
    }
    else    
      if (!this.element.style.zIndex) 
        this.setZIndex(Windows.maxZIndex + 1);        
      
    // To restore overflow if need be
    if (this.oldStyle)
      this.getContent().setStyle({overflow: this.oldStyle});
      
    this.computeBounds();
    
    this._notify("onBeforeShow");   
    if (this.options.showEffect != Element.show && this.options.showEffectOptions)
      this.options.showEffect(this.element, this.options.showEffectOptions);  
    else
      this.options.showEffect(this.element);  
      
    this._checkIEOverlapping();
    WindowUtilities.focusedWindow = this
    this._notify("onShow");   
    
  },
  
  // Displays window modal state or not at the center of the page
  showCenter: function(modal, top, left) {
    this.centered = true;
    this.centerTop = top;
    this.centerLeft = left;

    this.show(modal);
  },
  
  isVisible: function() {
    return this.visible;
  },
  
  _center: function(top, left) {    
    var windowScroll = WindowUtilities.getWindowScroll(this.options.parent);    
    var pageSize = WindowUtilities.getPageSize(this.options.parent);    
    if (typeof top == "undefined")
      top = (pageSize.windowHeight - (this.height + this.heightN + this.heightS))/2;
    top += windowScroll.top
    
    if (typeof left == "undefined")
      left = (pageSize.windowWidth - (this.width + this.widthW + this.widthE))/2;
    left += windowScroll.left      
    this.setLocation(top, left);
    this.toFront();
  },
  
  _recenter: function(event) {     
    if (this.centered) {
      var pageSize = WindowUtilities.getPageSize(this.options.parent);
      var windowScroll = WindowUtilities.getWindowScroll(this.options.parent);    

      // Check for this stupid IE that sends dumb events
      if (this.pageSize && this.pageSize.windowWidth == pageSize.windowWidth && this.pageSize.windowHeight == pageSize.windowHeight && 
          this.windowScroll.left == windowScroll.left && this.windowScroll.top == windowScroll.top) 
        return;
      this.pageSize = pageSize;
      this.windowScroll = windowScroll;
      // set height of Overlay to take up whole page and show
      if ($('overlay_modal')) 
        $('overlay_modal').setStyle({height: (pageSize.pageHeight + 'px')});
      
      if (this.options.recenterAuto)
        this._center(this.centerTop, this.centerLeft);    
    }
  },
  
  // Hides window
  hide: function() {
    this.visible = false;
    if (this.modal) {
      Windows.removeModalWindow(this);
      Windows.resetOverflow();
    }
    // To avoid bug on scrolling bar
    this.oldStyle = this.getContent().getStyle('overflow') || "auto"
    this.getContent().setStyle({overflow: "hidden"});

    this.options.hideEffect(this.element, this.options.hideEffectOptions);  

     if(this.iefix) 
      this.iefix.hide();

    if (!this.doNotNotifyHide)
      this._notify("onHide");
  },

  close: function() {
    // Asks closeCallback if exists
    if (this.visible) {
      if (this.options.closeCallback && ! this.options.closeCallback(this)) 
        return;

      if (this.options.destroyOnClose) {
        var destroyFunc = this.destroy.bind(this);
        if (this.options.hideEffectOptions.afterFinish) {
          var func = this.options.hideEffectOptions.afterFinish;
          this.options.hideEffectOptions.afterFinish = function() {func();destroyFunc() }
        }
        else 
          this.options.hideEffectOptions.afterFinish = function() {destroyFunc() }
      }
      Windows.updateFocusedWindow();
      
      this.doNotNotifyHide = true;
      this.hide();
      this.doNotNotifyHide = false;
      this._notify("onClose");
    }
  },
  
  minimize: function() {
    if (this.resizing)
      return;
    
    var r2 = $(this.getId() + "_row2");
    
    if (!this.minimized) {
      this.minimized = true;

      var dh = r2.getDimensions().height;
      this.r2Height = dh;
      var h  = this.element.getHeight() - dh;

      if (this.useLeft && this.useTop && Window.hasEffectLib && Effect.ResizeWindow) {
        new Effect.ResizeWindow(this, null, null, null, this.height -dh, {duration: Window.resizeEffectDuration});
      } else  {
        this.height -= dh;
        this.element.setStyle({height: h + "px"});
        r2.hide();
      }

      if (! this.useTop) {
        var bottom = parseFloat(this.element.getStyle('bottom'));
        this.element.setStyle({bottom: (bottom + dh) + 'px'});
      }
    } 
    else {      
      this.minimized = false;
      
      var dh = this.r2Height;
      this.r2Height = null;
      if (this.useLeft && this.useTop && Window.hasEffectLib && Effect.ResizeWindow) {
        new Effect.ResizeWindow(this, null, null, null, this.height + dh, {duration: Window.resizeEffectDuration});
      }
      else {
        var h  = this.element.getHeight() + dh;
        this.height += dh;
        this.element.setStyle({height: h + "px"})
        r2.show();
      }
      if (! this.useTop) {
        var bottom = parseFloat(this.element.getStyle('bottom'));
        this.element.setStyle({bottom: (bottom - dh) + 'px'});
      }
      this.toFront();
    }
    this._notify("onMinimize");
    
    // Store new location/size if need be
    this._saveCookie()
  },
  
  maximize: function() {
    if (this.isMinimized() || this.resizing)
      return;
  
    if (Prototype.Browser.IE && this.heightN == 0)
      this._getWindowBorderSize();
      
    if (this.storedLocation != null) {
      this._restoreLocation();
      if(this.iefix) 
        this.iefix.hide();
    }
    else {
      this._storeLocation();
      Windows.unsetOverflow(this);
      
      var windowScroll = WindowUtilities.getWindowScroll(this.options.parent);
      var pageSize = WindowUtilities.getPageSize(this.options.parent);    
      var left = windowScroll.left;
      var top = windowScroll.top;
      
      if (this.options.parent != document.body) {
        windowScroll =  {top:0, left:0, bottom:0, right:0};
        var dim = this.options.parent.getDimensions();
        pageSize.windowWidth = dim.width;
        pageSize.windowHeight = dim.height;
        top = 0; 
        left = 0;
      }
      
      if (this.constraint) {
        pageSize.windowWidth -= Math.max(0, this.constraintPad.left) + Math.max(0, this.constraintPad.right);
        pageSize.windowHeight -= Math.max(0, this.constraintPad.top) + Math.max(0, this.constraintPad.bottom);
        left +=  Math.max(0, this.constraintPad.left);
        top +=  Math.max(0, this.constraintPad.top);
      }
      
      var width = pageSize.windowWidth - this.widthW - this.widthE;
      var height= pageSize.windowHeight - this.heightN - this.heightS;

      if (this.useLeft && this.useTop && Window.hasEffectLib && Effect.ResizeWindow) {
        new Effect.ResizeWindow(this, top, left, width, height, {duration: Window.resizeEffectDuration});
      }
      else {
        this.setSize(width, height);
        this.element.setStyle(this.useLeft ? {left: left} : {right: left});
        this.element.setStyle(this.useTop ? {top: top} : {bottom: top});
      }
        
      this.toFront();
      if (this.iefix) 
        this._fixIEOverlapping(); 
    }
    this._notify("onMaximize");

    // Store new location/size if need be
    this._saveCookie()
  },
  
  isMinimized: function() {
    return this.minimized;
  },
  
  isMaximized: function() {
    return (this.storedLocation != null);
  },
  
  setOpacity: function(opacity) {
    if (Element.setOpacity)
      Element.setOpacity(this.element, opacity);
  },
  
  setZIndex: function(zindex) {
    this.element.setStyle({zIndex: zindex});
    Windows.updateZindex(zindex, this);
  },

  setTitle: function(newTitle) {
    if (!newTitle || newTitle == "") 
      newTitle = "&nbsp;";
      
    Element.update(this.element.id + '_top', newTitle);
  },
   
  getTitle: function() {
    return $(this.element.id + '_top').innerHTML;
  },
  
  setStatusBar: function(element) {
    var statusBar = $(this.getId() + "_bottom");

    if (typeof(element) == "object") {
      if (this.bottombar.firstChild)
        this.bottombar.replaceChild(element, this.bottombar.firstChild);
      else
        this.bottombar.appendChild(element);
    }
    else
      this.bottombar.innerHTML = element;
  },

  _checkIEOverlapping: function() {
  	
    if(!this.iefix && (navigator.appVersion.indexOf('MSIE')>0) && (navigator.userAgent.indexOf('Opera')<0) && (this.element.getStyle('position')=='absolute')) {
        new Insertion.After(this.element.id, '<iframe id="' + this.element.id + '_iefix" '+ 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' + 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
        this.iefix = $(this.element.id+'_iefix');
    }
    
    if(this.iefix) 
      setTimeout(this._fixIEOverlapping.bind(this), 50);
  },

  _fixIEOverlapping: function() {
      //
      if (this.element && this.iefix){
      	// Position.clone(this.element, this.iefix);
      	// Element.clonePosition(this.iefix, this.element);
      	this.iefix.style.zIndex = this.element.style.zIndex - 1;
      	this.iefix.show();
      }
  },
  
  _getWindowBorderSize: function(event) {
    // Hack to get real window border size!!
    var div = this._createHiddenDiv(this.options.className + "_n")
    this.heightN = Element.getDimensions(div).height;    
    div.parentNode.removeChild(div)

    var div = this._createHiddenDiv(this.options.className + "_s")
    this.heightS = Element.getDimensions(div).height;    
    div.parentNode.removeChild(div)

    var div = this._createHiddenDiv(this.options.className + "_e")
    this.widthE = Element.getDimensions(div).width;    
    div.parentNode.removeChild(div)

    var div = this._createHiddenDiv(this.options.className + "_w")
    this.widthW = Element.getDimensions(div).width;
    div.parentNode.removeChild(div);
    
    var div = document.createElement("div");
    div.className = "overlay_" + this.options.className ;
    Element.setOpacity(div, 0.6);

    document.body.appendChild(div);
    //alert("no timeout:\nopacity: " + div.getStyle("opacity") + "\nwidth: " + document.defaultView.getComputedStyle(div, null).width);
    var that = this;
    
    // Workaround for Safari!!
    setTimeout(function() {that.overlayOpacity = ($(div).getStyle("opacity")); div.parentNode.removeChild(div);}, 10);
    
    // Workaround for IE!!
    if (Prototype.Browser.IE) {
      this.heightS = $(this.getId() +"_row3").getDimensions().height;
      this.heightN = $(this.getId() +"_row1").getDimensions().height;
    }

    // Safari size fix
    if (Prototype.Browser.WebKit && Prototype.Browser.WebKitVersion < 420)
      this.setSize(this.width, this.height);
    if (this.doMaximize)
      this.maximize();
    if (this.doMinimize)
      this.minimize();
  },
 
  _createHiddenDiv: function(className) {
    var objBody = document.body;
    var win = document.createElement("div");
    win.setAttribute('id', this.element.id+ "_tmp");
    win.className = className;
    win.style.display = 'none';
    win.innerHTML = '';
    objBody.insertBefore(win, objBody.firstChild);
    return win;
  },
  
  _storeLocation: function() {
    if (this.storedLocation == null) {
      this.storedLocation = {useTop: this.useTop, useLeft: this.useLeft, 
                             top: this.element.getStyle('top'), bottom: this.element.getStyle('bottom'),
                             left: this.element.getStyle('left'), right: this.element.getStyle('right'),
                             width: this.width, height: this.height };
    }
  },
  
  _restoreLocation: function() {
    if (this.storedLocation != null) {
      this.useLeft = this.storedLocation.useLeft;
      this.useTop = this.storedLocation.useTop;
      
      if (this.useLeft && this.useTop && Window.hasEffectLib && Effect.ResizeWindow)
        new Effect.ResizeWindow(this, this.storedLocation.top, this.storedLocation.left, this.storedLocation.width, this.storedLocation.height, {duration: Window.resizeEffectDuration});
      else {
        this.element.setStyle(this.useLeft ? {left: this.storedLocation.left} : {right: this.storedLocation.right});
        this.element.setStyle(this.useTop ? {top: this.storedLocation.top} : {bottom: this.storedLocation.bottom});
        this.setSize(this.storedLocation.width, this.storedLocation.height);
      }
      
      Windows.resetOverflow();
      this._removeStoreLocation();
    }
  },
  
  _removeStoreLocation: function() {
    this.storedLocation = null;
  },
  
  _saveCookie: function() {
    if (this.cookie) {
      var value = "";
      if (this.useLeft)
        value += "l:" +  (this.storedLocation ? this.storedLocation.left : this.element.getStyle('left'))
      else
        value += "r:" + (this.storedLocation ? this.storedLocation.right : this.element.getStyle('right'))
      if (this.useTop)
        value += ",t:" + (this.storedLocation ? this.storedLocation.top : this.element.getStyle('top'))
      else
        value += ",b:" + (this.storedLocation ? this.storedLocation.bottom :this.element.getStyle('bottom'))
        
      value += "," + (this.storedLocation ? this.storedLocation.width : this.width);
      value += "," + (this.storedLocation ? this.storedLocation.height : this.height);
      value += "," + this.isMinimized();
      value += "," + this.isMaximized();
      WindowUtilities.setCookie(value, this.cookie)
    }
  },
  
  _createWiredElement: function() {
    if (! this.wiredElement) {
      if (Prototype.Browser.IE)
        this._getWindowBorderSize();
      var div = document.createElement("div");
      div.className = "wired_frame " + this.options.className + "_wired_frame";
      
      div.style.position = 'absolute';
      this.options.parent.insertBefore(div, this.options.parent.firstChild);
      this.wiredElement = $(div);
    }
    if (this.useLeft) 
      this.wiredElement.setStyle({left: this.element.getStyle('left')});
    else 
      this.wiredElement.setStyle({right: this.element.getStyle('right')});
      
    if (this.useTop) 
      this.wiredElement.setStyle({top: this.element.getStyle('top')});
    else 
      this.wiredElement.setStyle({bottom: this.element.getStyle('bottom')});

    var dim = this.element.getDimensions();
    this.wiredElement.setStyle({width: dim.width + "px", height: dim.height +"px"});

    this.wiredElement.setStyle({zIndex: Windows.maxZIndex+30});
    return this.wiredElement;
  },
  
  _hideWiredElement: function() {
    if (! this.wiredElement || ! this.currentDrag)
      return;
    if (this.currentDrag == this.element) 
      this.currentDrag = null;
    else {
      if (this.useLeft) 
        this.element.setStyle({left: this.currentDrag.getStyle('left')});
      else 
        this.element.setStyle({right: this.currentDrag.getStyle('right')});

      if (this.useTop) 
        this.element.setStyle({top: this.currentDrag.getStyle('top')});
      else 
        this.element.setStyle({bottom: this.currentDrag.getStyle('bottom')});

      this.currentDrag.hide();
      this.currentDrag = null;
      if (this.doResize)
        this.setSize(this.width, this.height);
    } 
  },
  
  _notify: function(eventName) {
    if (this.options[eventName])
      this.options[eventName](this);
    else
      Windows.notify(eventName, this);
  }
};

// Windows containers, register all page windows
var Windows = {
  windows: [],
  modalWindows: [],
  observers: [],
  focusedWindow: null,
  maxZIndex: 0,
  overlayShowEffectOptions: {duration: 0.5},
  overlayHideEffectOptions: {duration: 0.5},

  addObserver: function(observer) {
    this.removeObserver(observer);
    this.observers.push(observer);
  },
  
  removeObserver: function(observer) {  
    this.observers = this.observers.reject( function(o) { return o==observer });
  },
  
  // onDestroy onStartResize onStartMove onResize onMove onEndResize onEndMove onFocus onBlur onBeforeShow onShow onHide onMinimize onMaximize onClose
  notify: function(eventName, win) {  
    this.observers.each( function(o) {if(o[eventName]) o[eventName](eventName, win);});
  },

  // Gets window from its id
  getWindow: function(id) {
    return this.windows.detect(function(d) { return d.getId() ==id });
  },

  // Gets the last focused window
  getFocusedWindow: function() {
    return this.focusedWindow;
  },

  updateFocusedWindow: function() {
    this.focusedWindow = this.windows.length >=2 ? this.windows[this.windows.length-2] : null;    
  },
  
  // Registers a new window (called by Windows constructor)
  register: function(win) {
    this.windows.push(win);
  },
    
  // Add a modal window in the stack
  addModalWindow: function(win) {
    // Disable screen if first modal window
    if (this.modalWindows.length == 0) {
      WindowUtilities.disableScreen(win.options.className, 'overlay_modal', win.overlayOpacity, win.getId(), win.options.parent);
    }
    else {
      // Move overlay over all windows
      if (Window.keepMultiModalWindow) {
        $('overlay_modal').style.zIndex = Windows.maxZIndex + 1;
        Windows.maxZIndex += 1;
        WindowUtilities._hideSelect(this.modalWindows.last().getId());
      }
      // Hide current modal window
      else
        this.modalWindows.last().element.hide();
      // Fucking IE select issue
      WindowUtilities._showSelect(win.getId());
    }      
    this.modalWindows.push(win);    
  },
  
  removeModalWindow: function(win) {
    this.modalWindows.pop();
    
    // No more modal windows
    if (this.modalWindows.length == 0)
      WindowUtilities.enableScreen();     
    else {
      if (Window.keepMultiModalWindow) {
        this.modalWindows.last().toFront();
        WindowUtilities._showSelect(this.modalWindows.last().getId());        
      }
      else
        this.modalWindows.last().element.show();
    }
  },
  
  // Registers a new window (called by Windows constructor)
  register: function(win) {
    this.windows.push(win);
  },
  
  // Unregisters a window (called by Windows destructor)
  unregister: function(win) {
    this.windows = this.windows.reject(function(d) { return d==win });
  }, 
  
  // Closes all windows
  closeAll: function() {  
    this.windows.each( function(w) {Windows.close(w.getId())} );
  },
  
  closeAllModalWindows: function() {
    WindowUtilities.enableScreen();     
    this.modalWindows.each( function(win) {if (win) win.close()});    
  },

  // Minimizes a window with its id
  minimize: function(id, event) {
    var win = this.getWindow(id)
    if (win && win.visible)
      win.minimize();
    Event.stop(event);
  },
  
  // Maximizes a window with its id
  maximize: function(id, event) {
    var win = this.getWindow(id)
    if (win && win.visible)
      win.maximize();
    Event.stop(event);
  },

  // Closes a window with its id
  close: function(id, event) {
    var win = this.getWindow(id);
    if (win) 
      win.close();
    if (event)
      Event.stop(event);
  },
  
  blur: function(id) {
    var win = this.getWindow(id);  
    if (!win)
      return;
    if (win.options.blurClassName)
      win.changeClassName(win.options.blurClassName);
    if (this.focusedWindow == win)  
      this.focusedWindow = null;
    win._notify("onBlur");  
  },
  
  focus: function(id) {
    var win = this.getWindow(id);  
    if (!win)
      return;       
    if (this.focusedWindow)
      this.blur(this.focusedWindow.getId())

    if (win.options.focusClassName)
      win.changeClassName(win.options.focusClassName);  
    this.focusedWindow = win;
    win._notify("onFocus");
  },
  
  unsetOverflow: function(except) {    
    this.windows.each(function(d) { d.oldOverflow = d.getContent().getStyle("overflow") || "auto" ; d.getContent().setStyle({overflow: "hidden"}) });
    if (except && except.oldOverflow)
      except.getContent().setStyle({overflow: except.oldOverflow});
  },

  resetOverflow: function() {
    this.windows.each(function(d) { if (d.oldOverflow) d.getContent().setStyle({overflow: d.oldOverflow}) });
  },

  updateZindex: function(zindex, win) { 
    if (zindex > this.maxZIndex) {   
      this.maxZIndex = zindex;    
      if (this.focusedWindow) 
        this.blur(this.focusedWindow.getId())
    }
    this.focusedWindow = win;
    if (this.focusedWindow) 
      this.focus(this.focusedWindow.getId())
  }
};

var Dialog = {
  dialogId: null,
  onCompleteFunc: null,
  callFunc: null, 
  parameters: null, 
    
  confirm: function(content, parameters) {
    // Get Ajax return before
    if (content && typeof content != "string") {
      Dialog._runAjaxRequest(content, parameters, Dialog.confirm);
      return 
    }
    content = content || "";
    
    parameters = parameters || {};
    var okLabel = parameters.okLabel ? parameters.okLabel : "Ok";
    var cancelLabel = parameters.cancelLabel ? parameters.cancelLabel : "Cancel";

    // Backward compatibility
    parameters = Object.extend(parameters, parameters.windowParameters || {});
    parameters.windowParameters = parameters.windowParameters || {};

    parameters.className = parameters.className || "alert";

    var okButtonClass = "class ='" + (parameters.buttonClass ? parameters.buttonClass + " " : "") + " ok_button'" 
    var cancelButtonClass = "class ='" + (parameters.buttonClass ? parameters.buttonClass + " " : "") + " cancel_button'" 
    var content = "\
      <div class='" + parameters.className + "_message'>" + content  + "</div>\
        <div class='" + parameters.className + "_buttons'>\
          <input id='btOKconfirm' type='button' value='" + okLabel + "' onclick='Dialog.okCallback()' " + okButtonClass + " />\
          <input type='button' value='" + cancelLabel + "' onclick='Dialog.cancelCallback()' " + cancelButtonClass + " />\
        </div>\
    ";
    return this._openDialog(content, parameters)
  },
  
  alert: function(content, parameters) {
    // Get Ajax return before
    if (content && typeof content != "string") {
      Dialog._runAjaxRequest(content, parameters, Dialog.alert);
      return 
    }
    content = content || "";
    
    parameters = parameters || {};
    var okLabel = parameters.okLabel ? parameters.okLabel : "Ok";

    // Backward compatibility    
    parameters = Object.extend(parameters, parameters.windowParameters || {});
    parameters.windowParameters = parameters.windowParameters || {};
    
    parameters.className = parameters.className || "alert";
    
    var okButtonClass = "class ='" + (parameters.buttonClass ? parameters.buttonClass + " " : "") + " ok_button'" 
    var content = "\
      <div class='" + parameters.className + "_message'>" + content  + "</div>\
        <div class='" + parameters.className + "_buttons'>\
          <input id='btOKconfirm' type='button' value='" + okLabel + "' onclick='Dialog.okCallback()' " + okButtonClass + "/>\
        </div>";                  
    return this._openDialog(content, parameters)
  },
  
  info: function(content, parameters) {   
  	
    // Get Ajax return before
    if (content && typeof content != "string") {
      Dialog._runAjaxRequest(content, parameters, Dialog.info);
      return 
    }
    content = content || "";
    
    // Backward compatibility
    parameters = parameters || {};
    parameters = Object.extend(parameters, parameters.windowParameters || {});
    parameters.windowParameters = parameters.windowParameters || {};
    
    parameters.className = parameters.className || "alert";
     
    var content = "<div id='modal_dialog_message' class='" + parameters.className + "_message'>" + content  + "</div>";
    if (parameters.showProgress)
      content += "<div id='modal_dialog_progress' class='" + parameters.className + "_progress'>  </div>";

    parameters.ok = null;
    parameters.cancel = null;
    
    return this._openDialog(content, parameters)
  },
  
  setInfoMessage: function(message) {
    $('modal_dialog_message').update(message);
  },
  
  closeInfo: function() {
    Windows.close(this.dialogId);
  },
  
  _openDialog: function(content, parameters) {
    var className = parameters.className;
    
    if (! parameters.height && ! parameters.width) {
      parameters.width = WindowUtilities.getPageSize(parameters.options.parent || document.body).pageWidth / 2;
    }
    if (parameters.id)
      this.dialogId = parameters.id;
    else { 
      var t = new Date();
      this.dialogId = 'modal_dialog_' + t.getTime();
      parameters.id = this.dialogId;
    }

    // compute height or width if need be
    if (! parameters.height || ! parameters.width) {
      var size = WindowUtilities._computeSize(content, this.dialogId, parameters.width, parameters.height, 5, className)
      if (parameters.height)
        parameters.width = size + 5
      else
        parameters.height = size + 5
    }
    parameters.effectOptions = parameters.effectOptions ;
    parameters.resizable   = parameters.resizable || false;
    parameters.minimizable = parameters.minimizable || false;
    parameters.maximizable = parameters.maximizable ||  false;
    parameters.draggable   = parameters.draggable || false;
    parameters.closable    = parameters.closable || false;
    
    var win = new Window(parameters);
    win.getContent().innerHTML = content;
    
    win.showCenter(true, parameters.top, parameters.left);  
    win.setDestroyOnClose();
    
    win.cancelCallback = parameters.onCancel || parameters.cancel; 
    win.okCallback = parameters.onOk || parameters.ok;
    // setTimeout(function() { if($('btOKconfirm')) $('btOKconfirm').focus()}, 500);
  
    return win;    
  },
  
  _getAjaxContent: function(originalRequest)  {
      Dialog.callFunc(originalRequest.responseText, Dialog.parameters)
  },
  
  _runAjaxRequest: function(message, parameters, callFunc) {
    if (message.options == null)
      message.options = {}  
    Dialog.onCompleteFunc = message.options.onComplete;
    Dialog.parameters = parameters;
    Dialog.callFunc = callFunc;
    
    message.options.onComplete = Dialog._getAjaxContent;
    new Ajax.Request(message.url, message.options);
  },
  
  okCallback: function() {
    var win = Windows.focusedWindow;
    if (!win.okCallback || win.okCallback(win)) {
      // Remove onclick on button
      $$("#" + win.getId()+" input").each(function(element) {element.onclick=null;})
      win.close();
    }
  },

  cancelCallback: function() {
    var win = Windows.focusedWindow;
    // Remove onclick on button
    $$("#" + win.getId()+" input").each(function(element) {element.onclick=null})
    win.close();
    if (win.cancelCallback)
      win.cancelCallback(win);
  }
}
/*
  Based on Lightbox JS: Fullsize Image Overlays 
  by Lokesh Dhakar - http://www.huddletogether.com

  For more information on this script, visit:
  http://huddletogether.com/projects/lightbox/

  Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/
  (basically, do anything you want, just leave my name and link)
*/

if (Prototype.Browser.WebKit) {
  var array = navigator.userAgent.match(new RegExp(/AppleWebKit\/([\d\.\+]*)/));
  Prototype.Browser.WebKitVersion = parseFloat(array[1]);
}

var WindowUtilities = {  
  // From dragdrop.js
  getWindowScroll: function(parent) {
    var T, L, W, H;
    parent = parent || document.body;              
    if (parent != document.body) {
      T = parent.scrollTop;
      L = parent.scrollLeft;
      W = parent.scrollWidth;
      H = parent.scrollHeight;
    } 
    else {
      var w = window;
      with (w.document) {
        if (w.document.documentElement && documentElement.scrollTop) {
          T = documentElement.scrollTop;
          L = documentElement.scrollLeft;
        } else if (w.document.body) {
          T = body.scrollTop;
          L = body.scrollLeft;
        }
        if (w.innerWidth) {
          W = w.innerWidth;
          H = w.innerHeight;
        } else if (w.document.documentElement && documentElement.clientWidth) {
          W = documentElement.clientWidth;
          H = documentElement.clientHeight;
        } else {
          W = body.offsetWidth;
          H = body.offsetHeight
        }
      }
    }
    return { top: T, left: L, width: W, height: H };
  }, 
  //
  // getPageSize()
  // Returns array with page width, height and window width, height
  // Core code from - quirksmode.org
  // Edit for Firefox by pHaez
  //
  getPageSize: function(parent){
    parent = parent || document.body;              
    var windowWidth, windowHeight;
    var pageHeight, pageWidth;
    if (parent != document.body) {
      windowWidth = parent.getWidth();
      windowHeight = parent.getHeight();                                
      pageWidth = parent.scrollWidth;
      pageHeight = parent.scrollHeight;                                
    } 
    else {
      var xScroll, yScroll;

      if (window.innerHeight && window.scrollMaxY) {  
        xScroll = document.body.scrollWidth;
        yScroll = window.innerHeight + window.scrollMaxY;
      } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
        xScroll = document.body.scrollWidth;
        yScroll = document.body.scrollHeight;
      } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
        xScroll = document.body.offsetWidth;
        yScroll = document.body.offsetHeight;
      }


      if (self.innerHeight) {  // all except Explorer
        windowWidth = self.innerWidth;
        windowHeight = self.innerHeight;
      } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
        windowWidth = document.documentElement.clientWidth;
        windowHeight = document.documentElement.clientHeight;
      } else if (document.body) { // other Explorers
        windowWidth = document.body.clientWidth;
        windowHeight = document.body.clientHeight;
      }  

      // for small pages with total height less then height of the viewport
      if(yScroll < windowHeight){
        pageHeight = windowHeight;
      } else { 
        pageHeight = yScroll;
      }

      // for small pages with total width less then width of the viewport
      if(xScroll < windowWidth){  
        pageWidth = windowWidth;
      } else {
        pageWidth = xScroll;
      }
    }             
    return {pageWidth: pageWidth ,pageHeight: pageHeight , windowWidth: windowWidth, windowHeight: windowHeight};
  },

  disableScreen: function(className, overlayId, overlayOpacity, contentId, parent) {
    WindowUtilities.initLightbox(overlayId, className, function() {this._disableScreen(className, overlayId, overlayOpacity, contentId)}.bind(this), parent || document.body);
  },

  _disableScreen: function(className, overlayId, overlayOpacity, contentId) {
    // prep objects
    var objOverlay = $(overlayId);

    var pageSize = WindowUtilities.getPageSize(objOverlay.parentNode);

    // Hide select boxes as they will 'peek' through the image in IE, store old value
    if (contentId && Prototype.Browser.IE) {
      WindowUtilities._hideSelect();
      WindowUtilities._showSelect(contentId);
    }  
  
    // set height of Overlay to take up whole page and show
    objOverlay.style.height = (pageSize.pageHeight + 'px');
    objOverlay.style.display = 'none'; 
    if (overlayId == "overlay_modal" && Window.hasEffectLib && Windows.overlayShowEffectOptions) {
      objOverlay.overlayOpacity = overlayOpacity;
      new Effect.Appear(objOverlay, Object.extend({from: 0, to: overlayOpacity}, Windows.overlayShowEffectOptions));
    }
    else
      objOverlay.style.display = "block";
  },
  
  enableScreen: function(id) {
    id = id || 'overlay_modal';
    var objOverlay =  $(id);
    if (objOverlay) {
      // hide lightbox and overlay
      if (id == "overlay_modal" && Window.hasEffectLib && Windows.overlayHideEffectOptions)
        new Effect.Fade(objOverlay, Object.extend({from: objOverlay.overlayOpacity, to:0}, Windows.overlayHideEffectOptions));
      else {
        objOverlay.style.display = 'none';
        objOverlay.parentNode.removeChild(objOverlay);
      }
      
      // make select boxes visible using old value
      if (id != "__invisible__") 
        WindowUtilities._showSelect();
    }
  },

  _hideSelect: function(id) {
    if (Prototype.Browser.IE) {
      id = id ==  null ? "" : "#" + id + " ";
      $$(id + 'select').each(function(element) {
        if (! WindowUtilities.isDefined(element.oldVisibility)) {
          element.oldVisibility = element.style.visibility ? element.style.visibility : "visible";
          element.style.visibility = "hidden";
        }
      });
    }
  },
  
  _showSelect: function(id) {
    if (Prototype.Browser.IE) {
      id = id ==  null ? "" : "#" + id + " ";
      $$(id + 'select').each(function(element) {
        if (WindowUtilities.isDefined(element.oldVisibility)) {
          // Why?? Ask IE
          try {
            element.style.visibility = element.oldVisibility;
          } catch(e) {
            element.style.visibility = "visible";
          }
          element.oldVisibility = null;
        }
        else {
          if (element.style.visibility)
            element.style.visibility = "visible";
        }
      });
    }
  },

  isDefined: function(object) {
    return typeof(object) != "undefined" && object != null;
  },
  
  // initLightbox()
  // Function runs on window load, going through link tags looking for rel="lightbox".
  // These links receive onclick events that enable the lightbox display for their targets.
  // The function also inserts html markup at the top of the page which will be used as a
  // container for the overlay pattern and the inline image.
  initLightbox: function(id, className, doneHandler, parent) {
    // Already done, just update zIndex
    if ($(id)) {
      Element.setStyle(id, {zIndex: Windows.maxZIndex + 1});
      Windows.maxZIndex++;
      doneHandler();
    }
    // create overlay div and hardcode some functional styles (aesthetic styles are in CSS file)
    else {
      var objOverlay = document.createElement("div");
      objOverlay.setAttribute('id', id);
      objOverlay.className = "overlay_" + className
      objOverlay.style.display = 'none';
      objOverlay.style.position = 'absolute';
      objOverlay.style.top = '0';
      objOverlay.style.left = '0';
      objOverlay.style.zIndex = Windows.maxZIndex + 1;
      Windows.maxZIndex++;
      objOverlay.style.width = '100%';
      Element.setOpacity(objOverlay, 0.6);
      // objOverlay.setOpacity(0.6);
      parent.insertBefore(objOverlay, parent.firstChild);
      if (Prototype.Browser.WebKit && id == "overlay_modal") {
        setTimeout(function() {doneHandler()}, 10);
      }
      else
        doneHandler();
    }    
  },
  
  setCookie: function(value, parameters) {
    document.cookie= parameters[0] + "=" + escape(value) +
      ((parameters[1]) ? "; expires=" + parameters[1].toGMTString() : "") +
      ((parameters[2]) ? "; path=" + parameters[2] : "") +
      ((parameters[3]) ? "; domain=" + parameters[3] : "") +
      ((parameters[4]) ? "; secure" : "");
  },

  getCookie: function(name) {
    var dc = document.cookie;
    var prefix = name + "=";
    var begin = dc.indexOf("; " + prefix);
    if (begin == -1) {
      begin = dc.indexOf(prefix);
      if (begin != 0) return null;
    } else {
      begin += 2;
    }
    var end = document.cookie.indexOf(";", begin);
    if (end == -1) {
      end = dc.length;
    }
    return unescape(dc.substring(begin + prefix.length, end));
  },
    
  _computeSize: function(content, id, width, height, margin, className) {
    var objBody = document.body;
    var tmpObj = document.createElement("div");
    tmpObj.setAttribute('id', id);
    tmpObj.className = className + "_content";

    if (height)
      tmpObj.style.height = height + "px"
    else
      tmpObj.style.width = width + "px"
  
    tmpObj.style.position = 'absolute';
    tmpObj.style.top = '0';
    tmpObj.style.left = '0';
    tmpObj.style.display = 'none';

    tmpObj.innerHTML = content;
    objBody.insertBefore(tmpObj, objBody.firstChild);

    var size;
    if (height)
      size = $(tmpObj).getDimensions().width + margin;
    else
      size = $(tmpObj).getDimensions().height + margin;
    objBody.removeChild(tmpObj);
    return size;
  }  
}



/*! SWFObject v2.1 <http://code.google.com/p/swfobject/>
	Copyright (c) 2007-2008 Geoff Stearns, Michael Williams, and Bobby van der Sluis
	This software is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
*/

var swfobject = function() {
	
	var UNDEF = "undefined",
		OBJECT = "object",
		SHOCKWAVE_FLASH = "Shockwave Flash",
		SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash",
		FLASH_MIME_TYPE = "application/x-shockwave-flash",
		EXPRESS_INSTALL_ID = "SWFObjectExprInst",
		
		win = window,
		doc = document,
		nav = navigator,
		
		domLoadFnArr = [],
		regObjArr = [],
		objIdArr = [],
		listenersArr = [],
		script,
		timer = null,
		storedAltContent = null,
		storedAltContentId = null,
		isDomLoaded = false,
		isExpressInstallActive = false;
	
	/* Centralized function for browser feature detection
		- Proprietary feature detection (conditional compiling) is used to detect Internet Explorer's features
		- User agent string detection is only used when no alternative is possible
		- Is executed directly for optimal performance
	*/	
	var ua = function() {
		var w3cdom = typeof doc.getElementById != UNDEF && typeof doc.getElementsByTagName != UNDEF && typeof doc.createElement != UNDEF,
			playerVersion = [0,0,0],
			d = null;
		if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) {
			d = nav.plugins[SHOCKWAVE_FLASH].description;
			if (d && !(typeof nav.mimeTypes != UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) { // navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin indicates whether plug-ins are enabled or disabled in Safari 3+
				d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
				playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10);
				playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
				playerVersion[2] = /r/.test(d) ? parseInt(d.replace(/^.*r(.*)$/, "$1"), 10) : 0;
			}
		}
		else if (typeof win.ActiveXObject != UNDEF) {
			var a = null, fp6Crash = false;
			try {
				a = new ActiveXObject(SHOCKWAVE_FLASH_AX + ".7");
			}
			catch(e) {
				try { 
					a = new ActiveXObject(SHOCKWAVE_FLASH_AX + ".6");
					playerVersion = [6,0,21];
					a.AllowScriptAccess = "always";	 // Introduced in fp6.0.47
				}
				catch(e) {
					if (playerVersion[0] == 6) {
						fp6Crash = true;
					}
				}
				if (!fp6Crash) {
					try {
						a = new ActiveXObject(SHOCKWAVE_FLASH_AX);
					}
					catch(e) {}
				}
			}
			if (!fp6Crash && a) { // a will return null when ActiveX is disabled
				try {
					d = a.GetVariable("$version");	// Will crash fp6.0.21/23/29
					if (d) {
						d = d.split(" ")[1].split(",");
						playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
					}
				}
				catch(e) {}
			}
		}
		var u = nav.userAgent.toLowerCase(),
			p = nav.platform.toLowerCase(),
			webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, // returns either the webkit version or false if not webkit
			ie = false,
			windows = p ? /win/.test(p) : /win/.test(u),
			mac = p ? /mac/.test(p) : /mac/.test(u);
		/*@cc_on
			ie = true;
			@if (@_win32)
				windows = true;
			@elif (@_mac)
				mac = true;
			@end
		@*/
		return { w3cdom:w3cdom, pv:playerVersion, webkit:webkit, ie:ie, win:windows, mac:mac };
	}();

	/* Cross-browser onDomLoad
		- Based on Dean Edwards' solution: http://dean.edwards.name/weblog/2006/06/again/
		- Will fire an event as soon as the DOM of a page is loaded (supported by Gecko based browsers - like Firefox -, IE, Opera9+, Safari)
	*/ 
	var onDomLoad = function() {
		if (!ua.w3cdom) {
			return;
		}
		addDomLoadEvent(main);
		if (ua.ie && ua.win) {
			try {	 // Avoid a possible Operation Aborted error
				doc.write("<scr" + "ipt id=__ie_ondomload defer=true src=//:></scr" + "ipt>"); // String is split into pieces to avoid Norton AV to add code that can cause errors 
				script = getElementById("__ie_ondomload");
				if (script) {
					addListener(script, "onreadystatechange", checkReadyState);
				}
			}
			catch(e) {}
		}
		if (ua.webkit && typeof doc.readyState != UNDEF) {
			timer = setInterval(function() { if (/loaded|complete/.test(doc.readyState)) { callDomLoadFunctions(); }}, 10);
		}
		if (typeof doc.addEventListener != UNDEF) {
			doc.addEventListener("DOMContentLoaded", callDomLoadFunctions, null);
		}
		addLoadEvent(callDomLoadFunctions);
	}();
	
	function checkReadyState() {
		if (script.readyState == "complete") {
			script.parentNode.removeChild(script);
			callDomLoadFunctions();
		}
	}
	
	function callDomLoadFunctions() {
		if (isDomLoaded) {
			return;
		}
		if (ua.ie && ua.win) { // Test if we can really add elements to the DOM; we don't want to fire it too early
			var s = createElement("span");
			try { // Avoid a possible Operation Aborted error
				var t = doc.getElementsByTagName("body")[0].appendChild(s);
				t.parentNode.removeChild(t);
			}
			catch (e) {
				return;
			}
		}
		isDomLoaded = true;
		if (timer) {
			clearInterval(timer);
			timer = null;
		}
		var dl = domLoadFnArr.length;
		for (var i = 0; i < dl; i++) {
			domLoadFnArr[i]();
		}
	}
	
	function addDomLoadEvent(fn) {
		if (isDomLoaded) {
			fn();
		}
		else { 
			domLoadFnArr[domLoadFnArr.length] = fn; // Array.push() is only available in IE5.5+
		}
	}
	
	/* Cross-browser onload
		- Based on James Edwards' solution: http://brothercake.com/site/resources/scripts/onload/
		- Will fire an event as soon as a web page including all of its assets are loaded 
	 */
	function addLoadEvent(fn) {
		if (typeof win.addEventListener != UNDEF) {
			win.addEventListener("load", fn, false);
		}
		else if (typeof doc.addEventListener != UNDEF) {
			doc.addEventListener("load", fn, false);
		}
		else if (typeof win.attachEvent != UNDEF) {
			addListener(win, "onload", fn);
		}
		else if (typeof win.onload == "function") {
			var fnOld = win.onload;
			win.onload = function() {
				fnOld();
				fn();
			};
		}
		else {
			win.onload = fn;
		}
	}
	
	/* Main function
		- Will preferably execute onDomLoad, otherwise onload (as a fallback)
	*/
	function main() { // Static publishing only
		var rl = regObjArr.length;
		for (var i = 0; i < rl; i++) { // For each registered object element
			var id = regObjArr[i].id;
			if (ua.pv[0] > 0) {
				var obj = getElementById(id);
				if (obj) {
					regObjArr[i].width = obj.getAttribute("width") ? obj.getAttribute("width") : "0";
					regObjArr[i].height = obj.getAttribute("height") ? obj.getAttribute("height") : "0";
					if (hasPlayerVersion(regObjArr[i].swfVersion)) { // Flash plug-in version >= Flash content version: Houston, we have a match!
						if (ua.webkit && ua.webkit < 312) { // Older webkit engines ignore the object element's nested param elements
							fixParams(obj);
						}
						setVisibility(id, true);
					}
					else if (regObjArr[i].expressInstall && !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac)) { // Show the Adobe Express Install dialog if set by the web page author and if supported (fp6.0.65+ on Win/Mac OS only)
						showExpressInstall(regObjArr[i]);
					}
					else { // Flash plug-in and Flash content version mismatch: display alternative content instead of Flash content
						displayAltContent(obj);
					}
				}
			}
			else {	// If no fp is installed, we let the object element do its job (show alternative content)
				setVisibility(id, true);
			}
		}
	}
	
	/* Fix nested param elements, which are ignored by older webkit engines
		- This includes Safari up to and including version 1.2.2 on Mac OS 10.3
		- Fall back to the proprietary embed element
	*/
	function fixParams(obj) {
		var nestedObj = obj.getElementsByTagName(OBJECT)[0];
		if (nestedObj) {
			var e = createElement("embed"), a = nestedObj.attributes;
			if (a) {
				var al = a.length;
				for (var i = 0; i < al; i++) {
					if (a[i].nodeName == "DATA") {
						e.setAttribute("src", a[i].nodeValue);
					}
					else {
						e.setAttribute(a[i].nodeName, a[i].nodeValue);
					}
				}
			}
			var c = nestedObj.childNodes;
			if (c) {
				var cl = c.length;
				for (var j = 0; j < cl; j++) {
					if (c[j].nodeType == 1 && c[j].nodeName == "PARAM") {
						e.setAttribute(c[j].getAttribute("name"), c[j].getAttribute("value"));
					}
				}
			}
			obj.parentNode.replaceChild(e, obj);
		}
	}
	
	/* Show the Adobe Express Install dialog
		- Reference: http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=6a253b75
	*/
	function showExpressInstall(regObj) {
		isExpressInstallActive = true;
		var obj = getElementById(regObj.id);
		if (obj) {
			if (regObj.altContentId) {
				var ac = getElementById(regObj.altContentId);
				if (ac) {
					storedAltContent = ac;
					storedAltContentId = regObj.altContentId;
				}
			}
			else {
				storedAltContent = abstractAltContent(obj);
			}
			if (!(/%$/.test(regObj.width)) && parseInt(regObj.width, 10) < 310) {
				regObj.width = "310";
			}
			if (!(/%$/.test(regObj.height)) && parseInt(regObj.height, 10) < 137) {
				regObj.height = "137";
			}
			doc.title = doc.title.slice(0, 47) + " - Flash Player Installation";
			var pt = ua.ie && ua.win ? "ActiveX" : "PlugIn",
				dt = doc.title,
				fv = "MMredirectURL=" + win.location + "&MMplayerType=" + pt + "&MMdoctitle=" + dt,
				replaceId = regObj.id;
			// For IE when a SWF is loading (AND: not available in cache) wait for the onload event to fire to remove the original object element
			// In IE you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work
			if (ua.ie && ua.win && obj.readyState != 4) {
				var newObj = createElement("div");
				replaceId += "SWFObjectNew";
				newObj.setAttribute("id", replaceId);
				obj.parentNode.insertBefore(newObj, obj); // Insert placeholder div that will be replaced by the object element that loads expressinstall.swf
				obj.style.display = "none";
				var fn = function() {
					obj.parentNode.removeChild(obj);
				};
				addListener(win, "onload", fn);
			}
			createSWF({ data:regObj.expressInstall, id:EXPRESS_INSTALL_ID, width:regObj.width, height:regObj.height }, { flashvars:fv }, replaceId);
		}
	}
	
	/* Functions to abstract and display alternative content
	*/
	function displayAltContent(obj) {
		if (ua.ie && ua.win && obj.readyState != 4) {
			// For IE when a SWF is loading (AND: not available in cache) wait for the onload event to fire to remove the original object element
			// In IE you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work
			var el = createElement("div");
			obj.parentNode.insertBefore(el, obj); // Insert placeholder div that will be replaced by the alternative content
			el.parentNode.replaceChild(abstractAltContent(obj), el);
			obj.style.display = "none";
			var fn = function() {
				obj.parentNode.removeChild(obj);
			};
			addListener(win, "onload", fn);
		}
		else {
			obj.parentNode.replaceChild(abstractAltContent(obj), obj);
		}
	} 

	function abstractAltContent(obj) {
		var ac = createElement("div");
		if (ua.win && ua.ie) {
			ac.innerHTML = obj.innerHTML;
		}
		else {
			var nestedObj = obj.getElementsByTagName(OBJECT)[0];
			if (nestedObj) {
				var c = nestedObj.childNodes;
				if (c) {
					var cl = c.length;
					for (var i = 0; i < cl; i++) {
						if (!(c[i].nodeType == 1 && c[i].nodeName == "PARAM") && !(c[i].nodeType == 8)) {
							ac.appendChild(c[i].cloneNode(true));
						}
					}
				}
			}
		}
		return ac;
	}
	
	/* Cross-browser dynamic SWF creation
	*/
	function createSWF(attObj, parObj, id) {
		var r, el = getElementById(id);
		if (el) {
			if (typeof attObj.id == UNDEF) { // if no 'id' is defined for the object element, it will inherit the 'id' from the alternative content
				attObj.id = id;
			}
			if (ua.ie && ua.win) { // IE, the object element and W3C DOM methods do not combine: fall back to outerHTML
				var att = "";
				for (var i in attObj) {
					if (attObj[i] != Object.prototype[i]) { // Filter out prototype additions from other potential libraries, like Object.prototype.toJSONString = function() {}
						if (i.toLowerCase() == "data") {
							parObj.movie = attObj[i];
						}
						else if (i.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
							att += ' class="' + attObj[i] + '"';
						}
						else if (i.toLowerCase() != "classid") {
							att += ' ' + i + '="' + attObj[i] + '"';
						}
					}
				}
				var par = "";
				for (var j in parObj) {
					if (parObj[j] != Object.prototype[j]) { // Filter out prototype additions from other potential libraries
						par += '<param name="' + j + '" value="' + parObj[j] + '" />';
					}
				}
				el.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + att + '>' + par + '</object>';
				objIdArr[objIdArr.length] = attObj.id; // Stored to fix object 'leaks' on unload (dynamic publishing only)
				r = getElementById(attObj.id);	
			}
			else if (ua.webkit && ua.webkit < 312) { // Older webkit engines ignore the object element's nested param elements: fall back to the proprietary embed element
				var e = createElement("embed");
				e.setAttribute("type", FLASH_MIME_TYPE);
				for (var k in attObj) {
					if (attObj[k] != Object.prototype[k]) { // Filter out prototype additions from other potential libraries
						if (k.toLowerCase() == "data") {
							e.setAttribute("src", attObj[k]);
						}
						else if (k.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
							e.setAttribute("class", attObj[k]);
						}
						else if (k.toLowerCase() != "classid") { // Filter out IE specific attribute
							e.setAttribute(k, attObj[k]);
						}
					}
				}
				for (var l in parObj) {
					if (parObj[l] != Object.prototype[l]) { // Filter out prototype additions from other potential libraries
						if (l.toLowerCase() != "movie") { // Filter out IE specific param element
							e.setAttribute(l, parObj[l]);
						}
					}
				}
				el.parentNode.replaceChild(e, el);
				r = e;
			}
			else { // Well-behaving browsers
				var o = createElement(OBJECT);
				o.setAttribute("type", FLASH_MIME_TYPE);
				for (var m in attObj) {
					if (attObj[m] != Object.prototype[m]) { // Filter out prototype additions from other potential libraries
						if (m.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
							o.setAttribute("class", attObj[m]);
						}
						else if (m.toLowerCase() != "classid") { // Filter out IE specific attribute
							o.setAttribute(m, attObj[m]);
						}
					}
				}
				for (var n in parObj) {
					if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie") { // Filter out prototype additions from other potential libraries and IE specific param element
						createObjParam(o, n, parObj[n]);
					}
				}
				el.parentNode.replaceChild(o, el);
				r = o;
			}
		}
		return r;
	}
	
	function createObjParam(el, pName, pValue) {
		var p = createElement("param");
		p.setAttribute("name", pName);	
		p.setAttribute("value", pValue);
		el.appendChild(p);
	}
	
	/* Cross-browser SWF removal
		- Especially needed to safely and completely remove a SWF in Internet Explorer
	*/
	function removeSWF(id) {
		var obj = getElementById(id);
		if (obj && (obj.nodeName == "OBJECT" || obj.nodeName == "EMBED")) {
			if (ua.ie && ua.win) {
				if (obj.readyState == 4) {
					removeObjectInIE(id);
				}
				else {
					win.attachEvent("onload", function() {
						removeObjectInIE(id);
					});
				}
			}
			else {
				obj.parentNode.removeChild(obj);
			}
		}
	}
	
	function removeObjectInIE(id) {
		var obj = getElementById(id);
		if (obj) {
			for (var i in obj) {
				if (typeof obj[i] == "function") {
					obj[i] = null;
				}
			}
			obj.parentNode.removeChild(obj);
		}
	}
	
	/* Functions to optimize JavaScript compression
	*/
	function getElementById(id) {
		var el = null;
		try {
			el = doc.getElementById(id);
		}
		catch (e) {}
		return el;
	}
	
	function createElement(el) {
		return doc.createElement(el);
	}
	
	/* Updated attachEvent function for Internet Explorer
		- Stores attachEvent information in an Array, so on unload the detachEvent functions can be called to avoid memory leaks
	*/	
	function addListener(target, eventType, fn) {
		target.attachEvent(eventType, fn);
		listenersArr[listenersArr.length] = [target, eventType, fn];
	}
	
	/* Flash Player and SWF content version matching
	*/
	function hasPlayerVersion(rv) {
		var pv = ua.pv, v = rv.split(".");
		v[0] = parseInt(v[0], 10);
		v[1] = parseInt(v[1], 10) || 0; // supports short notation, e.g. "9" instead of "9.0.0"
		v[2] = parseInt(v[2], 10) || 0;
		return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false;
	}
	
	/* Cross-browser dynamic CSS creation
		- Based on Bobby van der Sluis' solution: http://www.bobbyvandersluis.com/articles/dynamicCSS.php
	*/	
	function createCSS(sel, decl) {
		if (ua.ie && ua.mac) {
			return;
		}
		var h = doc.getElementsByTagName("head")[0], s = createElement("style");
		s.setAttribute("type", "text/css");
		s.setAttribute("media", "screen");
		if (!(ua.ie && ua.win) && typeof doc.createTextNode != UNDEF) {
			s.appendChild(doc.createTextNode(sel + " {" + decl + "}"));
		}
		h.appendChild(s);
		if (ua.ie && ua.win && typeof doc.styleSheets != UNDEF && doc.styleSheets.length > 0) {
			var ls = doc.styleSheets[doc.styleSheets.length - 1];
			if (typeof ls.addRule == OBJECT) {
				ls.addRule(sel, decl);
			}
		}
	}
	
	function setVisibility(id, isVisible) {
		var v = isVisible ? "visible" : "hidden";
		if (isDomLoaded && getElementById(id)) {
			getElementById(id).style.visibility = v;
		}
		else {
			createCSS("#" + id, "visibility:" + v);
		}
	}

	/* Filter to avoid XSS attacks 
	*/
	function urlEncodeIfNecessary(s) {
		var regex = /[\\\"<>\.;]/;
		var hasBadChars = regex.exec(s) != null;
		return hasBadChars ? encodeURIComponent(s) : s;
	}
	
	/* Release memory to avoid memory leaks caused by closures, fix hanging audio/video threads and force open sockets/NetConnections to disconnect (Internet Explorer only)
	*/
	var cleanup = function() {
		if (ua.ie && ua.win) {
			window.attachEvent("onunload", function() {
				// remove listeners to avoid memory leaks
				var ll = listenersArr.length;
				for (var i = 0; i < ll; i++) {
					listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]);
				}
				// cleanup dynamically embedded objects to fix audio/video threads and force open sockets and NetConnections to disconnect
				var il = objIdArr.length;
				for (var j = 0; j < il; j++) {
					removeSWF(objIdArr[j]);
				}
				// cleanup library's main closures to avoid memory leaks
				for (var k in ua) {
					ua[k] = null;
				}
				ua = null;
				for (var l in swfobject) {
					swfobject[l] = null;
				}
				swfobject = null;
			});
		}
	}();
	
	
	return {
		/* Public API
			- Reference: http://code.google.com/p/swfobject/wiki/SWFObject_2_0_documentation
		*/ 
		registerObject: function(objectIdStr, swfVersionStr, xiSwfUrlStr) {
			if (!ua.w3cdom || !objectIdStr || !swfVersionStr) {
				return;
			}
			var regObj = {};
			regObj.id = objectIdStr;
			regObj.swfVersion = swfVersionStr;
			regObj.expressInstall = xiSwfUrlStr ? xiSwfUrlStr : false;
			regObjArr[regObjArr.length] = regObj;
			setVisibility(objectIdStr, false);
		},
		
		getObjectById: function(objectIdStr) {
			var r = null;
			if (ua.w3cdom) {
				var o = getElementById(objectIdStr);
				if (o) {
					var n = o.getElementsByTagName(OBJECT)[0];
					if (!n || (n && typeof o.SetVariable != UNDEF)) {
							r = o;
					}
					else if (typeof n.SetVariable != UNDEF) {
						r = n;
					}
				}
			}
			return r;
		},
		
		embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj) {
			if (!ua.w3cdom || !swfUrlStr || !replaceElemIdStr || !widthStr || !heightStr || !swfVersionStr) {
				return;
			}
			widthStr += ""; // Auto-convert to string
			heightStr += "";
			if (hasPlayerVersion(swfVersionStr)) {
				setVisibility(replaceElemIdStr, false);
				var att = {};
				if (attObj && typeof attObj === OBJECT) {
					for (var i in attObj) {
						if (attObj[i] != Object.prototype[i]) { // Filter out prototype additions from other potential libraries
							att[i] = attObj[i];
						}
					}
				}
				att.data = swfUrlStr;
				att.width = widthStr;
				att.height = heightStr;
				var par = {}; 
				if (parObj && typeof parObj === OBJECT) {
					for (var j in parObj) {
						if (parObj[j] != Object.prototype[j]) { // Filter out prototype additions from other potential libraries
							par[j] = parObj[j];
						}
					}
				}
				if (flashvarsObj && typeof flashvarsObj === OBJECT) {
					for (var k in flashvarsObj) {
						if (flashvarsObj[k] != Object.prototype[k]) { // Filter out prototype additions from other potential libraries
							if (typeof par.flashvars != UNDEF) {
								par.flashvars += "&" + k + "=" + flashvarsObj[k];
							}
							else {
								par.flashvars = k + "=" + flashvarsObj[k];
							}
						}
					}
				}
				addDomLoadEvent(function() {
					createSWF(att, par, replaceElemIdStr);
					if (att.id == replaceElemIdStr) {
						setVisibility(replaceElemIdStr, true);
					}
				});
			}
			else if (xiSwfUrlStr && !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac)) {
				isExpressInstallActive = true; // deferred execution
				setVisibility(replaceElemIdStr, false);
				addDomLoadEvent(function() {
					var regObj = {};
					regObj.id = regObj.altContentId = replaceElemIdStr;
					regObj.width = widthStr;
					regObj.height = heightStr;
					regObj.expressInstall = xiSwfUrlStr;
					showExpressInstall(regObj);
				});
			}
		},
		
		getFlashPlayerVersion: function() {
			return { major:ua.pv[0], minor:ua.pv[1], release:ua.pv[2] };
		},
		
		hasFlashPlayerVersion: hasPlayerVersion,
		
		createSWF: function(attObj, parObj, replaceElemIdStr) {
			if (ua.w3cdom) {
				return createSWF(attObj, parObj, replaceElemIdStr);
			}
			else {
				return undefined;
			}
		},
		
		removeSWF: function(objElemIdStr) {
			if (ua.w3cdom) {
				removeSWF(objElemIdStr);
			}
		},
		
		createCSS: function(sel, decl) {
			if (ua.w3cdom) {
				createCSS(sel, decl);
			}
		},
		
		addDomLoadEvent: addDomLoadEvent,
		
		addLoadEvent: addLoadEvent,
		
		getQueryParamValue: function(param) {
			var q = doc.location.search || doc.location.hash;
			if (param == null) {
				return urlEncodeIfNecessary(q);
			}
			if (q) {
				var pairs = q.substring(1).split("&");
				for (var i = 0; i < pairs.length; i++) {
					if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) {
						return urlEncodeIfNecessary(pairs[i].substring((pairs[i].indexOf("=") + 1)));
					}
				}
			}
			return "";
		},
		
		// For internal usage only
		expressInstallCallback: function() {
			if (isExpressInstallActive && storedAltContent) {
				var obj = getElementById(EXPRESS_INSTALL_ID);
				if (obj) {
					obj.parentNode.replaceChild(storedAltContent, obj);
					if (storedAltContentId) {
						setVisibility(storedAltContentId, true);
						if (ua.ie && ua.win) {
							storedAltContent.style.display = "block";
						}
					}
					storedAltContent = null;
					storedAltContentId = null;
					isExpressInstallActive = false;
				}
			} 
		}
	};
}();


/**
	Protofade 1.2 18/09/09
	Copyright (c) 2009 Filippo Buratti; info [at] cssrevolt.com [dot] com; http://www.filippoburatti.net/

	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:

	The above copyright notice and this permission notice shall be included in
	all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
	THE SOFTWARE.
*/

var Protofade = Class.create({

	initialize: function(element, options) {		
		this.options = {
      		duration: 1,
			delay: 4.0,
			randomize: false,
			autostart:true,
			autostartdelay: 0,
			controls:false,
			eSquare:false,
			eRows: 3, 
			eCols: 5,
			eColor: '#FFFFFF'
    	}
		Object.extend(this.options, options || {});

    	this.element        = $(element);
		this.slides			= this.element.childElements();
		this.num_slides		= this.slides.length;		
		this.current_slide 	= (this.options.randomize) ? (Math.floor(Math.random()*this.num_slides)) : 0;
		this.end_slide		= this.num_slides - 1;
		
		this.slides.invoke('hide');
		this.slides[this.current_slide].show();
		
		if (this.options.autostartdelay > 0) { 
			setTimeout(this.startSlideshow.bind(this), this.options.autostartdelay * 1000);
		}else{
			if (this.options.autostart) { 
				this.startSlideshow();
			}
		}
		if (this.options.controls) {
			this.addControls();
		}
		if (this.options.eSquare) {
			this.buildEsquare();
		}
	},
	
	addControls: function() {
		this.wrapper 		= this.element.up();
		this.controls		= new Element('div', { 'class': 'controls' });
		this.wrapper.insert(this.controls);
		
		this.btn_next 		= new Element('a', { 'class': 'next', 'title': 'Next', href: '#' }).update('Next');
		this.btn_previous	= new Element('a', { 'class': 'previous', 'title': 'Previous', href: '#' }).update('Previous');
		this.btn_start		= new Element('a', { 'class': 'start', 'title': 'Start', href: '#' }).update('Start');
		this.btn_stop		= new Element('a', { 'class': 'stop', 'title': 'Stop', href: '#' }).update('Stop');
		
		this.btns = [this.btn_previous, this.btn_next, this.btn_start, this.btn_stop];
		this.btns.each(function(el){
			this.controls.insert(el);
		}.bind(this));
		
		this.btn_previous.observe('click', this.moveToPrevious.bindAsEventListener(this));
		this.btn_next.observe('click', this.moveToNext.bindAsEventListener(this));
		this.btn_start.observe('click', this.startSlideshow.bindAsEventListener(this));
		this.btn_stop.observe('click', this.stopSlideshow.bindAsEventListener(this));
	},
	
	buildEsquare: function() {		
		this.eSquares 	= [];
		var elDimension	 	= this.element.getDimensions();
		var elWidth  		= elDimension.width;
		var elHeight 		= elDimension.height;
				
		var sqWidth 		= elWidth / this.options.eCols;
		var sqHeight 		= elHeight / this.options.eRows;
	
		$R(0, this.options.eCols-1).each(function(col) {
			this.eSquares[col] = [];							 	
			$R(0, this.options.eRows-1).each(function(row) {
				var sqLeft = col * sqWidth;
			    var sqTop  = row * sqHeight;
				this.eSquares[col][row] = new Element('div').setStyle({
 														    opacity: 0, backgroundColor: this.options.eColor,
															position: 'absolute', 'z-index': 5,
															left: sqLeft + 'px', top: sqTop + 'px',
															width: sqWidth + 'px', height: sqHeight + 'px'		
														});
				this.element.insert(this.eSquares[col][row]);				 							 										 
			}.bind(this))
		}.bind(this));			
	},

	startSlideshow: function(event) {
		if (event) { Event.stop(event); }
		if (!this.running)	{
			this.executer = new PeriodicalExecuter(function(){
	  			this.updateSlide(this.current_slide+1);
	 		}.bind(this),this.options.delay);
			this.running=true;
		}
	},
	
	stopSlideshow: function(event) {	
		if (event) { Event.stop(event); } 
		if (this.executer) { 
			this.executer.stop();
			this.running=false;
		}	 
	},

	moveToPrevious: function (event) {
		if (event) { Event.stop(event); }
		this.stopSlideshow();
  		this.updateSlide(this.current_slide-1);
	},

	moveToNext: function (event) {
		if (event) { Event.stop(event); }
		this.stopSlideshow();
  		this.updateSlide(this.current_slide+1);
	},
	
	updateSlide: function(next_slide) {		
		if (next_slide > this.end_slide) { 
			next_slide = 0; 
		} 
		else if ( next_slide == -1 ) {
			next_slide = this.end_slide;
		}	
		this.fadeInOut(next_slide, this.current_slide);		
	},

 	fadeInOut: function (next, current) {		
		new Effect.Parallel([
			new Effect.Fade(this.slides[current], { sync: true }),
			new Effect.Appear(this.slides[next], { sync: true }) 
  		], { duration: this.options.duration });
		
		if (this.options.eSquare) {			
			$R(0, this.options.eCols-1).each(function(col) {	 						 	
				$R(0, this.options.eRows-1).each(function(row) {
					var eSquare = this.eSquares[col][row];
					var delay = Math.random() * 150;				
					setTimeout(this.delayedAppear.bind(this, eSquare), delay);
				}.bind(this))
			}.bind(this));	
		}
		
		this.current_slide = next;		
	},
	
	delayedAppear: function(eSquare)	{
		var opacity = Math.random();
		new Effect.Parallel([ 
			new Effect.Appear ( eSquare, { from: 0, to: opacity, duration: this.options.duration/4 } ),
			new Effect.Appear ( eSquare, { from: opacity, to: 0, duration: this.options.duration/1.25} )
		], { sync: false });			
	}

});


var MENSAJES = {
			"confirmDel": "Confirme que desea eliminar el registro.",
			"confirmAutoSave": "Confirme que desea guardar el registro.",
			"confirmSend": "Confirme que desea enviar el registro",
			"confirmDelFile": "Confirme que desea eliminar el fichero",
			"revisar": "Por favor revise los siguientes campos",
			"obligatorios": "Los siguientes campos son obligatorios",
			"enviando_datos": "Enviando datos, por favor espere ...",
			"todos": "Todos",
			"registros_por_pagina": "Registros por p&aacute;gina",
			"problem": "Error",
			"complete": "Completado",
			"error_form": "Los datos no han sido completados correctamente.\n Por favor revise los datos marcados.",
			"formato_fechas": "El formato de fechas debe ser uno de los siguientes:\n - dd-mm-yyyy\n - ddmmyyyy\n - dd/mm/yyyy"}
