
function getScriptPath() {
  var scriptTags = document.getElementsByTagName('script');

  return scriptTags[scriptTags.length - 1].src.split('?')[0].split('/').slice(0, -1).join('/') + '/';
}
var DL_WEB_ROOT = (getScriptPath().replace("js/dedolib/","").replace("js/",""));
var idiomaJs = getCookie('lang');


(function($){$.toJSON=function(o)
{if(typeof(JSON)=='object'&&JSON.stringify)
return JSON.stringify(o);var type=typeof(o);if(o===null)
return"null";if(type=="undefined")
return undefined;if(type=="number"||type=="boolean")
return o+"";if(type=="string")
return $.quoteString(o);if(type=='object')
{if(typeof o.toJSON=="function")
return $.toJSON(o.toJSON());if(o.constructor===Date)
{var month=o.getUTCMonth()+1;if(month<10)month='0'+month;var day=o.getUTCDate();if(day<10)day='0'+day;var year=o.getUTCFullYear();var hours=o.getUTCHours();if(hours<10)hours='0'+hours;var minutes=o.getUTCMinutes();if(minutes<10)minutes='0'+minutes;var seconds=o.getUTCSeconds();if(seconds<10)seconds='0'+seconds;var milli=o.getUTCMilliseconds();if(milli<100)milli='0'+milli;if(milli<10)milli='0'+milli;return'"'+year+'-'+month+'-'+day+'T'+
hours+':'+minutes+':'+seconds+'.'+milli+'Z"';}
if(o.constructor===Array)
{var ret=[];for(var i=0;i<o.length;i++)
ret.push($.toJSON(o[i])||"null");return"["+ret.join(",")+"]";}
var pairs=[];for(var k in o){var name;var type=typeof k;if(type=="number")
name='"'+k+'"';else if(type=="string")
name=$.quoteString(k);else
continue;if(typeof o[k]=="function")
continue;var val=$.toJSON(o[k]);pairs.push(name+":"+val);}
return"{"+pairs.join(", ")+"}";}};$.evalJSON=function(src)
{if(typeof(JSON)=='object'&&JSON.parse)
return JSON.parse(src);return eval("("+src+")");};$.secureEvalJSON=function(src)
{if(typeof(JSON)=='object'&&JSON.parse)
return JSON.parse(src);var filtered=src;filtered=filtered.replace(/\\["\\\/bfnrtu]/g,'@');filtered=filtered.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']');filtered=filtered.replace(/(?:^|:|,)(?:\s*\[)+/g,'');if(/^[\],:{}\s]*$/.test(filtered))
return eval("("+src+")");else
throw new SyntaxError("Error parsing JSON, source is not valid.");};$.quoteString=function(string)
{if(string.match(_escapeable))
{return'"'+string.replace(_escapeable,function(a)
{var c=_meta[a];if(typeof c==='string')return c;c=a.charCodeAt();return'\\u00'+Math.floor(c/16).toString(16)+(c%16).toString(16);})+'"';}
return'"'+string+'"';};var _escapeable=/["\\\x00-\x1f\x7f-\x9f]/g;var _meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'};})(jQuery);

/* Simple JavaScript Inheritance
 * By John Resig http://ejohn.org/
 * MIT Licensed.
 */
// Inspired by base2 and Prototype
(function(){
  var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
  // The base Class implementation (does nothing)
  this.Class = function(){};
  
  // Create a new Class that inherits from this class
  Class.extend = function(prop) {
    var _super = this.prototype;
    
    // Instantiate a base class (but only create the instance,
    // don't run the init constructor)
    initializing = true;
    var prototype = new this();
    initializing = false;
    
    // Copy the properties over onto the new prototype
    for (var name in prop) {
      // Check if we're overwriting an existing function
      prototype[name] = typeof prop[name] == "function" && 
        typeof _super[name] == "function" && fnTest.test(prop[name]) ?
        (function(name, fn){
          return function() {
            var tmp = this._super;
            
            // Add a new ._super() method that is the same method
            // but on the super-class
            this._super = _super[name];
            
            // The method only need to be bound temporarily, so we
            // remove it when we're done executing
            var ret = fn.apply(this, arguments);        
            this._super = tmp;
            
            return ret;
          };
        })(name, prop[name]) :
        prop[name];
    }
    
    // The dummy class constructor
    function Class() {
      // All construction is actually done in the init method
      if ( !initializing && this.init )
        this.init.apply(this, arguments);
    }
    
    // Populate our constructed prototype object
    Class.prototype = prototype;
    
    // Enforce the constructor to be what we expect
    Class.prototype.constructor = Class;

    // And make this class extendable
    Class.extend = arguments.callee;
    
    return Class;
  };
})();


/**
* Funciones dedolib para los dialogos y alertas en pantalla
*/
function DL_messageInfo(){
	var winH = $(window).height();
	var winW = $(window).width();
	// var ancho = $("body div:first-child").width(); 
	var ancho = winW * 80 / 100;

	$("#mensajeInfo").css('width',  ancho);

	$("#mensajeInfo").css('top',  winH/2-$("#mensajeInfo").height()/2);
	$("#mensajeInfo").css('left', winW/2-(ancho/2));
	$('#mensajeInfo').fadeTo("fast",1.0);
	
	if($("#mensajeInfo li.info").length > 0){
		setTimeout(function() { $('#mensajeInfo').fadeOut('slow'); }, 2000);
	}else{
    	$('#mensajeInfo').click(function(e) { desbloqueaWindow();});
	}
}

function DL_showMask(){
	if($("#DL_mask").length == 0){
		$("<div/>", {
			id:"DL_mask"
		}).appendTo("body");
	}
	var maskHeight = $(document).height();
	var maskWidth = $(window).width();
	$('#DL_mask').css({'width':maskWidth,'height':maskHeight});
    
    $('#DL_mask').fadeTo("fast",0.7);
    // $('#DL_mask').click(function(e) { desbloqueaWindow();});
}
function DL_hideMask(){
	$('#DL_mask').hide();
}
function DL_growlMessage(msg) {
	if($("#DL_growl").length == 0){
		$("<div/>", {
			id:"DL_growl",
			text: msg
		}).appendTo("body");
	}
	var winH = $(window).height();
	var winW = $(window).width();
               
	$("#DL_growl").css('top',  winH/2-$("#DL_growl").height()/2);
	$("#DL_growl").css('left', winW/2-$("#DL_growl").width()/2);
	$('#DL_growl').fadeTo("fast",0.9);
}
function DL_hideGrowlMessage(){
	$('#DL_growl').hide();
}
function bloqueaWindow(){
    DL_showMask();
    DL_growlMessage(MENSAJES['enviando_datos']);
}
function desbloqueaWindow(){
	DL_hideGrowlMessage();
	DL_hideMask();
}
function alertaWin(msg) {
	$("#alertaWin").remove();
	if($("#alertaWin").length == 0){
		$("<div/>", {
			"class": "DLalerta",
			id:"alertaWin",
			"title": "",
			text: ''
		}).html('<p><span class="ui-icon ui-icon-alert" style="float:left; margin:3px 7px 60px 0;"></span>' + msg + '</p>').appendTo("body");
	}
	
	$( "#alertaWin" ).dialog({
			modal: false,
			draggable: false,
			resizable: false,
			buttons: {
				Ok: function() {
					$( this ).dialog( "close" );
				}
			}
		});
	$( "#alertaWin" ).bind( "dialogclose", function(event, ui) {
		desbloqueaWindow();
	});
}

function DL_messageConfirm(msg,myFunc){
	DL_showMask();
	if($("#confirmWin").length == 0){
		$("<div/>", {
			"class": "DLconfirm",
			id:"confirmWin",
			"title": "",
			text: ''
		}).html('<p><span class="ui-icon ui-icon-alert" style="float:left; margin:0px 7px 20px 0;"></span>' + msg + '</p>').appendTo("body");
	}
	$( "#confirmWin" ).dialog({
			modal: false,
			draggable: false,
			resizable: false
		});
		
	$('.ui-dialog :button').blur();
	$( "#confirmWin" ).dialog( "option", "buttons",
		[{	text: "Ok",
        	id: 'okBT',
        	click: myFunc
    	},
    	{	text: "Cancel",
        	id: 'cancelBT',
        	click: function() {$(this).dialog("close"); }
    	}]);
	$( "#confirmWin" ).bind( "dialogclose", function(event, ui) {
		desbloqueaWindow();
	});
}




/****************************************************
 * Funciones de submit
 ****************************************************/

function FormSubmitter(formName, formCbs)
{
	this.formName = formName;
	this.form = document[formName];
	this.formCbs = formCbs;
}

/**
 * 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";
	// bug safari / chrome
	this.form.action = this.form.action + '?' + Math.random()*1000;

	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'];
	}
	
	var okFunc = function() { $(this).dialog("close");s.ejecuta(accion, id); return true; }
	DL_messageConfirm(msg,okFunc);
	return false;
}


FormSubmitter.prototype.autoSave = function(accion, id)
{
	msg = MENSAJES['confirmAutoSave'];
	
	var okFunc = function() { $(this).dialog("close");s.valida_ejecuta(accion, id); return true; }
	DL_messageConfirm(msg,okFunc);
	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;
	
	var okFunc = function() { 
				$(this).dialog("close");
				var oldAccion = formu.accion.value;
				formu.accion.value = "ajaxDelfoto:" + memname;
				var valsForm = $('#f').serialize();
				valsForm = valsForm.split('accion_').join('boton_');
				formu.accion.value = oldAccion;
				var urlString = valsForm;
				$.ajax({
					type: "POST",
					url: formu.action,
					data: urlString,
					dataType : 'html',
					success: function(msg){
						document.f.elements[memname].value = 0;
						$('#contenedor_' + memname).slideUp('fast');
						
						$('#mensajeInfo').remove();
						$("body").append(msg);
						DL_messageInfo();
					}
				});
				return true;
				}
	DL_messageConfirm(msg,okFunc);
	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;
	
	var okFunc = function() { 
				$(this).dialog("close");
				var oldAccion = formu.accion.value;
				formu.accion.value = "ajaxDelfile:" + memname;
				var valsForm = $('#f').serialize();
				valsForm = valsForm.split('accion_').join('boton_');
				formu.accion.value = oldAccion;
				var urlString = valsForm;
				$.ajax({
					type: "POST",
					url: formu.action,
					data: urlString,
					dataType : 'html',
					success: function(msg){
						document.f.elements['F_' + memname].value = '';
						$('#contenedor_' + memname).slideUp('fast');
						$('#contenedor_' + memname + '_imgprev').slideUp('fast');
						$('#mensajeInfo').remove();
						$("body").append(msg);
						DL_messageInfo();
					}
				});
				return true;
				}
	DL_messageConfirm(msg,okFunc);
	
	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);
				$('#'+hiddenId).value = '';
				
				obj.value = "";
				break;
			case "file":
			case "textarea":
				obj.value = "";
				break;
		}
		
	}
	return false;
}



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;
	}
}


var MemberDedoLib = Class.extend({
	init: function(formElementName, pTipo, pFormat, pRequired, pTitle, pEnabled, pValidateFunc) {
    	var $this = this;
    	this.a_name = this.getMemberName(formElementName);
    	this.campoUser = $('#'+this.a_name); // el campo que rellena el usuario. normalmente el mismo id, a veces cambia el id (fecha, autocomplete)
		this.element = $('#'+this.a_name);		// el elemento que se usa para almacenar el valor real (p.ej. en autocomplete el valor real  esta en un hidden)
		this.memNameForLabel = this.a_name;
		if((this.a_tipo=='multienum' || this.a_tipo=='multiforkey') && this.a_format == 'select'){
			this.memNameForLabel = this.a_name.substr(0,this.a_name.length-2);
		}	
		
		
		if(pTipo == 'date'){
			this.element = $('#H_'+this.a_name);
			this.campoUser = $('#H_'+this.a_name);
		}
		if(pFormat == 'autocomplete') this.campoUser = $('#auto_'+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(this.element.is('.accesibleVal')){
			this.a_accesibleVal = this.campoUser.val();
		}
		if(pEnabled == '1') this.a_enabled = true;
	
		var validateFunc = '';
		if(pValidateFunc) validateFunc = pValidateFunc;
		this.a_validateFunc = validateFunc;
		
		this.hasError = false;
		if(pFormat == 'ckeditor'){
			setTimeout(function() { $this.initCKEDITOR();} , 1000);
			this.campoUser.change(function() {
				$this.validateInServer();
			});
		}else{
			if(pFormat == 'radio' || pFormat == 'checks') {
				$("input[name*='"+this.a_name+"']").each(function(k,el){
					$(el).change(function(){
						$this.validateInServer();
					});
				});
			}else{
				if((this.a_tipo=='multienum' || this.a_tipo=='multiforkey') && this.a_format == 'select'){
					// el change / validacion se hace desde la funcion que mueve los items
				}else{
					this.campoUser.change(function() {
						$this.validateInServer();
					});
				}
			}
		}

	},
   
	initCKEDITOR: function() {
		var $this = this;
		var editor = CKEDITOR.instances[this.a_name];
		if(editor) {
			editor.on( 'blur', function(e) { 
								// $this.validateInServer();
								$('#'+$this.a_name).html(this.getData());
								$('#'+$this.a_name).trigger('change');
							});
		}
	},
   
	getMemberName: function(formElementName) {
		var arr = formElementName.split("[");
		formElementName = arr[0];
		formElementName = formElementName.replace('Out','In');
		return formElementName;
	},
   
	setRequired: function(req) {
		var $this = this;
		this.a_required = req;
		$this.validateInServer();
	},
   
   onSubmitMember: function() {
		var valSerialize = '';
		var member = this.a_name;
		if(this.a_accesibleVal && $('#'+member).val() == this.a_accesibleVal){
			$('#'+member).val("");
		}
		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.val());
		}
		
		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).val();
				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.val('OK');
						var textoRte = $('#'+member).val();
					}
				}else{
					var textoRte = document.f.elements[member].value;
				}
			
			valSerialize += '&valSer_' + member + '=' + (textoRte);
		}
		
		return valSerialize;
   },
   
	validateInServer: function() {
   		if(this.a_enabled == false) return;
		var $this = this;
   		var member = this.a_name;
		var valSerialize = this.onSubmitMember();
		var valsForm = $('#f').serialize();
		
		var dataMember = {};
		$.each(['a_tipo','a_format','a_required','a_title','a_accesibleVal','a_validateFunc'], function(k,v) {
			dataMember[v] = $this[v];
		});
		
		var paramsMember = $.param(dataMember);
		var urlString = 'accionJS=validaMember&member='+member + '&' + paramsMember + '&' + valsForm + '&' + valSerialize;
		$.ajax({
			type: "POST",
			url: DL_WEB_ROOT+'utilidades/validator.php',
			data: urlString,
			dataType : 'html',
			success: function(msg){
				$this.showResponse(msg);
			}
		});
	},
   
	showResponse: function(msg) {
		this.hasError = false;
		var $this = this;
		if(msg == 'OKY'){
			this.campoUser.removeClass('campoError');
			$this.assignLabel('complete');
			// this.element.blur();
			this._closePrompt();
		}else{
			this.campoUser.addClass('campoError');
			// this.element.val(msg);
			$this.assignLabel('problem');
			this.element.blur();
			this._buildPrompt(msg);
		}
	},
   
	assignLabel: function(tipoLabel) {
   		var elImg = $('#L__'+this.memNameForLabel +' > img');
		elImg.attr('alt',MENSAJES[tipoLabel]);
		elImg.attr('src', DL_WEB_ROOT+'images/dedolib/'+tipoLabel+'.gif');
	},
       
        _closePrompt: function() {
        	var $this = this;
            if (this.prompt)
                this.prompt.fadeTo("fast", 0, function() {
                    $this.prompt.remove();
                    $this.prompt = null;
                });
        },

        _buildPrompt: function(promptText) {
			if(!oFormCallbacks.config.showErrorsText) return;
			if(this.prompt) return;
			var $this = this;
			var promptPos = oFormCallbacks.config.errorPosition || "topLeft";
			var options = {	showArrow:true
							,promptPosition: promptPos}
							
            // create the prompt
            var prompt = $('<div>');
            prompt.addClass("formError");

            // create the prompt content
            var promptContent = $('<div>').addClass("formErrorContent").html(promptText).appendTo(prompt);
            // create the css arrow pointing at the field
            // note that there is no triangle on max-checkbox and radio
            if (options.showArrow) {
                var arrow = $('<div>').addClass("formErrorArrow");

                switch (options.promptPosition) {
                    case "bottomLeft":
                    case "bottomRight":
                        prompt.find(".formErrorContent").before(arrow);
                        arrow.addClass("formErrorArrowBottom").html('<div class="line1"><!-- --></div><div class="line2"><!-- --></div><div class="line3"><!-- --></div><div class="line4"><!-- --></div><div class="line5"><!-- --></div><div class="line6"><!-- --></div><div class="line7"><!-- --></div><div class="line8"><!-- --></div><div class="line9"><!-- --></div><div class="line10"><!-- --></div>');
                        break;
                    case "topLeft":
                    case "topRight":
                        arrow.html('<div class="line10"><!-- --></div><div class="line9"><!-- --></div><div class="line8"><!-- --></div><div class="line7"><!-- --></div><div class="line6"><!-- --></div><div class="line5"><!-- --></div><div class="line4"><!-- --></div><div class="line3"><!-- --></div><div class="line2"><!-- --></div><div class="line1"><!-- --></div>');
                        prompt.append(arrow);
                        break;
                }
            }
            
			prompt.click(function(e) { $this._closePrompt();$this.campoUser.focus();});
            this.prompt = prompt;
            $("body").append(prompt);

            var pos = $this._calculatePosition($(this.campoUser), prompt, options);
            prompt.css({
                "top": pos.callerTopPosition,
                "left": pos.callerleftPosition,
                "marginTop": pos.marginTopSize,
                "opacity": 0
            });

            return prompt.animate({
                "opacity": 0.87
            });

        },
        _calculatePosition: function(field, promptElmt, options) {
			if(this.a_format == 'radio' || this.a_format == 'checks' || this.a_format == 'ckeditor') {
				// uso el label
				field = $('#L__'+this.memNameForLabel);
			}
            var promptTopPosition, promptleftPosition, marginTopSize;
            var fieldWidth = field.width();
            var promptHeight = promptElmt.height();
			
            var offset = field.offset();
            if(offset == null) alert(this.a_name);
            promptTopPosition = offset.top;
            promptleftPosition = offset.left;
            marginTopSize = 0;

            switch (options.promptPosition) {

                default:
                case "topRight":
                    promptleftPosition += fieldWidth - 25;
                    promptTopPosition += -promptHeight;
                    break;
                case "topLeft":
                    promptTopPosition += -promptHeight - 10;
                    break;
                case "centerRight":
                    promptleftPosition += fieldWidth + 13;
                    break;
                case "bottomLeft":
                    promptTopPosition = promptTopPosition + field.height() + 15;
                    break;
                case "bottomRight":
                    promptleftPosition += fieldWidth - 25;
                    promptTopPosition += field.height() + 5;
            }

            return {
                "callerTopPosition": promptTopPosition + "px",
                "callerleftPosition": promptleftPosition + "px",
                "marginTopSize": marginTopSize + "px"
            };
        }
  
});



/****************************************************
 * FormCallbacks
 ****************************************************/

/**
 * FormCallbacks
 * 
 * @param string nombre del formulario
 */
var FormCallbacks = Class.extend({
  init: 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;
   },
   
   setRequired: function(formElementName,req) {
		this.configMembers[formElementName].setRequired(req);
   },
   
   setValid: function(formElementName) {
		this.configMembers[formElementName].showResponse('OKY');
   },
   
   validateMember: function(formElementName) {
		this.configMembers[formElementName].validateInServer();
   },
   
   observeForm: function() {
		// los elementos se 'observan' ellos mismos
		return;
   },
   validateInServerForm: function(regMatch) {
		var valSerialize = '';
		var $this = this;
		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 += this.configMembers[i].onSubmitMember();
			
			var dataMember = {};
			$.each(['a_tipo','a_format','a_required','a_title','a_accesibleVal','a_validateFunc'], function(k,v) {
				dataMember[v] = $this.configMembers[i][v];
			});
			
			result[i] = dataMember;
		}
		
		var valsForm = $('#f').serialize();
		var vals = $.toJSON(result);
		var params = {} ;
		params.accionJS = 'validaForm';
		params.config = vals;
		var urlString = valsForm + '' + valSerialize + '&' + $.param(params);
		// alert(urlString);
		// params += valSerialize;
		$.ajax({
			type: "POST",
			url: DL_WEB_ROOT+'utilidades/validator.php',
			data: urlString,
			dataType : 'json',
			success: function(msg){
				// alert( "Data Saved: " + msg );
				//$this.showResponse(msg);
				var hasError = false;
				for (var i in msg) {
					var res = msg[i];
					$this.configMembers[i].showResponse(res);
					if(res != 'OKY' && res.substr(0,9) != "##alert##"){ 
						hasError = true;
					}
				}
				if(hasError){
					DL_hideGrowlMessage();
					alertaWin(MENSAJES['error_form']);
				}else{
					s.form.submit();
				}
			}
		});
   }
});


/****************************************************
 * MISC
 ****************************************************/
///////////////////////////////////////////////////////////////////////////
// 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[]'){
		var mem = (tbox.id);
		oFormCallbacks.setValid(mem);
	}else{
		var mem = (fbox.id);
		oFormCallbacks.validateMember(mem); // hace un bucle??
	}
}


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
///////////////////////////////////////////////////////////////////////////

/**
 * 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 to_permalink(camposArr,permaFieldId) {
	var str = '';
	for ( i = 0; i < camposArr.length; i++ ) {
		if(i>0) str += ' ';
		str += $('#'+camposArr[i]).val();
	}
	var params = { accion: 'toPermalink',q:str };
	var urlString = $.param(params);
	$.ajax({
			type: "POST",
			url: DL_WEB_ROOT+'utilidades/ctrl_XMLHttpRequest.php',
			data: urlString,
			dataType : 'html',
			success: function(msg){
				// alert( "Data Saved: " + msg );
				$('#'+permaFieldId).val(msg);
				oFormCallbacks.setValid(permaFieldId);
			}
		});
}

// creamos el objeto
var oFormCallbacks = new FormCallbacks('f');

var isSafari = (/Konqueror|Safari|KHTML/.test(navigator.userAgent));
$(function(){
	var selPerPage = '<select id="regsPerPage" name="regsPerPage" title="'+MENSAJES['registros_por_pagina']+'">';
			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>';
	$("#contPageListJS").append(selPerPage);
	$('#regsPerPage').val($('#perPage').val());

	$("#regsPerPage").change(function(){$('#perPage').val($(this).val());document.f.submit();});		
	// $( "#regsPerPage" ).tooltip();
});

function goPaginatorPage(regNum)
{
	if(document.f){
		document.f['regIni'].value = regNum;
		document.f.submit();
		return false;
	}
}

$(function(){
	$('.accesibleVal').focus(function() {
		var input = $(this);
		if (input.val() == $(this).attr('startVal')) {
			input.val('');
		}
	}).blur(function() {
		var input = $(this);
		if(!$(this).attr('startVal')) $(this).attr('startVal',input.val());
		if (input.val() == '' || input.val() == $(this).attr('startVal')) {
			input.val($(this).attr('startVal'));
		}
	}).blur();
	
	$(".zebra tr").mouseover(function(){$(this).addClass("ruled");}).mouseout(function(){$(this).removeClass("ruled");});
	$(".zebra tr:even").addClass("par");
	$(".datepicker").datepicker("option",$.datepicker.regional[idiomaJs]);
	$(".datepicker").datepicker({dateFormat:'dd-mm-yy',firstDay: 1 });
	
	$('#showBuscar').click(function() {
		 $('#cajaSearch').slideToggle('fast');
	});
	DL_messageInfo();
});


