Buscar alojamientos

Alojamientos Costa Blanca, 2 huéspedes. 23 alojamientos

Calpe

Alquiler de apartamento en primera linea de Calpe, CANTAL

Personas 6 pers. Camas 3 hab. Estrellas 4.71

Desde 154,00 € /noche

Moraira

Alquiler de apartamento en Moraira, CAP DOR

Personas 6 pers. Camas 3 hab. Playa 0,2 km Estrellas 4.66

Desde 110,00 € /noche

Calpe

Alquiler de apartamento en Calpe PARAISO MAR

Personas 6 pers. Camas 3 hab. Playa 0,1 km Estrellas 5

Desde 147,00 € /noche

Calpe

Alquiler de apartamento en Calpe JOYA

Personas 6 pers. Camas 3 hab. Playa 0,5 km Estrellas 4.73

Desde 154,00 € /noche

Calpe

TRAMONTANA,apartamento tramontana Calpe en primera linea. wifi gratis

Personas 6 pers. Camas 3 hab. Playa 0,1 km Estrellas 4.55

Desde 123,00 € /noche

Calpe

Alquiler de apartamento en primera linea de mar en Calpe, EVOLUTION

Personas 4 pers. Camas 2 hab. Playa 0,2 km Estrellas 5

Desde 232,00 € /noche

Moraira

Alquiler de apartamento en Moraira, Castell

Personas 4 pers. Camas 2 hab. Playa 0,3 km

Desde 138,00 € /noche

Moraira

Alquiler de apartamento en El Portet, BELLISSIMO para 6 pax

Personas 6 pers. Camas 3 hab. Playa 1,5 km Estrellas 4.4

Desde 120,00 € /noche

Moraira

MARJALETA, Bonito apartamento en el centro de Moraira para 4 pax wifi gratuita.

Personas 4 pers. Camas 2 hab. Playa 0,8 km Estrellas 4.61

Desde 94,00 € /noche

Calpe

TOPACIO IV,apartamentos Topacio Calpe en la playa Levante.

Personas 6 pers. Camas 2 hab. Playa 0,1 km Estrellas 4.64

Desde 79,00 € /noche

Calpe

Apartamentos Paraiso Mar en primera linea de playa de Calpe, TROND

Personas 5 pers. Camas 2 hab. Playa 0,1 km Estrellas 4.64

Desde 106,00 € /noche

Calpe

Alquiler de apartamento en Calpe, BRIGITTE

Personas 4 pers. Camas 2 hab. Playa 0,3 km Estrellas 4.59

Desde 80,00 € /noche

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 = 'Desde'; 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 }); } } } }">
Actualizando mapa...
Alojamientos 100% confiables

Alojamientos 100% confiables

Registrados en el Patronato de Turismo con Nº EGVT-183A, verificados y locales.
¡Sabes dónde llegas y quién te espera!

Registrados en el Patronato de Turismo con Nº EGVT-183A, verificados y locales. ¡Sabes dónde llegas y quién te espera!

Cancelación gratuita

Cancelación gratuita

Sabemos que los planes cambian.
Aquí puedes cancelar sin costes ni condiciones escondidas.

Sabemos que los planes cambian. Aquí puedes cancelar sin costes ni condiciones escondidas.

Reserva sin fianza de daños

Reserva sin fianza de daños

La confianza va primero, por eso no bloqueamos dinero en tu tarjeta ni pedimos depósitos.

La confianza va primero, por eso no bloqueamos dinero en tu tarjeta ni pedimos depósitos.

Filtros Filtros 1 Mapa Mapa Listado Listado