Rechercher des hébergements

Accommodations in Costa Blanca, 2 guests. 107 accommodations

Moraira

Villa à louer à El Portet de Moraira, SAN VICENTE, 50 mts de l'eau et piscine privée.

Personnes 12 pers. Lits 6 ch. Plage 0,1 km Étoiles 4.61

À partir de 368,00 € /nuit

Calpe / Calp

Villa à louer à Calpe BELLISSIMA 14 pax et piscine privée

Personnes 14 pers. Lits 7 ch. Plage 1,9 km Étoiles 4.93

À partir de 10,00 € /nuit

Calpe / Calp

Villa à louer à Calpe GRANDIOSA

Personnes 14 pers. Lits 7 ch. Plage 1,9 km Étoiles 4.66

À partir de 10,00 € /nuit

Moraira

Villa à louer à Moraira ANDURINA

Personnes 10 pers. Lits 6 ch. Plage 0,7 km Étoiles 4.54

À partir de 163,00 € /nuit

Benissa

villa à louer à Benissa ARC pour 12 personnes, piscine privée et vue sur la mer

Personnes 12 pers. Lits 6 ch. Plage 2,7 km Étoiles 5

À partir de 352,00 € /nuit

Benissa

villa à louer à Benissa, MARIO

Personnes 12 pers. Lits 6 ch. Plage 1,5 km Étoiles 4.78

À partir de 253,00 € /nuit

Calpe / Calp

Location villa à Calpe STEFKA

Personnes 16 pers. Lits 8 ch. Plage 1,7 km Étoiles 4.59

À partir de 246,00 € /nuit

Calpe / Calp

Villa à louer à Calpe, SENIETA

Personnes 10 pers. Lits 5 ch. Plage 1,5 km Étoiles 4.88

À partir de 276,00 € /nuit

Moraira

Villa à louer à Moraira, FLORIDA.

Personnes 12 pers. Lits 6 ch. Plage 1,7 km Étoiles 4.61

À partir de 336,00 € /nuit

Calpe / Calp

XENIA, villa à louer à Calpe pour 12 pax avec piscine privée

Personnes 12 pers. Lits 6 ch. Plage 1,7 km Étoiles 4.84

À partir de 312,00 € /nuit

Calpe / Calp

Location de villa IFACH

Personnes 12 pers. Lits 6 ch. Plage 2,0 km Étoiles 4.67

À partir de 241,00 € /nuit

Benissa

RAPHAEL, Belle villa pour 6 pax avec vue spectaculaire sur la mer à Benissa.wifi gratuit

Personnes 6 pers. Lits 3 ch. Plage 1,0 km Étoiles 4.75

À partir de 209,00 € /nuit

link.href === href); if (existing) { resolve(); return; } const link = document.createElement('link'); link.rel = 'stylesheet'; link.href = href; link.onload = resolve; link.onerror = reject; document.head.appendChild(link); }); }, highlightMarker(accommodationId) { // Primero limpiar todos los marcadores para evitar estados inconsistentes this.markers.forEach(m => { const el = m.getElement(); const priceEl = el.querySelector('.simple-price-marker'); if (priceEl) { priceEl.classList.remove('highlighted'); } // Restaurar z-index original if (el.dataset.originalZindex !== undefined) { el.style.zIndex = el.dataset.originalZindex; } else { el.style.zIndex = ''; } el.classList.remove('marker-highlighted'); }); // Ahora destacar el marcador específico const marker = this.markers.find(m => { const el = m.getElement(); return el && String(el.getAttribute('data-accommodation-id')) === String(accommodationId); }); if (marker) { const el = marker.getElement(); const priceEl = el.querySelector('.simple-price-marker'); if (priceEl) { priceEl.classList.add('highlighted'); } // Guardar z-index original si no está guardado if (!el.dataset.originalZindex) { el.dataset.originalZindex = el.style.zIndex || ''; } el.style.zIndex = '9999'; el.classList.add('marker-highlighted'); // Mover la cámara del mapa hasta el marcador manteniendo el zoom actual const lngLat = marker.getLngLat(); this.map.flyTo({ center: [lngLat.lng, lngLat.lat], duration: 1000, // Duración de la animación en ms essential: true // Esta animación es considerada esencial }); } }, unhighlightMarker(accommodationId) { const marker = this.markers.find(m => { const el = m.getElement(); return el && String(el.getAttribute('data-accommodation-id')) === String(accommodationId); }); if (marker) { const el = marker.getElement(); const priceEl = el.querySelector('.simple-price-marker'); if (priceEl) { // Limpiar todas las clases relacionadas con el estado de hover priceEl.classList.remove('highlighted'); // También limpiar cualquier estado de hover nativo que pueda haber quedado priceEl.classList.remove('show-price'); // Solo restaurar el texto si no está en estado clicked if (!priceEl.classList.contains('clicked')) { // Para marcadores con precio oculto, limpiar el texto if (priceEl.classList.contains('hidden-price')) { priceEl.textContent = ''; } } } // Restaurar z-index original if (el.dataset.originalZindex !== undefined) { el.style.zIndex = el.dataset.originalZindex; } else { el.style.zIndex = ''; } el.classList.remove('marker-highlighted'); } }, updateMarkers(accommodations) { // Verificar que el mapa esté inicializado if (!this.map || !this.mapInitialized) { return; } // Limpiar marcadores existentes this.markers.forEach(marker => marker.remove()); this.markers = []; accommodations.forEach(accommodation => { const lat = accommodation.lat; const lng = accommodation.lng; const price = accommodation.totalPrice; const shouldDisplayPrice = accommodation.display === true; const el = document.createElement('div'); // Aplicar clase condicional basada en la propiedad display const markerClass = shouldDisplayPrice ? 'simple-price-marker' : 'simple-price-marker hidden-price'; const displayText = shouldDisplayPrice ? price : ''; el.innerHTML = `
${displayText}
`; try { // Usar la URL ya construida desde PHP que incluye todos los parámetros necesarios const accommodationUrl = accommodation.url; // Crear el popup const fromLabel = 'De'; const popupContent = document.createElement('div'); popupContent.className = 'card card--map'; const link = document.createElement('a'); link.href = accommodationUrl; link.className = 'card__link'; popupContent.appendChild(link); if (accommodation.picture) { const img = document.createElement('img'); img.src = accommodation.picture; img.className = 'card__image'; img.alt = accommodation.name || 'Alojamiento'; img.addEventListener('error', () => { img.style.display = 'none'; }); popupContent.appendChild(img); } const content = document.createElement('div'); content.className = 'card__content'; const title = document.createElement('h3'); title.className = 'card__title'; title.textContent = accommodation.name || 'Alojamiento'; content.appendChild(title); const priceWrap = document.createElement('div'); priceWrap.className = 'card__price'; priceWrap.appendChild(document.createTextNode(fromLabel + ' ')); const priceMoney = document.createElement('span'); priceMoney.className = 'card__price-money'; priceMoney.textContent = price; priceWrap.appendChild(priceMoney); priceWrap.appendChild(document.createTextNode(' ' + (accommodation.priceSuffix || ''))); content.appendChild(priceWrap); popupContent.appendChild(content); const popup = new mapboxgl.Popup({ offset: 45, closeButton: true }); if (typeof popup.setDOMContent === 'function') { popup.setDOMContent(popupContent); } else { popup.setHTML(popupContent.outerHTML); } // Crear el marcador const marker = new mapboxgl.Marker(el) .setLngLat([lng, lat]) .setPopup(popup) .addTo(this.map); // Asignar el atributo al contenedor real del marker const markerElement = marker.getElement(); markerElement.setAttribute('data-accommodation-id', accommodation.id); // Añadir listeners para hover y click const priceEl = el.querySelector('.simple-price-marker'); if (priceEl) { // Funcionalidad estándar de hover para todos los marcadores priceEl.addEventListener('mouseenter', () => { markerElement.dataset.originalZindex = markerElement.style.zIndex || ''; markerElement.style.zIndex = '99999'; markerElement.classList.add('marker-highlighted'); }); priceEl.addEventListener('mouseleave', () => { markerElement.style.zIndex = markerElement.dataset.originalZindex || ''; markerElement.classList.remove('marker-highlighted'); }); // Funcionalidad especial para marcadores con precio oculto if (!shouldDisplayPrice) { // Mostrar precio al hacer hover priceEl.addEventListener('mouseenter', () => { priceEl.classList.add('show-price'); priceEl.textContent = price; }); priceEl.addEventListener('mouseleave', () => { if (!priceEl.classList.contains('clicked')) { priceEl.classList.remove('show-price'); priceEl.textContent = ''; } }); // Manejar click en marcadores ocultos priceEl.addEventListener('click', (e) => { // No prevenir la propagación para permitir que el popup se abra // Remover clase clicked de todos los otros marcadores this.markers.forEach(otherMarker => { const otherPriceEl = otherMarker.getElement().querySelector('.simple-price-marker'); if (otherPriceEl && otherPriceEl !== priceEl) { otherPriceEl.classList.remove('clicked', 'show-price'); otherPriceEl.textContent = ''; } }); // Toggle del estado clicked en el marcador actual if (priceEl.classList.contains('clicked')) { priceEl.classList.remove('clicked', 'show-price'); priceEl.textContent = ''; } else { priceEl.classList.add('clicked', 'show-price'); priceEl.textContent = price; } }); } } this.markers.push(marker); } catch (e) { console.error('Error creating marker element:', e); } }); // Solo ajustar bounds automáticamente si: // 1. Hay marcadores // 2. No ha habido interacción del usuario // 3. Es la primera carga (no hay centro inicial establecido por alojamientos) if (this.markers.length > 0 && !this.userAct) { const bounds = new mapboxgl.LngLatBounds(); this.markers.forEach(marker => bounds.extend(marker.getLngLat())); // Solo hacer fitBounds si no hay un alojamiento específico como centro inicial const hasSpecificCenter = this.accommodations && this.accommodations.length > 0 && this.accommodations[0].lat && this.accommodations[0].lng && this.accommodations[0].lat !== 0 && this.accommodations[0].lng !== 0; if (!hasSpecificCenter) { this.map.fitBounds(bounds, { padding: 100, maxZoom: 15 }); } } } }">
Mise à jour de la carte...
Hébergements 100% fiables

Hébergements 100% fiables

Enregistrés au Patronat du Tourisme avec le Nº EGVT-183A, vérifiés et locaux.
Vous savez où vous arrivez et qui vous attend !

Enregistrés au Patronat du Tourisme avec le Nº EGVT-183A, vérifiés et locaux. Vous savez où vous arrivez et qui vous attend !

Annulation gratuite

Annulation gratuite

Nous savons que les plans changent.
Ici, vous pouvez annuler sans frais ni conditions cachées.

Nous savons que les plans changent. Ici, vous pouvez annuler sans frais ni conditions cachées.

Réservation sans caution de dommages

Réservation sans caution de dommages

La confiance passe avant tout, c'est pourquoi nous ne bloquons pas d'argent sur votre carte ni ne demandons de dépôts.

La confiance passe avant tout, c'est pourquoi nous ne bloquons pas d'argent sur votre carte ni ne demandons de dépôts.

Filtros Filtres Mapa Carte Listado Liste