Skip to main content

Overview

The map integration displays property locations using OpenStreetMap with:
  • Embedded interactive map with marker
  • Link to Google Maps for navigation
  • Fallback to address-based search when coordinates are unavailable
  • Responsive iframe rendering

HTML Structure

From index.html:185-197, the location section:
<section class="bg-white dark:bg-slate-800 p-8 rounded-2xl shadow-sm border border-slate-100 dark:border-slate-700">
  <div class="flex justify-between items-center mb-6">
    <h3 class="text-xl font-display font-bold flex items-center gap-2">
      <span class="material-icons-outlined text-primary">map</span>
      Ubicación
    </h3>
    <a id="property-map" class="text-primary text-sm font-semibold flex items-center gap-1 hover:underline" href="#" target="_blank" rel="noopener">
      Ver en Google Maps <span class="material-icons-outlined text-xs">open_in_new</span>
    </a>
  </div>
  <p id="property-address" class="text-slate-500 dark:text-slate-400 text-sm mb-4">Dirección no disponible</p>
  <div id="property-map-preview" class="w-full h-[300px] bg-slate-200 dark:bg-slate-700 rounded-xl relative overflow-hidden"></div>
</section>

renderMap() Function

From app.js:531-569, this function handles both OpenStreetMap embedding and Google Maps linking:
const renderMap = (property) => {
  const address = [property.direccion, property.barrio, property.ciudad]
    .filter(Boolean)
    .join(", ");
  const mapLink = $("#property-map");
  const mapPreview = $("#property-map-preview");
  const coords = property.latitud && property.longitud
    ? `${property.latitud},${property.longitud}`
    : null;

  $("#property-address").textContent = address || "Dirección no disponible";

  // Google Maps link (for navigation)
  const mapUrl = coords
    ? `https://www.google.com/maps/search/?api=1&query=${coords}`
    : `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(address)}`;

  mapLink.href = mapUrl;

  // OpenStreetMap embed (for preview)
  if (coords) {
    const [lat, lon] = coords.split(",");
    const delta = 0.01;
    const left = parseFloat(lon) - delta;
    const right = parseFloat(lon) + delta;
    const top = parseFloat(lat) + delta;
    const bottom = parseFloat(lat) - delta;
    const iframe = document.createElement("iframe");
    iframe.src = `https://www.openstreetmap.org/export/embed.html?bbox=${left}%2C${bottom}%2C${right}%2C${top}&layer=mapnik&marker=${lat}%2C${lon}`;
    iframe.loading = "lazy";
    iframe.referrerPolicy = "no-referrer-when-downgrade";
    iframe.title = "Mapa de ubicación";
    iframe.style.border = "0";
    iframe.style.width = "100%";
    iframe.style.height = "100%";
    mapPreview.innerHTML = "";
    mapPreview.appendChild(iframe);
  } else {
    mapPreview.textContent = "Ubicación aproximada";
  }
};

Address Formatting

The address is constructed from multiple property fields:
const address = [property.direccion, property.barrio, property.ciudad]
  .filter(Boolean)
  .join(", ");

Example

Given:
property = {
  direccion: "Calle 123 #45-67",
  barrio: "Chicó",
  ciudad: "Bogotá"
}
Output:
"Calle 123 #45-67, Chicó, Bogotá"
The filter(Boolean) removes any null, undefined, or empty string values before joining.

Coordinate Handling

The function checks for both latitude and longitude:
const coords = property.latitud && property.longitud
  ? `${property.latitud},${property.longitud}`
  : null;
Both coordinates must be present for coordinate-based display.

Google Maps Integration

The “Ver en Google Maps” link uses Google Maps Search API:

With Coordinates

const mapUrl = coords
  ? `https://www.google.com/maps/search/?api=1&query=${coords}`
  : `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(address)}`;

URL Examples

https://www.google.com/maps/search/?api=1&query=4.6097,-74.0817

OpenStreetMap Embedding

When coordinates are available, an interactive map is embedded:

Bounding Box Calculation

const delta = 0.01;
const left = parseFloat(lon) - delta;
const right = parseFloat(lon) + delta;
const top = parseFloat(lat) + delta;
const bottom = parseFloat(lat) - delta;
The delta value (0.01 degrees) creates approximately a 1km × 1km viewing area around the property.
Adjust the delta value to zoom in (smaller) or out (larger). For reference:
  • 0.005 ≈ 500m × 500m (closer)
  • 0.01 ≈ 1km × 1km (default)
  • 0.02 ≈ 2km × 2km (wider)

Iframe Construction

const iframe = document.createElement("iframe");
iframe.src = `https://www.openstreetmap.org/export/embed.html?bbox=${left}%2C${bottom}%2C${right}%2C${top}&layer=mapnik&marker=${lat}%2C${lon}`;
iframe.loading = "lazy";
iframe.referrerPolicy = "no-referrer-when-downgrade";
iframe.title = "Mapa de ubicación";
iframe.style.border = "0";
iframe.style.width = "100%";
iframe.style.height = "100%";
mapPreview.innerHTML = "";
mapPreview.appendChild(iframe);

OpenStreetMap URL Parameters

ParameterValueDescription
bboxleft,bottom,right,topBounding box coordinates
layermapnikMap rendering layer
markerlat,lonMarker position

Example URL

https://www.openstreetmap.org/export/embed.html?
bbox=-74.0917%2C4.5997%2C-74.0717%2C4.6197&
layer=mapnik&
marker=4.6097%2C-74.0817

Fallback Behavior

When coordinates are not available:
if (coords) {
  // Render iframe with map
} else {
  mapPreview.textContent = "Ubicación aproximada";
}
The preview area shows placeholder text instead of a map.

Performance Optimization

The iframe uses lazy loading:
iframe.loading = "lazy";
This defers loading the map until it’s near the viewport, improving initial page load time.

Security Attributes

iframe.referrerPolicy = "no-referrer-when-downgrade";
This privacy setting controls what referrer information is sent to OpenStreetMap.

Responsive Sizing

The map container has a fixed height with responsive width:
<div id="property-map-preview" class="w-full h-[300px] bg-slate-200 dark:bg-slate-700 rounded-xl relative overflow-hidden"></div>
  • Width: 100% of parent container
  • Height: Fixed at 300px
  • Background: Light/dark mode compatible placeholder color

Complete Example

With Full Coordinates

const property = {
  direccion: "Carrera 7 #71-21",
  barrio: "Chapinero",
  ciudad: "Bogotá",
  latitud: 4.6533,
  longitud: -74.0602
};

renderMap(property);
Result:
  • Address: “Carrera 7 #71-21, Chapinero, Bogotá”
  • Google Maps link: https://www.google.com/maps/search/?api=1&query=4.6533,-74.0602
  • Embedded OpenStreetMap with marker at (4.6533, -74.0602)

Without Coordinates

const property = {
  direccion: "Carrera 7 #71-21",
  barrio: "Chapinero",
  ciudad: "Bogotá"
};

renderMap(property);
Result:
  • Address: “Carrera 7 #71-21, Chapinero, Bogotá”
  • Google Maps link: https://www.google.com/maps/search/?api=1&query=Carrera%207%20%2371-21%2C%20Chapinero%2C%20Bogot%C3%A1
  • Preview shows: “Ubicación aproximada”

Why OpenStreetMap?

No API Key Required

Unlike Google Maps embed, OpenStreetMap doesn’t require authentication

Open Source

Free to use with no usage limits or billing

Privacy Friendly

No tracking or data collection by default

Lightweight

Simple iframe embed with minimal overhead

Build docs developers (and LLMs) love