	//---------------------------------------------------------------------------------------------------------
	// 20/Octubre/2014
	// Versión 1.0 Script que se cargará SIEMPRE al cargarse la página web
	//---------------------------------------------------------------------------------------------------------
	// 28/Octubre/2014
	// Versión 1.1 Añadimos la función que envía una consulta por post a una web y devuelve el resultado
	//---------------------------------------------------------------------------------------------------------
	// 18/Marzo/2015
	// Versión 1.2 Se añade la función que te devuelve el objeto html inmediátamente anterior al script desde el que se llama
	//---------------------------------------------------------------------------------------------------------
	// 14/Noviembre/2016
	// Versión 1.3 Añadimos una función que corrige la posición de los elementos en pantalla para que no se salgan de la misma
	//---------------------------------------------------------------------------------------------------------
	// 24/Noviembre/2016
	// Versión 1.4 Añadimos una función que recarga los scripts que hayan sido cargados del DOM
	//---------------------------------------------------------------------------------------------------------
/*-----------------------------------------------------------------------*/
/*-----------------------------Funciones varias--------------------------*/
/*-----------------------------------------------------------------------*/
	function limpiar_texto(texto_a_limpiar){
		var acentos = "ÃÀÁÄÂÈÉËÊÌÍÏÎÒÓÖÔÙÚÜÛãàáäâèéëêìíïîòóöôùúüûÇç _";
		var original = "AAAAAEEEEIIIIOOOOUUUUaaaaaeeeeiiiioooouuuucc--";
		for (var i=0; i<acentos.length; i++) {
			texto_a_limpiar = replaceAll(texto_a_limpiar, acentos.charAt(i), original.charAt(i));
		}
		return(texto_a_limpiar);
	}
	
	//Estas dos funciones son para poder hacer replaceALl
	function escapeRegExp(string) {
		return string.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
	}
	function replaceAll(string, find, replace) {
		return string.replace(new RegExp(escapeRegExp(find), 'g'), replace);
	}

//-------------------------------------------------------------------------------------
// comprobamos si un elemento es visible o no
//-------------------------------------------------------------------------------------
(function($){

    /**
     * Copyright 2012, Digital Fusion
     * Licensed under the MIT license.
     * http://teamdf.com/jquery-plugins/license/
     *
     * @author Sam Sehnert
     * @desc A small plugin that checks whether elements are within
     *       the user visible viewport of a web browser.
     *       can accounts for vertical position, horizontal, or both
     */
    var $w=$(window);
    $.fn.visible = function(partial,hidden,direction,container){

        if (this.length < 1)
            return;
	
	// Set direction default to 'both'.
	direction = direction || 'both';
	    
        var $t          = this.length > 1 ? this.eq(0) : this,
						isContained = typeof container !== 'undefined' && container !== null,
						$c				  = isContained ? $(container) : $w,
						wPosition        = isContained ? $c.position() : 0,
            t           = $t.get(0),
            vpWidth     = $c.outerWidth(),
            vpHeight    = $c.outerHeight(),
            clientSize  = hidden === true ? t.offsetWidth * t.offsetHeight : true;

        if (typeof t.getBoundingClientRect === 'function'){

            // Use this native browser method, if available.
            var rec = t.getBoundingClientRect(),
                tViz = isContained ?
												rec.top - wPosition.top >= 0 && rec.top < vpHeight + wPosition.top :
												rec.top >= 0 && rec.top < vpHeight,
                bViz = isContained ?
												rec.bottom - wPosition.top > 0 && rec.bottom <= vpHeight + wPosition.top :
												rec.bottom > 0 && rec.bottom <= vpHeight,
                lViz = isContained ?
												rec.left - wPosition.left >= 0 && rec.left < vpWidth + wPosition.left :
												rec.left >= 0 && rec.left <  vpWidth,
                rViz = isContained ?
												rec.right - wPosition.left > 0  && rec.right < vpWidth + wPosition.left  :
												rec.right > 0 && rec.right <= vpWidth,
                vVisible   = partial ? tViz || bViz : tViz && bViz,
                hVisible   = partial ? lViz || rViz : lViz && rViz,
		vVisible = (rec.top < 0 && rec.bottom > vpHeight) ? true : vVisible,
                hVisible = (rec.left < 0 && rec.right > vpWidth) ? true : hVisible;

            if(direction === 'both')
                return clientSize && vVisible && hVisible;
            else if(direction === 'vertical')
                return clientSize && vVisible;
            else if(direction === 'horizontal')
                return clientSize && hVisible;
        } else {

            var viewTop 				= isContained ? 0 : wPosition,
                viewBottom      = viewTop + vpHeight,
                viewLeft        = $c.scrollLeft(),
                viewRight       = viewLeft + vpWidth,
                position          = $t.position(),
                _top            = position.top,
                _bottom         = _top + $t.height(),
                _left           = position.left,
                _right          = _left + $t.width(),
                compareTop      = partial === true ? _bottom : _top,
                compareBottom   = partial === true ? _top : _bottom,
                compareLeft     = partial === true ? _right : _left,
                compareRight    = partial === true ? _left : _right;

            if(direction === 'both')
                return !!clientSize && ((compareBottom <= viewBottom) && (compareTop >= viewTop)) && ((compareRight <= viewRight) && (compareLeft >= viewLeft));
            else if(direction === 'vertical')
                return !!clientSize && ((compareBottom <= viewBottom) && (compareTop >= viewTop));
            else if(direction === 'horizontal')
                return !!clientSize && ((compareRight <= viewRight) && (compareLeft >= viewLeft));
        }
    };
	//Añadimos una función que nos dice si un elemento tiene o on un atributo:
	$.fn.hasAttr = function(attr) { var attribVal = this.attr(attr); return (attribVal !== undefined) && (attribVal !== false); };
})(jQuery);

/*-----------------------------------------------------------------------*/
/*-----------------------Copiar CSS entre elementos----------------------*/
/*-----------------------------------------------------------------------*/
(function($) {
	$.fn.copyCSS = function (source) {
		var dom = $(source).get(0);
		var dest = {};
		var style, prop;
		if (window.getComputedStyle) {
			var camelize = function (a, b) {
					return b.toUpperCase();
			};
			if (style = window.getComputedStyle(dom, null)) {
				var camel, val;
				if (style.length) {
					for (var i = 0, l = style.length; i < l; i++) {
						prop = style[i];
						camel = prop.replace(/\-([a-z])/, camelize);
						val = style.getPropertyValue(prop);
						dest[camel] = val;
					}
				} else {
					for (prop in style) {
						camel = prop.replace(/\-([a-z])/, camelize);
						val = style.getPropertyValue(prop) || style[prop];
						dest[camel] = val;
					}
				}
				return this.css(dest);
			}
		}
		if (style = dom.currentStyle) {
			for (prop in style) {
				dest[prop] = style[prop];
			}
			return this.css(dest);
		}
		if (style = dom.style) {
			for (prop in style) {
				if (typeof style[prop] != 'function') {
					dest[prop] = style[prop];
				}
			}
		}
		return this.css(dest);
	};
})(jQuery);
/* Modo de uso:
	$(div2).copyCSS(div1);
*/

// jquery toggle whole attribute
  $.fn.toggleAttr = function(attr, val) {
    var test = $(this).attr(attr);
    if ( test ) { 
      // if attrib exists with ANY value, still remove it
      $(this).removeAttr(attr);
    } else {
      $(this).attr(attr, val);
    }
    return this;
  };

  // jquery toggle just the attribute value
  $.fn.toggleAttrVal = function(attr, val1, val2) {
    var test = $(this).attr(attr);
    if ( test === val1) {
      $(this).attr(attr, val2);
      return this;
    }
    if ( test === val2) {
      $(this).attr(attr, val1);
      return this;
    }
    // default to val1 if neither
    $(this).attr(attr, val1);
    return this;
  };

function anotarLog(cadena){
	var capaLog = $("#log");
	if (capaLog.length > 0){

		var texto = capaLog.html();
		if (texto != ""){
			texto += "\n";
		}

		capaLog.html(texto + cadena);
	}
}
/*-----------------------------------------------------------------------*/
/*--------------------Ejecutar consulta a un fichero php-----------------*/
/*-----------------------------------------------------------------------*/
function realizar_solicitud(url, parametros, proceso, xml){
	if (typeof XMLHttpRequest === "undefined") {
		XMLHttpRequest = function () {
		try {
			return new ActiveXObject("Msxml2.XMLHTTP.6.0");
		}
		catch (e) {antoarLog("Msxml2.XMLHTTP.6.0 No soportado.\n" + e.message);}
		try {
			return new ActiveXObject("Msxml2.XMLHTTP.3.0");
		}
		catch (e) {antoarLog("Msxml2.XMLHTTP.3.0 No soportado.\n" + e.message);}
		try {
			return new ActiveXObject("Microsoft.XMLHTTP");
		}
		catch (e) {antoarLog("Microsoft.XMLHTTP No soportado.\n" +  e.message);}
		
		throw new Error("This browser does not support XMLHttpRequest.");
	  };
	}

	var http = new XMLHttpRequest();
	xml = (xml == null) ? 0 : xml;
	proceso = (proceso == null) ? function(){} : proceso;
	//anotarLog("abrimos: " + url);
	try {
		//Abrimos la URL
		http.open("POST", url, true);
	}catch (e) {antoarLog("Error al abrir la página " + url + ".\n" + e.message);}
	try {
		//Modificamos las cabeceras del envío
		http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	}catch (e) {antoarLog("Error al enviar el header.\n" + e.message);}
	//Le asignamos el listener para cuando se realice el enío
	try {
	http.onreadystatechange = function() {
		anotarLog("readyState = " + http.readyState + " status = " + http.status == 200);
		if(http.readyState == 4 && http.status == 200) {
			/*anotarLog("cadena: " + JSON.stringify(http));
			anotarLog("cadena: " + JSON.stringify(document.cookie));
			*/
			if (xml){
				proceso(http.responseXML);
			}else{
				proceso(http.responseText);
			}
		}
	};
	}catch (e) {antoarLog("Error al obtener el contenido.\n" + e.message);}
		anotarLog("Enviamos los parametros: " + parametros);
	try{
		http.send(parametros);
	}catch(e){anotarLog("Error al enviar los parametros " + e.message)};
}

/*-----------------------------------------------------------------------*/
/*--------------- Ponemos y quitamos la sombra de un elemento------------*/
/*-----------------------------------------------------------------------*/
function poner_sombra(elemento){
	if (elemento != null){
		elemento.css({
			"-webkit-box-shadow": "0px 0px 10px 2px rgba(255, 0, 0, 0.75)",
			"-moz-box-shadow": "0px 0px 10px 2px rgba(255, 0, 0, 0.75)",
			"box-shadow": "0px 0px 10px 2px rgba(255, 0, 0, 0.75)"
		});
	}
}

function quitar_sombra(elemento){
	if (elemento != null){
		elemento.css({
			"-webkit-box-shadow": "",
			"-moz-box-shadow": "",
			"box-shadow": ""
		});
	}
}

/*-------------------------------------------------------------------------------------------------------*/
/*--------------- Modificamos los prototipos de la clase string para que admita justificacion------------*/
/*-------------------------------------------------------------------------------------------------------*/
function leftJustify(cadena, length, char){
	cadena = String(cadena);
	if (arguments.length < 3) char = " ";
    var fill = [];
    while ( fill.length + cadena.length < length ) {
      fill[fill.length] = char;
    }
    return cadena + fill.join('');
}
function rightJustify(cadena, length, char){
	cadena = String(cadena);
	if (arguments.length < 3) char = " ";
    var fill = [];
    while ( fill.length + cadena.length < length ) {
      fill[fill.length] = char;
    }
    return fill.join('') + cadena;
}
/*-------------------------------------------------------------------------------------------------------*/
/*--------------- Modificamos los prototipos de la clase string para que admita justificacion------------*/
/*-------------------------------------------------------------------------------------------------------*/

/*-------------------------------------------------------------------------------------------------------*/
/*--------------- Obtención del objeto inmediatamente anterior al script llamador de la misma------------*/
/*-------------------------------------------------------------------------------------------------------*/
function getLastHtmlObject(id){
	//Vamos a tener en cuenta el ID para cargar los elementos
	var scripts = document.getElementsByTagName( 'script' );
	//Si hemos recibido un ID filtramos
	if (id != null){
		scripts = $(scripts).filter("#" + id);
	}
	var thisScriptTag_pass = scripts[ scripts.length - 1 ];
	return($(thisScriptTag_pass).prev());
}

function getPreviousHtml(){	//==> No se puede utilizar dentro de eventos
	return($(document.currentScript).prev());
}

function getParentHtml(old_method){	//==> No se puede utilizar dentro de eventos
	if (old_method != null){
		var scripts = document.getElementsByTagName( 'script' );
		var thisScriptTag_pass = scripts[ scripts.length - 1 ];
		return($(thisScriptTag_pass).parent());
	}else{
		console.log(document.currentScript);
		return($(document.currentScript).parent());
	}
}

/*-------------------------------------------------------------------------------------------------------*/
/*--------------- Obtención del objeto inmediatamente anterior al script llamador de la misma------------*/
/*-------------------------------------------------------------------------------------------------------*/

/*-------------------------------------------------------------------------------------------------------*/
/*---- Redirección javascript que tiene en cuenta si estamos en IE8 o no, paramantener el httreferer-----*/
/*-------------------------------------------------------------------------------------------------------*/
function redirect(url) {
	var ua = navigator.userAgent.toLowerCase(),
	isIE = ua.indexOf('msie') !== -1,
	version = parseInt(ua.substr(4, 2), 10);

	// Internet Explorer 8 e inferior
	if (isIE && version < 9) {
		var link = document.createElement('a');
		link.href = url;
		document.body.appendChild(link);
		link.click();
	}else {
		//Resto de navegadores
		window.location.href = url;
	}
}
/*-------------------------------------------------------------------------------------------------------*/
/*---- Redirección javascript que tiene en cuenta si estamos en IE8 o no, paramantener el httreferer-----*/
/*-------------------------------------------------------------------------------------------------------*/

/*-------------------------------------------------------------------------------------------------------*/
/*--------------------------------------- Codificamos en UTF8 -------------------------------------------*/
/*-------------------------------------------------------------------------------------------------------*/
function utf8_encode(argString) {
  //  discuss at: http://phpjs.org/functions/utf8_encode/
  // original by: Webtoolkit.info (http://www.webtoolkit.info/)
  // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  // improved by: sowberry
  // improved by: Jack
  // improved by: Yves Sucaet
  // improved by: kirilloid
  // bugfixed by: Onno Marsman
  // bugfixed by: Onno Marsman
  // bugfixed by: Ulrich
  // bugfixed by: Rafal Kukawski
  // bugfixed by: kirilloid
  //   example 1: utf8_encode('Kevin van Zonneveld');
  //   returns 1: 'Kevin van Zonneveld'

  if (argString === null || typeof argString === 'undefined') {
    return '';
  }

  // .replace(/\r\n/g, "\n").replace(/\r/g, "\n");
  var string = (argString + '');
  var utftext = '',
    start, end, stringl = 0;

  start = end = 0;
  stringl = string.length;
  for (var n = 0; n < stringl; n++) {
    var c1 = string.charCodeAt(n);
    var enc = null;

    if (c1 < 128) {
      end++;
    } else if (c1 > 127 && c1 < 2048) {
      enc = String.fromCharCode(
        (c1 >> 6) | 192, (c1 & 63) | 128
      );
    } else if ((c1 & 0xF800) != 0xD800) {
      enc = String.fromCharCode(
        (c1 >> 12) | 224, ((c1 >> 6) & 63) | 128, (c1 & 63) | 128
      );
    } else {
      // surrogate pairs
      if ((c1 & 0xFC00) != 0xD800) {
        throw new RangeError('Unmatched trail surrogate at ' + n);
      }
      var c2 = string.charCodeAt(++n);
      if ((c2 & 0xFC00) != 0xDC00) {
        throw new RangeError('Unmatched lead surrogate at ' + (n - 1));
      }
      c1 = ((c1 & 0x3FF) << 10) + (c2 & 0x3FF) + 0x10000;
      enc = String.fromCharCode(
        (c1 >> 18) | 240, ((c1 >> 12) & 63) | 128, ((c1 >> 6) & 63) | 128, (c1 & 63) | 128
      );
    }
    if (enc !== null) {
      if (end > start) {
        utftext += string.slice(start, end);
      }
      utftext += enc;
      start = end = n + 1;
    }
  }

  if (end > start) {
    utftext += string.slice(start, stringl);
  }

  return utftext;
}


/*-----------------------------------------------------------------------*/
/*----funciones a utilizar en la composición de las URLs de filtrado-----*/
/*-----------------------------------------------------------------------*/
	function componer_cadena_redirigir(currentURL){
		var newUrl = componer_cad_filtrado_final();
		//Por último hacemos el redirect
		redirect(currentURL + newUrl);
	}

	function componer_cad_filtrado_final(){
		var newUrl = "";
		newUrl = componer_cad_filtrado();
		//console.log("1.-" , newUrl);
		//aquí hay que añadir los filtrados de PVP si existen
		newUrl += componer_cad_filtrado_pvp();
		//console.log("2.-" , newUrl);
		//EL escaparate:
		newUrl += componer_cad_filtrado_escaparate()
		//console.log("3.-" , newUrl);
		newUrl += componer_cad_filtrado_edad()
		//console.log("4.-" , newUrl);
		//Si tenemos algo en la cadena de filtrado, entonces terminamos de compober newUrl
		if (newUrl != ""){
			//Aquí añadimos la página actual
			newUrl = "/filtrado/" + newUrl
		}
		return(newUrl);
	}

	function componer_cad_filtrado_pvp(){
		var cadena_filtro = "";
		var formulario = $("div.filtrado form.filtrado_pvp");
		if (formulario.length > 0){
			var desde = formulario.find("input[name='desde_pvp']").val();
			var hasta = formulario.find("input[name='hasta_pvp']").val();
			//Es posible que el "desde" y el "hasta" nos lo hayan puesto con comas, vamos a cambiarlos a .
			desde = desde.replace(",", ".");
			hasta = hasta.replace(",", ".");
			//Los pasamos a float
			desde = parseFloat(desde);
			hasta = parseFloat(hasta);
			if ( (desde <= hasta) && (desde > 0 || hasta > 0) ){
				cadena_filtro = "*pvp:" + desde + "-" + hasta;
			}
		}
		return(cadena_filtro);
	}

	function componer_cad_filtrado(){
		var cadena_filtrado = "";
		var array_campos = new Array();
		//objetoObjetivo.find("input[type=checkbox]:checked").each(function(){
		$("div.filtrado form[class^='filtrado_'] input[type=checkbox]:checked").each(function(){
			//sacamos el tipo de filtrado
			var campo_filtrado = $(this).prop("class");
			campo_filtrado = campo_filtrado.replace("filtrar_", "");
			//Nos aseguramos de que la clave exista
			array_campos[campo_filtrado] = (campo_filtrado in array_campos)? array_campos[campo_filtrado] : "";
			//Añadimos a la clave el elemento. Si es un check de stock, no lleva ID, así que el valor lo metemos a mano
			if (campo_filtrado == "stock_disponible"){
				array_campos[campo_filtrado] = "disponible";
			}else{
				//Si el elemento ya contiene algo, le añadimos un guión
				array_campos[campo_filtrado] += (array_campos[campo_filtrado] != "")? "-" : "";
				array_campos[campo_filtrado] += $(this).prop("id").replace("check_", "");
			}
		});
		//Ahora recorremos el array de campos para generar la cadena de filtrado
		for (var i in array_campos){
			cadena_filtrado += (cadena_filtrado != "")? "*" : "";
			cadena_filtrado += i + ":" + array_campos[i];
		}
		
		//Ahora vamos a controlar, agrupando por clases, las que no tienen nada seleccionado:
		var obj = {};
		$("div.filtrado form[class^='filtrado_'] input[type=checkbox]").not(":checked").each(function () {
			$.each((this.className || '').split(/\s+/), function (i, v) {
				obj[v] = true;
			});
		});
		var clases = $.map(obj, function (val, key) {
			return key == '' ? undefined : key;
		});
		//Clases es un array que contiene aquellas diferentes clases de este  tipo de filtrado que no están chequeadas. Ahora vamos a ver si de cada una de ellas existen chequeadas
		//Si no existen entonces añadimos este filtrado vacío.
		for (var i in clases){
			//Comprobamos si hay alguno chequeado:
			if ($("." + clases[i] + ":checked").length == 0){
				cadena_filtrado += (cadena_filtrado != "")? "*" : "";
				cadena_filtrado += clases[i].replace("filtrar_", "") + ":";
			}
		}
		//console.log(classes);
		//En clases tenemos 
		
		return(cadena_filtrado);
	}
	
	function componer_cad_filtrado_escaparate(){
		var cadena_filtrado = "";
		var valor_escaparate = $("select[name='filtro_escaparate_busqueda_simple']").val();
		if (valor_escaparate > 0){
			cadena_filtrado = "*escaparate:" + valor_escaparate;
		}
		return(cadena_filtrado);
	}
	
	function componer_cad_filtrado_edad(){
		var cadena_filtrado = "";
		var valor_escaparate = $("select[name='filtrar_edad']").val();
		if (valor_escaparate != null){
			cadena_filtrado = "*edad:" + valor_escaparate;
		}
		return(cadena_filtrado);
	}
/*-----------------------------------------------------------------------*/
/*----funciones a utilizar en la composición de las URLs de filtrado-----*/
/*-----------------------------------------------------------------------*/



/*-----------------------------------------------------------------------*/
/*---------------------Lupa en la portada del producto-------------------*/
/*-----------------------------------------------------------------------*/

//Vamos a recibir una imagen (su clase o us ID) y crearemos la imagen en grande por encima y transparente
function armiLupa(capa_origen, ruta_imagen){
	var id_lupa = randomId();
	var id_lupaTrans = randomId();
	var lupa =  function(){
		var estiloVisor = '';
		$(capa_origen).each(function(){
			if (ruta_imagen != "" ){
				//Vamos a ver donde se ubica la imagen ampliada
				var posicion = $(this).position();
				posicion.left += $(this).parent().width();
				var ancho_imagen = $(this).width();
				var alto_imagen = $(this).height();
				var cad_img = '<img src="' + ruta_imagen + '" style="width:auto; height:auto; position:absolute;" />';
				var capa_destino = '<div id="' + id_lupa + '" class="lupa" style="display:none; position:absolute;" ></div>';
				var capaTrans = '<div id="' + id_lupaTrans + '" class="LupaTrans" style="display:none;position:absolute;"></div>';
				var anchoTrans = 0;
				var altoTrans = 0;
				capa_destino = $(capa_destino).html(cad_img);
				capaTrans = $(capaTrans);
				$("body").append($(capa_destino));
				$("body").append($(capaTrans));
				//Hemos dado la orden de q se cargue una imagen, vamos a poner un onload
				$(capa_destino).find("img").on('load',function(event){
					//Tener en cuenta el scroll actual
					//$(capa_destino).css("top", $(window).scrollTop() + "px");
					if ($(capa_destino).is(":hidden")){
						$(capa_destino).show();
					}
					if ($(capa_destino).is(":visible")){
						$(capa_destino).hide();
					}
					//Hay que cargar la ruta de la imagen e insertar justo después del enlace dicha imagen
					$(capa_origen).mousemove(function(event){
						mueveCapa(event);
					});
					
					$(capaTrans).on("mousemove", function(event){
						mueveCapa(event);
					});
					$(capaTrans).on("mouseout", function(event){
						//Si el ratón está fuera de la capaOrigen, entonces hay que ver si se oculta
						mueveCapa(event);
					});
					$(capa_origen).on("mouseout", function(event){
						//Si el ratón está fuera de la capaOrigen, entonces hay que ver si se oculta
						$(capaTrans).hide();
						$(capa_destino).hide();
					});
					$(window).on("scroll", function(event){
						//Controlar scroll
						$(capa_destino).css("top", $(window).scrollTop() + "px");
					});
					function mueveCapa(event){
						//Calculamos el tamaño de la capa transparente
						anchoTrans = $(capaTrans).outerWidth();
						altoTrans = $(capaTrans).outerHeight();
						//Calculamos la posición del ratón y de la imagen
						posicion = $(capa_origen).offset();
						var posX = event.pageX - posicion.left;
						var posY = event.pageY - posicion.top;
						if ( (posX < 0) || (posY < 0 ) ){
							//console.log("pasa")
							$(capaTrans).hide();
							$(capa_destino).hide();
						}else if ((posX > $(capa_origen).outerWidth()) || (posY > $(capa_origen).outerHeight() )){
							//console.log("pasa2")
							$(capaTrans).hide();
							$(capa_destino).hide();
						}else{
							//console.log("pasa3")
							$(capaTrans).show();
							$(capa_destino).show();
						}
						
						//Calculamos la posición final de la capa transparente
						var xTrans = event.pageX - (anchoTrans/2);
						var yTrans = event.pageY - (altoTrans/2);
						//Si nos salimos, hacemos la corrección
						xTrans = Math.max(xTrans, posicion.left);
						yTrans = Math.max(yTrans, posicion.top);
						
						xTrans = Math.min(xTrans, posicion.left + $(capa_origen).outerWidth() - anchoTrans);
						yTrans = Math.min(yTrans, posicion.top + $(capa_origen).outerHeight() - altoTrans);
						
						$(capaTrans).css({
							"left" : xTrans + "px",
							"top" : yTrans + "px"
						});
						
						escalaImagenX = $(capa_destino).find("img").width() / $(capa_origen).width();
						escalaImagenY = $(capa_destino).find("img").height() / $(capa_origen).height();
						
						var posicionXFinal = -1 * ((xTrans - posicion.left) * escalaImagenX);
						var posicionYFinal = -1 * ((yTrans - posicion.top) * escalaImagenY);
						$(capa_destino).find("img").css("left", posicionXFinal + "px");
						$(capa_destino).find("img").css("top", posicionYFinal + "px");
					}
					
					//Por último redimensionamos la lupa y su conteindo:
					redimensiona_lupa();
				});
			}
		});
	};

	function redimensiona_lupa(){
		var anchoLupa = $("#" + id_lupa).width();
		var altoLupa = $("#" + id_lupa).height();
		var anchoImagen = $(capa_origen).width();
		var altoImagen = $(capa_origen).height();
		var propX = anchoImagen / anchoLupa;
		var propY = altoImagen / altoLupa;
		var escala = Math.max(propX, propY);
		//la escala es la cuarta parte de la imagen SIEMPRE
		escala /= 4;
		var visorX = anchoLupa * escala;
		var visorY = altoLupa * escala;
		$("#" + id_lupaTrans).css("width", visorX + "px");
		$("#" + id_lupaTrans).css("height", visorY + "px");
		//Ahora redimensionamos la imagen en la misma proporción:
		//para coger las dimensiones de la imagen, necesito mostrarla:
		anchoImagen /= (escala);
		altoImagen /= (escala);
		$("#" + id_lupa).find("img").css("width", anchoImagen + "px");
		$("#" + id_lupa).find("img").css("height", altoImagen + "px");
	}
	
	//$(window).on("load",function(){
		lupa();
	//});
	$(window).on("resize", function(){
		redimensiona_lupa();
	});
}
function setPropiedadExtra(data,capa){
	var obj = JSON.parse(data);
	for(var key in obj){
		$(capa + ' .' + key).html(obj[key]);
	}
	
}
/*-----------------------------------------------------------------------*/
/*--------------Personalizamos los errores de los formularios------------*/
/*-----------------------------------------------------------------------*/
/*
;(function(){
	var form = document.querySelector('form');
	form.addEventListener( 'invalid',function(event){
		event.preventDefault();
		console.log("error");
	},true);
}());
*/

/*-----------------------------------------------------------------------*/
/*-------------- Corregimos la posición de un menú ul li ul  ------------*/
/*-----------------------------------------------------------------------*/
function corrigePosicionMenu(estiloPrimerUl, capaPadre){
	// estiloPrimerUl ==> puede ser "L" -> Izquierda, "C" -> Centrado, "R" -> Derecha. Por defecto será siempre "C"
	// capaPadre ==> Capa desde la que vamos a partir para hacer los recálculos sobre ".menu_escaparate"
	var estiloPrimerUl = (estiloPrimerUl == null ) ? "C" : estiloPrimerUl;
	var capaPadre =  (capaPadre == null ) ? "header" : capaPadre;
	$(capaPadre + " .menu_escaparates>ul>li>ul").each(function (index, element) {
		//recolocarUl($(this));
		//Aquí tenemos los primeros ul, que cuelgan a su vez de otros ul -> li
		//Vamos a colocar estos ul en su sitio en función del "estiloPrimerUl"
		var capaPadre = $(this).parent("li");
		var anchoPadre = capaPadre.outerWidth();
		var anchoElemento = $(this).outerWidth();
		//console.log($("body").width(), anchoElemento);
		//Si el estilo es "L", no hacemos nada, viene por defecto. Si es C hay que centrar la capa y con R se alinea al márgen derecho del padre:
		if (estiloPrimerUl == "C") {
			//El margen de esta capa es -(ancho padre / 2)
			$(this).css("margin-left", (anchoPadre - anchoElemento) / 2 + "px");
		} else if (estiloPrimerUl == "R") {
			$(this).css("margin-left", (anchoPadre - anchoElemento) + "px");
		}
		//Si después de alinear la capa, queda fuera de la pantalla, tenemos un problema
		var posicionElemento = $(this).offset().left;
		if (posicionElemento < 0){
			$(this).css("margin-left", posicionElement + "px");
		}else if ( (posicionElemento + anchoElemento) > $("body").width() ){
			$(this).css("margin-left", (anchoPadre - anchoElemento) + "px");
		}
		$(this).find("ul").each(function(index, element) {
			var capaPadre = $(this).parent("li");
			var anchoPadre = capaPadre.outerWidth();
			var anchoElemento = $(this).outerWidth();
			var posicionElemento = $(this).offset().left;
			if (posicionElemento < 0){
				$(this).css("margin-left", anchoPadre + "px");
			}else if ( (posicionElemento + anchoElemento) > $("body").width() ){
				$(this).css("margin-left", "-" + (anchoPadre + anchoElemento) + "px");
			}
		});
	});
}

/*-----------------------------------------------------------------------*/
/*---------- Recargamos los scripts para que sean interpretados  --------*/
/*-----------------------------------------------------------------------*/
function recargarScripts(capaOrigen){
	var listaOrigen = $(capaOrigen);
	if (listaOrigen.length > 0){
		var listaScripts = listaOrigen[0].getElementsByTagName("script");
		for (var i in listaScripts) {
			var elemento = listaScripts[i];
			if (elemento.src == ""){
				var newScript = document.createElement('script');
				var id = elemento.id;
				newScript.text = elemento.innerText;
				if (id != ""){
					newScript.id = id;
				}
				elemento.parentNode.insertBefore(newScript, elemento);
				elemento.remove();
			}
		}
	}
}

/*-----------------------------------------------------------------------*/
/*---------------------- generador de ids aleatorios  -------------------*/
/*-----------------------------------------------------------------------*/
function randomId() {
	return '_' + Math.random().toString(36).substr(2, 9);
};


function makeBackButtons(){
	$('div.volver').each(function(){
		var contenido = $(this).html().trim();
		if (contenido == ''){
			contenido = '<a class="home" href="' + document.referrer + '" title="Volver"> <span class="mdi mdi-chevron-left"></span><span class="title">Volver</span></a>';
			$(this).html(contenido);
		}
	});
}

/*-----------------------------------------------------------------------*/
/*------------------ codificar y descodificar en base64  ----------------*/
/*-----------------------------------------------------------------------*/
function b64EncodeUnicode(str) {
    // first we use encodeURIComponent to get percent-encoded UTF-8,
    // then we convert the percent encodings into raw bytes which
    // can be fed into btoa.
    return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
        function toSolidBytes(match, p1) {
            return String.fromCharCode('0x' + p1);
    }));
}


function b64DecodeUnicode(str) {
    // Going backwards: from bytestream, to percent-encoding, to original string.
    return decodeURIComponent(atob(str).split('').map(function(c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
    }).join(''));
}