jQuery.fn.extend({
    print: function() {
		if ($('#lda-print').length) return false;
        var cache = jQuery('body>*').addClass('lda-noprint');
        this.clone().appendTo('body').wrapAll('<div id="lda-print"></div>');
		window.print();
		setTimeout(function() {
			cache.removeClass('lda-noprint');
			jQuery('#lda-print').remove();
		}, 2000);
		return this;
    }
});

// -------------------------------------------------------------- utilizacion de cookies
function getCookie( name ) {
	var start = document.cookie.indexOf( name + "=" );
	var len = start + name.length + 1;
	if ( ( !start ) && ( name != document.cookie.substring( 0, name.length ) ) ) {
		return null;
	}
	if ( start == -1 ) return null;
	var end = document.cookie.indexOf( ';', len );
	if ( end == -1 ) end = document.cookie.length;
	return unescape( document.cookie.substring( len, end ) );
} // function

function setCookie( name, value, expires, path, domain, secure ) {
	var today = new Date();
	today.setTime( today.getTime() );
	if ( expires ) {
		expires = expires * 1000 * 60 * 60 * 24;
	}
	var expires_date = new Date( today.getTime() + (expires) );
	document.cookie = name+'='+escape( value ) +
		( ( expires ) ? ';expires='+expires_date.toGMTString() : '' ) + //expires.toGMTString()
		( ( path ) ? ';path=' + path : '' ) +
		( ( domain ) ? ';domain=' + domain : '' ) +
		( ( secure ) ? ';secure' : '' );
} // function

function deleteCookie( name, path, domain ) {
	if ( getCookie( name ) ) document.cookie = name + '=' +
			( ( path ) ? ';path=' + path : '') +
			( ( domain ) ? ';domain=' + domain : '' ) +
			';expires=Thu, 01-Jan-1970 00:00:01 GMT';
} // function

// ----------------------------------- plugin de jQuery para suavizar enlaces con anchor
jQuery.fn.extend({
	smoothAnchor: function(duration, easing, callback) {
		var $t = this.eq(0),
			elem = $.layout.name == 'webkit' ? 'body' : 'html';
		$(elem).animate({scrollTop: $t.offset().top}, duration, easing, callback);
		return this;
	}
});

// ---------------------- pasar a dos decimales y cambiar de puntos a comas en un numero 
Number.prototype.aPrecio = function() {
	var aNum = (this.toFixed(2)+'').split('.'),
		entero = aNum[0],
		i, l;
	// txtSeparadorMiles y txtSeparadorDecimales vienen de lang/.../texts.js
	aNum[0] = '';
	aNum[1] = ['<small>', aNum[1], '</small>'].join('');
	for (i=0,l=entero.length;i<l;i++) {
		if (i && i%3===0) aNum[0]= txtSeparadorMiles + aNum[0];
		aNum[0] = entero.charAt(l-i-1) + aNum[0];
	}
	return aNum.join(txtSeparadorDecimales);
}

// -------------------------------------------------------------- Comprobar email valido
String.prototype.testEmail = function() {
	var reEmail = /^(?:\w+(-\w+)*\.?)*\w+@(?:\w+(-\w+)*\.)+\w+$/;
	return reEmail.test(this);
}

// -------------------------------------------------------- Comprobar documentos validos
String.prototype.testDNI = function() {
	var _t = this.toUpperCase(),
		reDNI = /\d{8}[A-Z]/,
		sCode = 'TRWAGMYFPDXBNJZSQVHLCKE';
	if (reDNI.test(_t) && sCode.charAt(parseInt(_t)%23) == _t.replace(/\d/g, '')) {
		return true;
	} else {
		return false;
	}
	
}
String.prototype.testNIE = function() {
	var _t = this.toUpperCase(),
		reNIE = /([A-Z])(\d{7}[A-Z])/,
		deltaChar = _t.charCodeAt(0) - 'X'.charCodeAt(0);
	return (_t.replace(reNIE, deltaChar + '$2')).testDNI();
}

// -------------------------------------------------------- Comprobar tarjetas de credito
String.prototype.testLuhn = function(){
	var number = this.replace(/\D/g, '');
	var number_length = number.length;
	var parity = number_length % 2;
	var total = 0;

	for (i = 0; i < number_length; i++) {
		var digit = number.charAt(i);
		if (i % 2 == parity) {
			digit = digit * 2;
			if (digit > 9) {
				digit = digit - 9;
			}
		}
		total = total + parseInt(digit);
	}
	if (total % 10 == 0) {
		return true;
	} else {
		return false;
	}
}
String.prototype.testVisa = function() {
	var cardNumber = this.replace(/(\d)([\s\-])(\d)/g, '$1$3');
	return /^4\d{12}(\d{3})?$/.test(cardNumber) && cardNumber.testLuhn();
}
String.prototype.testMasterCard = function() {
	var cardNumber = this.replace(/(\d)([\s\-])(\d)/g, '$1$3');
	return /^5[1-5]\d{14}$/.test(cardNumber) && cardNumber.testLuhn();
}
String.prototype.testAmericanExpress = function() {
	var cardNumber = this.replace(/(\d)([\s\-])(\d)/g, '$1$3');
	return /^3[47]\d{13}$/.test(cardNumber) && cardNumber.testLuhn();
}

// Extraer de un String todo lo anterior al primer  (para enlaces)
String.prototype.getAnchor = function() {
	var subS = this.substring(this.indexOf('#'));
	if (subS == this) subS = '';
	return subS;
}

// PREPARAMOS FUNCIONES PARA EL DATEPICKER
// extendemos el objeto String con la clase toDate, que devuelve un objeto Date 

if(lang == 'en') {
	dformat = 'mm/dd/yyyy';
	jqdformat = 'mm/dd/yy';
} else {
	dformat = 'dd/mm/yyyy';
	jqdformat = 'dd/mm/yy';
}  
String.prototype.toDate = function(f, modDia, modMes) {
	var f     = f || 'dd/mm/yyyy';
    var modDia= modDia || 0;
    var modMes= modMes || 0;
    var anyo  = this.substring(f.indexOf('y'), f.lastIndexOf('y') + 1);
    var mes   = parseInt(this.substring(f.indexOf('m'), f.lastIndexOf('m') + 1), 10) + modMes;
    var dia   = parseInt(this.substring(f.indexOf('d'), f.lastIndexOf('d') + 1), 10) + modDia;
    var fecha = new Date(anyo, mes-1, dia);
    return fecha;
}
Date.prototype.fechaLocal = function() {
	return this.toLocaleString().replace(/[0-2]?[0-9]\:.{5}/g, '');
}

Date.prototype.ddmmyyyy = function() {
	var dia = this.getDate()  < 10 ? '0'+this.getDate()  : this.getDate();
	var mes = (this.getMonth()+1) < 10 ? '0'+(this.getMonth()+1) : this.getMonth()+1;
	var fecha = [dia,'/',mes,'/',this.getFullYear()].join('');
	return fecha;
}

String.prototype.testDate = function(f) {
	var f = f || 'dd/mm/yyyy';
    f = f.replace(/([\/\-])/g, '\\$1');
    f = f.replace('dd', '(0?[1-9]|[12][0-9]|3[01])'); // dias
    f = f.replace('mm', '(0?[1-9]|1[0-2])'); // meses
    f = f.replace('yyyy', '(19|20)\\d{2}'); // anyos, solo para 1901 hasta 2099
    f = ['/\\b', f, '/'].join('');
    reFecha = eval(f);
    if (!reFecha.test(this) || this.substring(0, 2) != this.toDate().getDate()) {
        return false;
    } else {
        return true;
    }
}

$.datepicker.setDefaults( {
	yearRange :'-1:+2',
	changeFirstDay :false,
	minDate :'+0',
	showOn :'button',
	buttonImage :approot+'img/calendarIcon.gif',
	dateFormat : jqdformat
});

$('#ajaxSendToGPS a.boton').live('click', function() {
	var uri = $('#ajaxSendToGPS select').val(),
		popup;
	if (uri && uri != 0) {
		popup = window.open(uri, 'popupGps', 'width=800, height=450');
		popup.focus();
	}
});

/*
 * -------------------------------------------------------------- paneles genericos 
 * estilos asociados en css/comun.css (clases panel, shown, active y showPanel)
 */
var estadoPaneles;
try { estadoPaneles = eval(getCookie('estadoPaneles')) } catch(e) {};
estadoPaneles = estadoPaneles || {};

function inicPanels(scope) {
	var scope = scope || document,
		$a = $('a.showPanel', scope),
		$p = $('.panel', scope);
	
	$p.each(function(index) {
		var sAccion = estadoPaneles[this.id]===0 ? 'removeClass' : 'addClass',
			$thisA = $a.eq(index),
			$thisP = $p.eq(index),
			clasesOK = $thisA.filter('.active').length == $thisP.filter('.shown').length;
		
		// si tiene identificador actuamos segun lo almacenado en estadoPaneles o
		// si tiene las clases desemparejadas las quitamos (sAccion es 'removeClass')
		if (this.id || !clasesOK ) {
			$thisA[sAccion]('active');
			$thisP[sAccion]('shown');
		}
		// chivato para desarrollo en caso de error
		if (!clasesOK) {
			try {
				console.log('Error de emparejamiento de clases entre:');
				console.log($thisA.get(0));
				console.log($thisP.get(0));
			} catch(e) {}
		}
	});
}
// evento de click
$('a.showPanel').live('click', function() {
	var $a = $('a.showPanel'),
		$p = $('.panel'),
		index = $a.index(this);
	$a.eq(index).toggleClass('active');
	$p.eq(index).css('height','').slideToggle(400, function() {
		var $t = $(this);
		$t.toggleClass('shown').css({display:'', height:($.browser.msie && $t.css('position')=='static') ? '1%':''}); // height:1% para corregir bug IE
		if (this.id) {
			estadoPaneles[this.id] = $t.hasClass('shown') ? 1 : 0;
		}
	});
	return false;
});
// almacenar cookie
$(window).unload(function() {
	var aTemp = [];
	for (i in estadoPaneles) {
		aTemp.push('"'+i+'":'+estadoPaneles[i]);
	}
	setCookie('estadoPaneles', '({' +aTemp.join(',')+ '})', 7);
});
/*
 * --------------------------------------------------------- FIN: paneles genericos 
 */

// evento autoadjudicable de paneles conmutables (requiere relacion href->id
$('a.conmutador').live('click', function() {
	var enlace = $(this).toggleClass('active').attr('href');
	enlace = enlace.substring(enlace.lastIndexOf('#'));
	$(enlace).slideToggle('fast');
	return false;
});
$('a[rel=external]').live('click',function(){
	this.target='_blank';
});

// evento autoadjudicable de filas con un solo enlace
$('tr, li').live('click', function(evento) {
	var $a = $('a',this),
		pinch = evento.target;
	if ($a.closest('.clickMe').length && $a.length == 1 && pinch.tagName.toLowerCase() != 'a' && !$(pinch).parents('a').length) {
		document.location.href=$a.get(0).href;
	}
});


// evento autoadjudicable de pestanyas, requiere pasarle una HREF="#LOQUESEA"
$('.controlTabs li a').live('click',function() {
	var $t     = $(this).not('.active'),
		$a     = $t.closest('.controlTabs').find('li a[href*=#]'),
		$tabs  = $($a.map(function(){ return this.href.getAnchor() }).get().join(',')),
		$toShow= $(this.href.getAnchor()),
		$ul    = $toShow.parent('.tabList'), // solo aplicable en caso de existir listado (no es estrictamente necesario)
		vel    = 1000,
		targetH= 0;
	// si no hay objeto lo paramos todo
	if (!$t.length) return false;
	// reasignamos clases
	$a.removeClass('active');
	$t.addClass('active');
	// averiguamos la altura del elemento a mostrar
	targetH = $toShow.css({visibility:'hidden',display:'block'}).height()
	$toShow.css({visibility:'visible',display:'none'});
	if ($ul.length) {
		//forzamos que el $ul vaya a targetH
		$ul.css({
			overflow:'hidden',
			height:$ul.height()
		}).animate({height:targetH}, vel, function() {
			$ul.css({overflow:'', height:''});
		});
	}
	// ocultamos las que sean visibles y mostramos la que toca
	$tabs.filter(':visible').not(this.href.getAnchor()).hide('blind',{direction:'vertical'},vel);
	$toShow.show('blind',{direction:'vertical'},vel);
	return false;
});
$('a.closeTab').live('click',function() {
	// ocultamos las pestanas y asignamos la funcion closeTab de ser necesario
	// la unica condicion que se le pone al closeTab es que el primer elemento con identificador que encuentre en todos sus ancestros sea la propia pestana
	var id = $(this).closest('[id]').attr('id');
	$('#'+id).hide('blind',{direction:'vertical'},1000);
	$('a[href$=#'+id+']').removeClass('active');
});;

// inicializarPestanyas
function inicTabs(contexto) {
	var $li= $('.controlTabs li'),
		$a = $li.find('a'),
		$active = $li.find('a.active');
		
	if ($a.length && $li.length) {
		$($a.map(function(){
			return this.href.getAnchor()
		}).get().join(',')).hide(); // ocultamos las pestanas
		if ($active.length) {
			$($active.map(function(){
				return this.href.getAnchor()
			}).get().join(',')).show(); // si hay alguna activa la mostramos, faltaria mas
		}
	}
}

// Funciones de eventos y extensiones del DOM
function extenderClases(contexto) {
	// tablas y listados
	var $e = $('tr', contexto).children().add($('li', contexto));
	$e.filter(':odd').addClass('odd');
	$e.filter(':even').addClass('even');
	$e.filter(':first-child').addClass('first');
	$e.filter(':last-child').addClass('last');
	// inputs
	$('input', contexto).each(function() {
		$(this).addClass(this.type);
	});
	// eventos hover para MSIE6
	if ($.browser.msie && $.browser.version < 7) {
		$('tr, li', contexto).hover( function() { $(this).addClass('hover') }, function() { $(this).removeClass('hover') });
	}
}


function extenderEnlaces(contexto) {
	var $a = $('a', contexto)
	
	// evento autoadjudicable de enlaces de mostrar GPS
    $a.filter('.addToGPS').bind('click', function() {
        if (!this.asignadoFancyBox) {
            this.asignadoFanybox = true;
            $(this).fancybox({
                hideOnContentClick:false,
                frameWidth: 300,
                frameHeight: 230,
                padding: 15,
                overlayShow: false
            });
            $(this).click();
        }
        return false;
    });
	// imprimir divs
	$a.filter('.imprimirDiv').click(function() {
		var ids = '#' + $.trim(this.rel).split(' ').join(', #');
		$(ids).print();
		return false;
	});
	
	// crear formulario de envio de datos del buscador en el apartado Usted Quiso Decir...
	$('#ustedQuisoDecir a').click(function(){
		// si existen fechas se realiza el submit del formulario de busqueda con los valores dados por el link
		if ($('#fechaEntrada').val()!='' && $('#fechaSalida').val()!='') {
			$this = $(this);
			$buscador = $('#buscadorReservas');

			if ($this.attr('href').match('/hotel/')) {
				$('#destinoTipo').val('HOT');
			} else if ($this.attr('href').match('/poblacion/')) {
				$('#destinoTipo').val('CIU');
			} else if ($this.attr('href').match('/provincia/')) {
				$('#destinoTipo').val('PRO');
			}
			
			$('#destinoUrl').val($this.attr('href').substr($this.attr('href').lastIndexOf('/') + 1, $this.attr('href').length));
			$('#destinoCodigo').val($this.siblings('input[name=codigoSugerencia]').val());
			$('#oldDestino').val($this.text());
			$('#searchDestinoHotel').val($this.text());
			
			$buscador.submit();
			// anulamos el envio del link
			return false;
		}
	});
	
	// Galerias de FancyBox
	$('.fancyLinks a', contexto).fancybox({
		hideOnContentClick:false,
		padding: 15,
		frameWidth: $('#fancy_outer').data('cachewidth'),
		frameHeight: $('#fancy_outer').data('cacheheight'),
		overlayShow: true,
		overlayOpacity: 0.5,
		callbackOnShow: function() {
			var $in = $('#ajaxGaleria-interior'),
				nW  = $in.width() + 30,
				nH  = $in.height() + 30,
				$win = $(window);
			$('#fancy_outer').animate({
				width: nW + 'px',
				height: nH + 'px',
				left: ($win.width() - nW)/2 + 'px',
				top: ($win.height() - nH)/2 + $(document).scrollTop() + 'px'
			}, 600)
		}
	});

	// AutoSmooth
	$a.filter('.autoSmooth').click( function() {
		$(this.href.getAnchor()).smoothAnchor();
		return false;
	});

	// añadir a favoritos
	$a.filter('.addFavorites', contexto).click( function() {
        title = document.title;
        if (window.sidebar) { // Firefox
            window.sidebar.addPanel(title, window.location.href,"");
        } else if( window.external ) { // IE
            window.external.AddFavorite( window.location.href, title);
        } else {
            alert(txtBrowserNoSoportado);
        }
		return false;
	});

	// enlace a colectivo dentro de colectivos.resultados.inc.php
	$a.filter('.verColectivo', contexto).click( function() {
        $('#nombreColectivo').html($(this).html());
        $('#panelAutentificacion').addClass('shown').show();
        window.scrollTo(0, 0);
        $('input:text[name=login]').focus();
		return false;
	});

	// enlace a reservar dentro de listaHoteles.php y hotel.precios
	$a.filter('a[href*=/nuestros-hoteles/reservar/v/u/]', contexto).click( function() {
		if (!$('input[name=fechaEntrada]').val() ||	!$('input[name=fechaSalida]').val()) return;
		
        var urlDestino = this.href;
		var contexto = '#contenido-lateral';
        var pos = urlDestino.indexOf('/u/');
        if (pos > 0) {
            urlDestino = urlDestino.substring(pos + 3);
        } else {
            urlDestino = '';
        }
        $('input:hidden[name=destinoTipo]', contexto).val('HOT');
        $('input:hidden[name=destinoUrl]', contexto).val(urlDestino);
        $('input:hidden[name=destinoCodigo]', contexto).val($(this).siblings('input:hidden[name=c]').val());
        if ($('#buscadorReservas').length > 0) {
            $('input:text[name=searchDestinoHotel]', contexto).val($(this).siblings('input:hidden[name=n]').val());
            $('input:hidden[name=oldDestino]', contexto).val($(this).siblings('input:hidden[name=n]').val());
            $('#buscadorReservas').submit();
        } else if ($('#buscadorDisponibilidad').length > 0) {
            $('#buscadorDisponibilidad').submit();
        } else if ($('#modificarReserva').length > 0) {
            $('#modificarReserva').submit();
        }
        window.scroll(0, 0); // para que se vea el waitScreen si estamos al final de la página
        return false;
	});

	// enlace a modificar reserva
	$a.filter('a[href*=/nuestros-hoteles/modificar-reserva/v/u/]', contexto).click( function() {
        $('input:hidden[name=destinoTipo]').val('HOT');
        var urlDestino = this.href;
        var pos = urlDestino.indexOf('/u/');
        if (pos > 0) {
            urlDestino = urlDestino.substring(pos + 3);
        } else {
            urlDestino = '';
        }
        $('input:hidden[name=destinoUrl]').val(urlDestino);
        $('input:hidden[name=destinoCodigo]').val($(this).siblings('input:hidden[name=c]').val());
        $('input:text[name=searchDestinoHotel]').val('');
        $('input:text[name=oldDestino]').val('');
        $('#modificarReserva').submit();
        window.scroll(0, 0); // para que se vea el waitScreen si estamos al final de la página
        return false;
	});

	// enlaces a paginador (/pagina/xxx)
    // Considerar también el fresto de params get (orden, tipo, pais, etc)
	$a.filter('[href*=/nuestros-hoteles/lista/],[href*=/nuestros-hoteles/buscar/]', contexto).not('.noJS,[href*=#],a[href*=ajax/]').filter('a[href*=/pagina/],a[href*=/orden/],a[href*=/tipo/],a[href*=/pais/],a[href*=/poblacion/],a[href*=/provincia/]', contexto).click( function() {
        var urlDestino = this.href;
        var pagina = extraerValorParametro(urlDestino, 'pagina', '1');
        var orden = extraerValorParametro(urlDestino, 'orden', '');
        var tipo = extraerValorParametro(urlDestino, 'tipo', '');
        var pais = extraerValorParametro(urlDestino, 'pais', '');
        var poblacion = extraerValorParametro(urlDestino, 'poblacion', '');
        var provincia = extraerValorParametro(urlDestino, 'provincia', '');
		var $form = $('#searchFilters');
		
		if (!$form.length) return true;
		
        $('#searchFilters').find('input:hidden[name=pais]').val(pais);
//        $('#searchFilters').find('input:hidden[name=poblacion]').val(poblacion);
//        $('#searchFilters').find('input:hidden[name=provincia]').val(provincia);
        $('#searchFilters').find('input:hidden[name=orden]').val(orden);
        $('#searchFilters').find('input:hidden[name=paginaPost]').val(pagina);
        if (urlDestino.indexOf('/nuestros-hoteles/lista/') >= 0) {
            var actionLista = lang+'/nuestros-hoteles/lista/v/pagina/' + pagina;
            if (orden != '') {
                actionLista += ('/orden/' + orden);
            }
            if (pais != '') {
                actionLista += ('/pais/' + pais);
            } else if (poblacion != '') {
                actionLista += ('/poblacion/' + poblacion);
            } else if (provincia != '') {
                actionLista += ('/provincia/' + provincia);
            } else if (tipo != '') {
                actionLista += ('/tipo/' + tipo);
            }
            $('#searchFilters').attr('action', actionLista);
        } else {
            $('#searchFilters').find('input:hidden[name=pagina]').val(pagina);
        }
        $form.submit();
        return false;
	});
} 
function extraerValorParametro(laUrl, nombreParam, valorDefecto) {
    var valorParam = '';
    var pos = laUrl.indexOf('/' + nombreParam + '/');
    if (pos > 0) {
        valorParam = laUrl.substring(pos + nombreParam.length + 2);
        pos = valorParam.indexOf('/');
        if (pos >= 0) {
            valorParam = valorParam.substring(0, pos);
        }
    } else {
        valorParam = valorDefecto;
    }
    return valorParam;
}
function redondearBordes(contexto) {
	if (!$.browser.msie) return; // solo hacemos esto para Internet Explorer
	$('button.boton').each(function(){
		var $t = $(this).hide();
		if ($t.prev().hasClass('js-anchorButton')) return false;
		$('<a></a>').attr('className', $t.attr('className')).addClass('js-anchorButton').html('<span>'+$t.html()+'</span>')
		.insertBefore($t)
		.click( function() {
			var $boton = $(this);
			if ($t.is('[type=submit]')) {
				$boton.closest('form').submit();
			} else {
				$t.trigger('click');
			}
			return false;
		});
	});
}
var fechaValidada = true;
function validarFecha(inputFecha, func) {
    var fecha0 = inputFecha.val();
    if (fecha0 == '' || fecha0.testDate(dformat)) {
        return true;
    } else {
        fechaValidada = false;
        alert(txtErrorFecha + ': ' + fecha0);
        setTimeout(function(){
            inputFecha.focus();
        }, 100);
        inputFecha.val('');
        return false;
    }
}
function extenderFormularios(contexto) {
	// fechas relacionadas
	// ver $.datepicker.setDefaults para las opciones por defecto
	$('div.fechasRelacionadas', contexto).each(function() {
		var $input = $('input.datepicker', this),
			desfase=$(this).hasClass('mismoDia') ? 0 : 1;
        $input.change(function() {
                return validarFecha($(this), 'change');
        });
        $input.keypress(function (e) {
            if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
                return fechaValidada;
            }
            return true;

        });
		$input.eq(0).datepicker({
			beforeShow:function() {
				if ( $input.eq(0).val() && $input.eq(1).val() ) {
					$input.eq(1).val('');
				}
				var fecha = ($input.eq(1).val()) ? $input.eq(1).val().toDate(dformat,-desfase) : false;
				$input.eq(0).datepicker('option',{'maxDate':fecha,'dateFormat':jqdformat});
			},
			onSelect: function() {
				if (!$input.eq(1).val()) {
					setTimeout(function(){
						$input.eq(1).next().click();
					}, 100);
				}
			}
		});
		
		$input.eq(1).datepicker({
			beforeShow:function() {
				var fecha = $input.eq(0).val();
				fecha = fecha.testDate(dformat) ? fecha.toDate(dformat,desfase) : 0;
				$input.eq(1).datepicker('option',{'minDate':fecha,'dateFormat':jqdformat});
			}
		});			
	});
	
	// falsos inputs con un select asociado
	$("select.autocompleter").each(function (index) {
		var ops = $(this).children();
		var data = new Array();
		var $this = $(this);
		var id = $this.attr("id") || (new Date()).getTime()+index;
		
		$this.hide();
		ops.each(function (index) {
			data[index] = {id:$(this).val() , value:$(this).text()};
		});
			
		if ($("#result_"+id).length == 0) {
			
			$("<input type='text' id='result_"+id+"' class='text autocompleter' name='inputValue_"+id+"'>")
				.insertBefore($this);
		}
		
		$("#result_"+id)
			.autocomplete(data, {formatItem: function(item) {return item.value;}, matchContains: true})
			.result(function (event, item) {$this.val(item.id);});
	});

    // presentar waitScreen al hacer submit
    // waitScreen está en waitScreen.php que se incluye en y buscador.inc.php
	var $formReservas = $('#buscadorReservas'),
		$input = $formReservas.find('input.principal');
	$formReservas.submit(function() {
		var secureapproot = 'https://www.husa.es/'
		if ($input.val() != $('#oldDestino').val()) {
	        $('#destinoTipo').val('');
	        $('#destinoCodigo').val('');
		}

            if ($('#destinoUrl').val() != '') {
                $('#destinoTipo').val('HOT');
            }
		if ($('#destinoTipo').val() == "HOT") {
			if ($('#fechaEntrada').val() && $('#fechaSalida').val()) {
				$(this).attr('action', secureapproot+lang+'/nuestros-hoteles/reservar-1');
            }
			else {
				$(this).attr('action', approot+lang+'/nuestros-hoteles/hotel/v/u/'+$('#destinoUrl').val());
            }
        }
        var $criterio = $('#searchDestinoHotel').val(),
            $fechaEnt = $('#fechaEntrada').val(),
            $fechaSal = $('#fechaSalida').val(),
            $adultos = $('[name="adultos"] :selected').val(),
            $ninos = $('[name="ninos"] :selected').val(),
            $form = $(this);
            if (!$criterio || !fechaValidada || !validarFecha($('#fechaEntrada'), 'submit') || !validarFecha($('#fechaSalida'), 'submit')) {
                fechaValidada = true;
				if (!$criterio)  {
					$('#searchDestinoHotel').css("border","1px red solid");
					$('#searchDestinoHotel').css("background-color","#FFFFEC");
				}
                return false;
				
            }
            submitBuscadores($form, $criterio, $fechaEnt, $fechaSal, $adultos, $ninos);
	});
	
	$('body#hotel').find('#buscadorDisponibilidad').attr('target', '_blank');
	$('#searchFilters').submit(function() {
        var $criterio = $('#searchDestinoHotel').val(),
            $fechaEnt = $('#fechaEntrada').val(),
            $fechaSal = $('#fechaSalida').val(),
            $adultos = $('[name="adultos"]').val(),
            $ninos = $('[name="ninos"]').val(),
            $form = $(this);
            submitBuscadores($form, $criterio, $fechaEnt, $fechaSal, $adultos, $ninos);
	});


}
function submitBuscadores($form, $criterio, $fechaEnt, $fechaSal, $adultos, $ninos) {
        if ($form.attr('target')) {
            return;
        }
        var $textoBusqueda = '<ul>';
        if ($criterio && $criterio != '' && $criterio != 'undefined') {
            $textoBusqueda += ('<li>' + txtDestinoHotel + ': ' + $criterio + '</li>');
        }
        if ($fechaEnt != '') {
            $textoBusqueda += ('<li>' + txtFechaEntrada + ': ' + $fechaEnt + '</li>');
        }
        if ($fechaSal != '') {
            $textoBusqueda += ('<li>' + txtFechaSalida + ': ' + $fechaSal + '</li>');
        }
        if ($adultos != '' && $adultos != '0') {
            $textoBusqueda += ('<li>' + txtAdultos + ': ' + $adultos + '</li>');
        }
        if ($ninos != '' && $ninos != '0') {
            $textoBusqueda += ('<li>' + txtNinos + ': ' + $ninos + '</li>');
        }
        $textoBusqueda += '</ul>';
        $('#criterioBusqueda').html($textoBusqueda);
        $('#contenido-principal').children().hide().end().append($('#waitScreen').html());
        $form.find(':input').attr('readonly', 'readonly');
}
// agrupamos todas las funciones relacionadas con extensiones del DOM y funciones que no sean invocables mediante un evento "live"
// en la siguiente funcion, util en caso de actualizar eventos de HTML creado con AJAX
function prepararEventos(contexto) {
	var contexto = contexto || document;
	extenderClases(contexto);
	extenderEnlaces(contexto);
	redondearBordes(contexto);
	extenderFormularios(contexto);
	inicTabs(contexto);
	inicPanels(contexto);
}

$(function() {
	prepararEventos(document);
});

/*
 * -------------------------------------------------------------- eventos globales para AJAX
*/
var contenedorAjaxLoader = null;
$(function(){
	var rutaImg = approot+'img/ajax-loader.gif';
	$('<div id="cargando"><img src="'+ rutaImg +'" alt="" /></div>').appendTo('body');
	$('#cargando').bind("ajaxSend", function(){
		var $cont = $(contenedorAjaxLoader || 'body'),
			$aux  = $cont.is('body') ? $(document) : $cont
			$t=$(this);
		// evitamos un bug de FF con los computedStyles de jQuery en elementos con display:none
		if ($aux.parents().andSelf().is(':hidden')) return false;
		
		// seteamos los estilos para que ocupe el espacio adecuado
		$t.css({
			top:   $cont.offset().top + 'px',
			left:  $cont.offset().left + 'px',
			width: $aux.width() + parseInt($cont.css('paddingLeft')) + parseInt($cont.css('paddingRight')) + 'px',
			height:$aux.height() + parseInt($cont.css('paddingTop')) + parseInt($cont.css('paddingBottom')) + 'px'
		})
		.css('opacity', 0).show().fadeTo(1200, 0.8);
		// cambiamos a position:fixed para la imagen si estamos en el body
		if ($cont.is('body')) {
			$t.find('img').css('position', 'fixed');
		} else {
			$t.find('img').css('position', 'absolute');
		}
	})
	.bind("ajaxComplete", function(){
		// ocultamos y reseteamos la variable contenedorAjaxLoader
		$(this).stop().fadeTo(600, 0, function() {
			$(this).hide();
		});
		contenedorAjaxLoader = null;
	});
});



/*
 * -------------------------------------------------------------- validacion de formularios multipagina
*/ 
function DForm(elem, o) {
	// definimos el a partir del propio Element o a traves de la ID
	var _this = this;
	var _el = _this.elem  = typeof elem == 'object' && elem.tagName ? elem : document.getElementById(elem);
	var _fi = _this.field = _el.getElementsByTagName('FIELDSET');
	var o   = o || {};
	_this.legend= [];
	_this.validation = [];
	_this.aniSpeed = o.aniSpeed || 600;
	_this.useAJAX  = o.useAJAX || false;
	_this._aField = 0;
	_this._evSumbit = false;
	// asignamos a cada elemento del Array legend, de no tenerlo se deja vacio
	for (var i=0,l=_fi.length; i<l; ++i) {
		this.legend.push(_fi[i].getElementsByTagName('LEGEND')[0]);
	}
	// 
	$(_el).submit(function() {
		return _this.submit();
	});
} 
/**
 * 
 * @param {Number} nF el <fieldset> al que asignamos la funcion de validacion
 * @param {Function} fVal si el <fieldset> esta correcto esta funcion debe devolver TRUE, de lo contrario devolvemos un string con un error
 */
DForm.prototype.addValidation = function(nF, fVal) {
	/* las funciones de validacion deberian devolver o bien
	 * un String con el HTML de error si es invalido
	 * o FALSE si es valido
	 */
	var _t = this;
	this.validation[nF] = fVal;
}

DForm.prototype.validate = function(nF, animacion) {
	var OKO = this.validation[nF](this.field[nF]),
		animacion = animacion === false ? false : true;
	if (typeof OKO == 'string' && OKO.length) {
		this.showError(nF, OKO, animacion)
		return false;
	} else {
		this.hideError(nF);
		return true;
	}
}

DForm.prototype.hideError = function(nF) {
	var field = this.field[nF];
	$('div.ko', field).slideUp(this.aniSpeed, function(){
		$(this).remove();
	});
}

DForm.prototype.showError = function(nF, errTxt) {
	var field = this.field[nF],
		animacion = animacion === false ? false : true,
		aniSpeed = animacion ? this.aniSpeed : 0,
		errDiv = $('div.ok,div.ko', field);
	if (errDiv.length) {
		errDiv.removeClass('ok').addClass('ko').html(errTxt).fadeOut(aniSpeed/2).fadeIn(aniSpeed/2);
	} else {
		$(['<div class="ko" style="display:none">', errTxt, '</div>'].join('')).prependTo(field).slideDown(aniSpeed);
	}
}

DForm.prototype.showSuccess = function(nF, successTxt) {
	var field = this.field[nF],
		animacion = animacion === false ? false : true,
		aniSpeed = animacion ? this.aniSpeed : 0,
		errDiv = $('div.ko,div.ok', field);
	if (errDiv.length) {
		errDiv.removeClass('ko').addClass('ok').html(errTxt).fadeOut(aniSpeed/2).fadeIn(aniSpeed/2);
	} else {
		$(['<div class="ok" style="display:none">', successTxt, '</div>'].join('')).prependTo(field).slideDown(aniSpeed);
	}
}

/**
 * Esta funcion lleva el fieldset actual hasta nF. 
 * En caso de ir hacia adelante se hacen las validaciones necesarias antes
 * @param {Number} nF numero (empieza por cero) de <fieldset> que tiene que hacerse visible
 */
DForm.prototype.toField = function (nF) {
	var _aF = this._aField,
		$f  = $(this.field),
		val = true,
		$tabs = $(this.elem).prev('.DForm-tabs').find('a'),
		animField = function(ini, fin) {
			var $ini = $f.eq(ini),
				$fin = $f.eq(fin).css({visibility:'hidden', position:'absolute', display:'block'}), // ocultamos pero mostramos :P
				$form = $f.eq(0).closest('form'),
				dir = ini > fin ? {ini:'right', fin: 'left'} : {ini: 'left', fin: 'right'}, // los campos van a izquierda o derecha ?
				aniSpeed = this.aniSpeed,
				targetH = parseInt($fin.height()) + parseInt($fin.css('paddingTop')) + parseInt($fin.css('paddingBottom')); // calculamos la altura a la que se tiene que convertir el $form
			$form.css({position: 'relative', overflow: 'hidden'});
			$fin.css({visibility:'', position:'', display:'none'});
			$form.animate({height:targetH+'px'}, aniSpeed);
			$ini.hide('drop', {direction:dir.ini}, aniSpeed, function() {
				$fin.show('drop', {direction:dir.fin}, aniSpeed, function() {
					$form.css({height:'auto', overflow:'auto'})
				});
			});
			$tabs.removeClass('active').eq(fin).addClass('active');
		};
	
	// hacemos las validaciones hasta que esten todas las que tocan o hasta que pete
	if (nF == _aF) return false;
	for (var i=_aF; i<nF; ++i)  {
		if (this.validation[i] && !this.validate(i, i==_aF)) { // OJO, si i!=_aF pasamos FALSE como parametro de animacion
			this.toField(i);
			val = i;
			break;
		}
	}
	
	if (val === true) {
		// hacemos la animacion hacia nF
		if (nF<$f.length) {
			animField(_aF, nF);
			this._aField = nF;
		}
		return true;
	} else {
		// hacemos la animacion, pero hacia val
		if (_aF!=val) {
			animField(_aF, val);
			this._aField = val;
		}
		return false;
	}
}

DForm.prototype.submit = function() {
	var _this = this;
	// comprobamos los campos del form
	if (_this.toField(this.field.length) === true) {
		// si esta correcto miramos si es por AJAX
		if (_this.useAJAX) {
			contenedorAjaxLoader = _this.elem;
			$.ajax({
				url: _this.elem.action,
				data: $(_this.elem).serialize() + '&esAJAX=1&lang=' + lang,
				type: 'post',
				dataType: 'json',
				complete: function(respuesta) {
					var oJSON = JSON.parse(respuesta.responseText),
						mensaje = oJSON.text;
					// comprobamos si el texto contiene un listado de erorres
					if (mensaje.indexOf('<ul>')==-1) {
						mensaje = ['<ul><li>', mensaje, '</li></ul>'].join('');
					}
					if (oJSON.respuesta == 'ok') {
						_this.showSuccess(this.aField || 0, mensaje);
						$(':input', _this.elem).attr('disabled', 'disabled');
					} else {
						_this.showError(this.aField || 0, mensaje);
					}
				}
			});
			// el AJAX destruye el comportamiento normal del <form>
			return false; 
		} else {
			// si esta correcto y no es AJAX devolvemos true
			return true;
		}
	} else {
		return false;
	}
}

DForm.prototype.makeTabs = function(controls) {
	var _t = this,
		_e = _t.elem,
		_f = this.field,
		$c = $(_f).append('<div class="DForm-buttons" />').children(':last-child'),
		controls = controls === false ? false : true,
		aHtml = ['<ul class="DForm-tabs">'];
	for (var i=0,l=_f.length; i<l; ++i) {
		// anadimos los botones dentro de los fields
		if (i>0) {
			_f[i].style.display = 'none';
			if (controls) {
				$(['<a class="DForm-prev boton" rel="', i-1,'"><span>', txtAnterior, '</span></a>'].join('')).appendTo($c.eq(i)).click(function() {
					_t.toField(this.rel);
				});
			}
		}
		if (i<l-1 && controls) {
			$(['<a class="DForm-next boton" rel="', i+1,'"><span>', txtSiguiente, '</span></a>'].join('')).appendTo($c.eq(i)).click(function() {
				_t.toField(this.rel);
			});
		}
		if (i==l-1 && controls) {
			$(_e).find('[type=submit], a.js-anchorButton').remove();
			$(['<button type="submit" class="DForm-submit boton">', txtEnviar, '</button>'].join('')).appendTo($c.eq(i));
		}
		aHtml.push('<li id="', _e.id, '_', i, '"><a class="', i==0 ? 'active':'' ,'">', _t.legend[i] ? _t.legend[i].innerHTML : txtLeyenda+(i+1), '</a></li>');
	}
	aHtml.push('</ul>');
	
	// una vez realizada la insercion de contenido preparamos los eventos sobre los grupos de botones
	prepararEventos($c);
	if (controls) {
		$(aHtml.join('')).insertBefore(_e).find('li').click(function() {
			var id = this.id;
			_t.toField( id.substring(id.lastIndexOf('_')+1) );
		});
	}
}



/*
 * -------------------------------------------------------------- funciones globales para construir y alimentar GMaps
*/
var HUSA_DEFAULT_ICON, HUSA_HOTEL_ICON;
var hol;soundManager.url=approot+'swf';soundManager.debugMode=false;soundManager.onload=function(){hol=soundManager.createSound({id:'r5oHol',url:approot+'swf/hi01321.mp3',volume:50,pan:50});$('body').append('<div id="R5O"></div>');$('#footer-pictos').click(showR5O);};function showR5O(){var $d=$('#R5O').css('visibility','visible');$d.appendTo('body').stop(true,true).animate({marginTop:'-200px'},400,function(){hol.play();setTimeout(function(){$d.animate({marginTop:'0px'},400,function(){$d.css('visibility','hidden')})},600)})}
function defineGMapsIcons() {
	HUSA_DEFAULT_ICON = new GIcon(G_DEFAULT_ICON, approot+'img/mapas/_defaultIcon.png');
	HUSA_DEFAULT_ICON.shadow = approot+'img/mapas/_shadow.png';
	HUSA_DEFAULT_ICON.transparent = approot+'img/mapas/_transparent.png';
	HUSA_DEFAULT_ICON.iconSize = new GSize(25, 25);
	HUSA_DEFAULT_ICON.shadowSize = new GSize(25, 25);
	HUSA_DEFAULT_ICON.iconAnchor = new GPoint(12, 12);
	HUSA_DEFAULT_ICON.infoWindowAnchor = new GPoint(25, 0);
	HUSA_DEFAULT_ICON.imageMap = [8,0, 0,8, 0,17, 8,24, 17,24, 24,17, 24,8, 17,0];

	HUSA_HOTEL_ICON = new GIcon(HUSA_DEFAULT_ICON, approot+'img/mapas/hotel.png');
	HUSA_HOTEL_ICON.shadow = '';
	HUSA_HOTEL_ICON.transparent = approot+'img/mapas/hotelTransparent.png';
	HUSA_HOTEL_ICON.iconSize = new GSize(28, 35);
	HUSA_HOTEL_ICON.shadowSize = new GSize(28, 35);
	HUSA_HOTEL_ICON.iconAnchor = new GPoint(15, 31);
	HUSA_HOTEL_ICON.infoWindowAnchor = new GPoint(29, 8);
	HUSA_HOTEL_ICON.imageMap = [0,0, 6,9, 4,15, 15,34, 27,16, 21,5, 8,5];
	
	HUSA_CURRENT_HOTEL_ICON = new GIcon(HUSA_HOTEL_ICON, approot+'img/mapas/_hotel.png');
	HUSA_CURRENT_HOTEL_ICON.transparent = approot+'img/mapas/_hotelTransparent.png';
	HUSA_CURRENT_HOTEL_ICON.iconSize = new GSize(42, 52);
	HUSA_CURRENT_HOTEL_ICON.shadowSize = new GSize(42, 52);
	HUSA_CURRENT_HOTEL_ICON.iconAnchor = new GPoint(24, 50);
	HUSA_CURRENT_HOTEL_ICON.infoWindowAnchor = new GPoint(47, 15);
	HUSA_CURRENT_HOTEL_ICON.imageMap = [0,0, 9,14, 6,32, 22,52, 41,26, 28,5, 14,8];
}

// definimos un objeto mapa global para ejecutar metodos que nos interesen
// center tiene que ser un Array con latitud y longitud (en este orden)
function Mapa(elem, center, o) {
	// iniciamos variables internas
	var _t  = this,
		_el = this.elem = typeof elem == 'string' ? document.getElementById(elem) : elem,  
		_o  = this.options = o || {};
		styleCache = $(_el).css('display') || '';
	_t.markers = {}; // gestion de marcadores para acceder a ellos externamente
	_t.mappedZone = [] // zona mapeada con marcadores
	if (!HUSA_DEFAULT_ICON) {
		defineGMapsIcons();
	}
	
	// definimos las opciones por defecto
	_o.mapTypes = _o.mapTypes || [G_NORMAL_MAP, G_SATELLITE_MAP, G_HYBRID_MAP];
	_o.zoom = _o.zoom || 13;
	_o.zoomControl = (_o.zoomControl===undefined)? new GSmallZoomControl3D() : _o.zoomControl;
	_o.mapTypeControl = (_o.mapTypeControl===undefined) ? new GMenuMapTypeControl() : _o.mapTypeControl;

	// nos aseguramos que el elemento tiene display:block
	$(_el).css({
		display:'block'
	});
	// creamos el nuevo objeto GMap2, lo asignamos a this.GMap y revertimos el atributo style del elemento
	_t.GMap = new GMap2( _el, {mapTypes: _o.mapTypes} );
	_t.GMap.setCenter(new GLatLng(center[0], center[1]), _o.zoom);
	$(_el).css('display', styleCache);
	
	// definimos UI, esto tal vez se cambie mas adelante para permitir customizacion
	if(_o.zoomControl) _t.GMap.addControl(_o.zoomControl);
	if (_o.mapTypeControl) _t.GMap.addControl(_o.mapTypeControl);
	
	// preparamos el reseteo de markers en caso de clearOverlays()
	GEvent.addListener(_t.GMap, 'clearoverlays', function(){
		_t.markers = {};
		_t.mappedZone = [];
	});
	
	// preparamos un evento de asignacion de eventos + extenderDOM para las ventanas
	GEvent.addListener(_t.GMap, 'infowindowopen', function() {
		var elem = mapa.GMap.getInfoWindow().getContentContainers()[0];
		prepararEventos(elem);
	})
	
}

Mapa.prototype.objectToOverlays = function(obj) {
	/*
	imprime un overlay para cada atributo dentro del objeto, el formato de este debe ser:
	obj={
		'hotel-666': {id:666, type:'hotel', name:'Lorem ipsum', lat:40.0, lng:0.0, cat: 'GL', img: approot+'img/_HOTELPEQUE.jpg', address: 'Gran Via de les Corts Catalanes, 668<br/>08010 Barcelona<br/>Tel. +34.93.510.11.30<br/>Fax. +34.93.318.01.48', web: 'http://www.hotelpalacebarcelona'},
		'otro-777': {id:777, type:'otro', name:'Dolor sit', lat:40.0, lng:0.01, icon:'', text:'Together forever and ever blah blah'}
	}
	*/
	var _map = this.GMap,
		newZone = null,
		tempGLatLng;
	for (i in obj) {
		// evitamos que se repitan registros
		if (this.markers[i]) continue;
		// evitamos que se creen puntos sin datos 
		if (obj[i].lat == null || obj[i].lng == null) continue;
		// extendemos la zona que ocupan los puntos creados
		tempGLatLng = new GLatLng(obj[i].lat, obj[i].lng);
		if (newZone) {
			newZone.extend(tempGLatLng);
		}
		else {
			newZone = new GLatLngBounds(tempGLatLng);
		}
		// en primer lugar creamos un nuevo objeto GMarker a partir latitud, longitud y tipo de objeto
		var icono = (obj[i].current) ? HUSA_CURRENT_HOTEL_ICON : (obj[i].type == 'hotel' ? HUSA_HOTEL_ICON : new GIcon(HUSA_DEFAULT_ICON, obj[i].icon))
		this.markers[i] = new GMarker(tempGLatLng,
			{icon: icono}
		);
		this.GMap.addOverlay(this.markers[i]);
		// como propiedad del marcador guardamos una referencia al objeto que lo ha creado para utilizarlo onclick
		this.markers[i].markerInfo = obj[i];
		GEvent.addListener(this.markers[i], 'click', function() {
			this.openInfoWindow(buildInfoWindow(this.markerInfo));
		});
	}
	// Control de nueva zona mapeada
	// si esta funcion se ha llamado desde updateViewport nunca deberia anyadir una nueva zona
	// porque se ha anyadida ya en la funcion anterior
	if (newZone) this.extendMappedZone(newZone);
}

Mapa.prototype.feedMapWithJSON = function(JSONurl, additionalParams, updateCallback) {
	var _t = this, // para referencias futuras
		_map = _t.GMap, // id. que ant.
		additionalParams = additionalParams || '',
		updateCallback = updateCallback || (typeof additionalParams == 'function')? additionalParams : function() {};
	// iniciamos la zona mapeada con un unico punto, anyadimos listener y llamamos por primera vez
	_t.mappedZone = [];
	GEvent.addListener(_map, 'moveend', function(){
		_t.JSON2Overlays(JSONurl, additionalParams, updateCallback)
	});
}

Mapa.prototype.JSON2Overlays = function(JSONurl, additionalParams, updateCallback) {
	var _t = this, // para referencias futuras
		_map = _t.GMap, // id. que ant.
		additionalParams = additionalParams || '',
		updateCallback = updateCallback || (typeof additionalParams == 'function')? additionalParams : function() {},
		bounds = _map.getBounds(),
		NEWS, bigNEWS;
	// si el "viewport" esta dentro de la zona mapeada devolvemos false y NO hacemos llamada AJAX
	
	// de otro modo calculamos las nuevas coordenadas del mapeado
	NEWS = {N:bounds.getNorthEast().lat(),E:bounds.getNorthEast().lng(),W:bounds.getSouthWest().lng(),S:bounds.getSouthWest().lat()},
	bigNEWS = {
		N: NEWS.N * 2 - NEWS.S,
		E: NEWS.E * 2 - NEWS.W,
		W: NEWS.W * 2 - NEWS.E,
		S: NEWS.S * 2 - NEWS.N
	}
	if (_t.isZoneInMappedZone(bounds)) {
		return false;
	} else {
		_t.extendMappedZone(bigNEWS.N, bigNEWS.E, bigNEWS.W, bigNEWS.S);
	}
	$.ajax({
		type: 'get',
		dataType: 'json',
		url: JSONurl,
		global:false,
		data: 'n=' + bigNEWS.N + '&e=' + bigNEWS.E + '&w=' + bigNEWS.W + '&s=' + bigNEWS.S + '&' + additionalParams, 
		complete: function(respuesta) {
			if (respuesta.status == 200) {
				_t.objectToOverlays(JSON.parse(respuesta.responseText));
				updateCallback();
			} else {
				try{console.log('ERROR: response.status != 200')}catch(e){};
			}
		}
	});

	
}

Mapa.prototype.extendMappedZone = function(N, E, W, S) {
	var _mZ     = this.mappedZone,
		newZone;
	// podemos pasar como primer argumento una zona
	if (N.extend) {
		newZone = N;
	}
	// o pasar cuatro argumentos con los puntos cardinales
	else {
		newZone = new GLatLngBounds(new GLatLng(N, E));
		newZone.extend(new GLatLng(S, W));
	}
	// comprobamos por si acaso que no la tengamos
	if (this.isZoneInMappedZone(newZone)) {
		return false;
	}
	// si no la incluimos y devolvemos newZone
	else {
		_mZ.push(newZone);
		return newZone;
	}
}

Mapa.prototype.isZoneInMappedZone = function(zone) {
	// si ya tenemos la zona mapeada devolvemos false
	var _mZ = this.mappedZone;
	for (var i=0,l=_mZ.length;i<l;++i){
		if (_mZ[i].containsBounds(zone)) return true;
	}
	return false;
}

Mapa.prototype.setZoomOnMarkers = function() {
	var _markers = this.markers;
	var limites = new GLatLngBounds();
	var flag = false;
	
	for($i in _markers){
		flag = true;
		limites.extend(_markers[$i].getLatLng())
	}
	if(flag)
		this.GMap.setCenter(limites.getCenter(),this.GMap.getBoundsZoomLevel(limites) - 1);
	
	return this;
}

// funcion que devuelve un String de HTML para pintar dentro del InfoWindow
function buildInfoWindow(info) {
	if (info.type != 'hotel') {
		return ['<div class="hotelInfoGMap"><h4>', info.name, '</h4>', info.text, '</div>'].join('');
	}
	
	var catMap = new Array();
	catMap[0] = 0;
	catMap[1] = 1;
	catMap[2] = 2;
	catMap[3] = 3;
	catMap[4] = 4;
	catMap[5] = 5;
	catMap[6] = 'GL';
	catMap[7] = 'empty';
	catMap[8] = 'empty';
	
	var a = [];
	a.push('<div class="hotelInfoGMap">');
		a.push('<h4><a href="', approot, lang, info.reservar.replace(/(.+\/)(v\/.+)/g,'/nuestros-hoteles/hotel/$2'), '">', info.name, ' <img src="img/stars/', catMap[info.cat], '.gif" alt="', info.cat, '" /></a></h4>');
		a.push('<img height="74" class="imgHotel" src="', info.img, '" alt="', info.name, '" />');
		a.push('<address>', info.address, '<br />', info.poblacion, '<br /><a href="mailto:', info.email, '">', info.email, '</a><br />', info.telefono, '<br />',  '</address>');
	a.push('</div>');

	a.push('<div class="hotelAccionesGMap">');
		a.push('<ul class="inlineList floatLeft">');
			if (info.web) {
				a.push('<li><a href="', info.web, '">', txtWeb, '</a></li> ');
			}

			a.push('<li><a rel="external" href="http://maps.google.es/maps?f=d&amp;daddr=', info.lat, ' ', info.lng, '">', txtComoLlegar, '</a></li> ');
			a.push('<li><a href="', info.reservar ,'">', txtReservar, '</a>');
            if (info.ulyses) {
                a.push('<input name="c" type="hidden" value="' + info.ulyses + '" />');
            }
            a.push('<input name="n" type="hidden" value="' + info.name + '" />');
			a.push('</li> ');
		a.push('</ul>');
		a.push('<span class="floatRight">');
		a.push('<a href="', approot, 'ajax/addToGPS.php?id=' + info.id + '&lang=', lang, '" class="addToGPS"><img src="', approot, 'img/icoGPS.png" alt="', txtEnviarGPS, '" title="', txtEnviarGPS, '" /></a>');
		a.push('<a href="', approot, 'ajax/generarKml.php?id=' + info.id + '"><img src="', approot, 'img/icoKML.gif" alt="', txtGenerarKML, '" title="', txtGenerarKML, '" /></a>');
		a.push('<a href="javascript:print();"><img src="', approot, 'img/icoPrint.gif" alt="', txtImprimir, '" title="', txtImprimir, '" /></a>');
		a.push('</span>');
	a.push('</div>');
	return a.join('');
}
