Skip to content

Switch Between Buildings

Large properties — airports, university campuses, shopping malls with multiple wings — can contain more than one building. Each building has its own floors and indoor coordinate system. This guide shows how to observe building context, list and switch floors within the active building, and route across buildings.

First load: the map iframe may render a consumer-facing onboarding overlay ("Explore Building Details") on first visit. Click Got It inside the map preview to dismiss it before tapping any building.

Prerequisites

  • The library initialized and in the READY state (API lifecycle)
  • A property that contains multiple buildings (check the Mapsted CMS for building IDs)

Listing available floors for the current building

After navigating to a building you can enumerate the floors it contains using getFloors:

CDN:

html
<script src="https://mapi.mapsted.com/v4.0.1/maps.js?id=1234"></script>
<script>
  await mapsted.maps.init({ element: '#map' });

  // Returns the floors for the currently active building.
  const floors = await mapsted.maps.getFloors();
  floors.forEach((f) => {
    console.log(f.floorId, f.shortName['en'] ?? f.longName['en'] ?? '');
  });
</script>

npm:

js
import * as maps from '@mapsted/maps-js-api';

await maps.init({ element: '#map', propertyId: 1234 });

const floors = await maps.getFloors();
floors.forEach((f) => {
  console.log(f.floorId, f.shortName['en'] ?? f.longName['en'] ?? '');
});

getFloors is async — it sends a request to the iframe and resolves once the child frame responds. It returns an array of FloorInfo objects for the currently active building.

Current public-API scope: There is no getBuildings() method in the public API surface. Building IDs for the loaded property must be obtained out-of-band (e.g., from the Mapsted CMS or your own backend). See Known API gaps below.

Entering a building

Building entry is driven by the map itself: a user taps a building on the property overview, or a routing boost that targets an entity inside a building causes the iframe to enter that building as part of the route (see Cross-building routing below). When the active building changes, the API emits a buildingChange event you can subscribe to, and getState() reflects the new context.

Tip — navigateToBuilding({ buildingId, floorId? }) moves the map to a building, optionally focusing a floor (only buildingId is required). Use navigateToFloorById / navigateToFloorByName to switch floors once a building is active, and observe transitions with the buildingChange event.

Once a building is active you can switch floors by ID or by display name:

CDN:

html
<script>
  // By numeric floor ID.
  await mapsted.maps.navigateToFloorById(3);

  // By display name (as shown in the CMS floor list).
  await mapsted.maps.navigateToFloorByName('Ground Floor');
</script>

npm:

js
// By numeric floor ID.
await maps.navigateToFloorById(3);

// By display name.
await maps.navigateToFloorByName('Ground Floor');

Reacting to floor changes

The floorChange event fires whenever the active floor changes — either from a user tap on the floor switcher widget or a programmatic call to navigateToFloorById / navigateToFloorByName.

CDN:

html
<script>
  const instance = await mapsted.maps.init({ element: '#map' });

  mapsted.maps.on('floorChange', (floorInfo) => {
    console.log('Active floor:', floorInfo.floorId, floorInfo.shortName['en'] ?? floorInfo.longName['en'] ?? '');
    updateFloorDisplay(floorInfo);
  });
</script>

npm:

js
import * as maps from '@mapsted/maps-js-api';

const instance = await maps.init({ element: '#map', propertyId: 1234 });

maps.on('floorChange', (floorInfo) => {
  console.log('Active floor:', floorInfo.floorId, floorInfo.shortName['en'] ?? floorInfo.longName['en'] ?? '');
  updateFloorDisplay(floorInfo);
});

floorInfo is a FloorInfo object containing floorId, shortName (locale map), longName (locale map), floorNumber, and related metadata. Use floorInfo.shortName['en'] ?? floorInfo.longName['en'] ?? '' to get a display string.

Reacting to building changes

The buildingChange event fires whenever the active building changes — for example, when the user taps a different building on the property overview, or when a routing boost enters a building as part of a cross-building route. buildingChange is a canonical event in KNOWN_EVENTS.

CDN:

html
<script>
  await mapsted.maps.init({ element: '#map' });

  mapsted.maps.on('buildingChange', (buildingInfo) => {
    console.log('Active building:', buildingInfo.buildingId);
    updateBuildingHeader(buildingInfo);
  });
</script>

npm:

js
import * as maps from '@mapsted/maps-js-api';

await maps.init({ element: '#map', propertyId: 1234 });

maps.on('buildingChange', (buildingInfo) => {
  console.log('Active building:', buildingInfo.buildingId);
  updateBuildingHeader(buildingInfo);
});

A floor change always accompanies a building transition, so floorChange also fires when the active building changes; use buildingChange when you specifically need the building-level signal.

Floor picker UI example

A minimal dropdown that stays in sync with the active building whenever the building context changes:

CDN:

html
<script>
  await mapsted.maps.init({ element: '#map' });

  const select = document.getElementById('floor-picker');

  async function populateFloors() {
    const floors = await mapsted.maps.getFloors();
    select.innerHTML = '';
    floors.forEach((f) => {
      const opt = document.createElement('option');
      opt.value = String(f.floorId);
      opt.textContent = f.shortName['en'] ?? f.longName['en'] ?? '';
      select.appendChild(opt);
    });
  }

  await populateFloors();

  // Re-populate after building navigation.
  mapsted.maps.on('floorChange', async (floorInfo) => {
    select.value = String(floorInfo.floorId);
  });

  // Handle user-driven picker change.
  select.addEventListener('change', () => {
    mapsted.maps.navigateToFloorById(Number(select.value));
  });
</script>

npm:

js
import * as maps from '@mapsted/maps-js-api';

await maps.init({ element: '#map', propertyId: 1234 });

const select = document.getElementById('floor-picker');

async function populateFloors() {
  const floors = await maps.getFloors();
  select.innerHTML = '';
  floors.forEach((f) => {
    const opt = document.createElement('option');
    opt.value = String(f.floorId);
    opt.textContent = f.shortName['en'] ?? f.longName['en'] ?? '';
    select.appendChild(opt);
  });
}

await populateFloors();

maps.on('floorChange', (floorInfo) => {
  select.value = String(floorInfo.floorId);
});

select.addEventListener('change', () => {
  maps.navigateToFloorById(Number(select.value));
});

Cross-building routing

When routing between an origin in one building and a destination in another, pass both building and entity IDs in the routing boost string. The iframe handles the building transition as part of the route steps automatically. Use buildingChange / floorChange to observe when the active view switches during route playback.

CDN:

html
<script>
  await mapsted.maps.init({ element: '#map' });

  // Routing boost: "buildingId:entityId,buildingId:entityId"
  await mapsted.maps.applyBoost(
    mapsted.maps.createBoostRouting('42:1001,43:2005')
  );

  mapsted.maps.on('floorChange', (floorInfo) => {
    console.log('Route progressed to floor:', floorInfo.shortName['en'] ?? floorInfo.longName['en'] ?? '');
  });
</script>

npm:

js
import * as maps from '@mapsted/maps-js-api';

await maps.init({ element: '#map', propertyId: 1234 });

await maps.applyBoost(maps.createBoostRouting('42:1001,43:2005'));

maps.on('floorChange', (floorInfo) => {
  console.log('Route progressed to floor:', floorInfo.shortName['en'] ?? floorInfo.longName['en'] ?? '');
});

Reading static building metadata

getBuildingInfo(buildingId) returns metadata about a specific building without requiring navigation into it. It is useful for populating a directory UI (floor count, building name) before the user selects a building.

buildingId is a numbernot a string. Building IDs must be obtained from the Mapsted CMS or your own backend (see Known API gaps for why there is no getBuildings() yet).

The return type is BuildingInfo:

ts
interface BuildingInfo {
  buildingId: number;
  name: MultiLangString | null;   // locale map — use name['en'] for display
  entityId: MapstedId | null;
  levels: unknown[];              // raw CMS level objects (floor count = levels.length)
}

CDN:

html
<script src="https://mapi.mapsted.com/v4.0.1/maps.js?id=1234"></script>
<script>
  await mapsted.maps.init({ element: '#map' });

  const info = await mapsted.maps.getBuildingInfo(42);
  const displayName = info.name?.['en'] ?? `Building ${info.buildingId}`;
  console.log(displayName, '—', info.levels.length, 'floor(s)');
</script>

npm:

js
import * as maps from '@mapsted/maps-js-api';

await maps.init({ element: '#map', propertyId: 1234 });

const info = await maps.getBuildingInfo(42);
const displayName = info.name?.['en'] ?? `Building ${info.buildingId}`;
console.log(displayName, '—', info.levels.length, 'floor(s)');

getBuildingInfo throws:

Error codeCondition
MAPSTED-1090API is not yet READY
MAPSTED-1012buildingId is null or undefined
MAPSTED-1013buildingId is not a number
MAPSTED-1086Building not found for this property

Known API gaps

Missing getBuildings() API The API does not expose a getBuildings() method. There is no call in the current API surface that enumerates buildings for the loaded property. Consumers must obtain building IDs out-of-band (e.g., from the Mapsted CMS or a backend configuration). A getBuildings(): Promise<BuildingInfo[]> method — mirroring the getFloors pattern — is planned for a future release. Contact info@mapsted.com to register interest.

navigateToBuilding()navigateToBuilding({ buildingId, floorId? }) moves the map to a building, optionally focusing a floor within it (only buildingId is required). Switch floors within the active building with navigateToFloorById / navigateToFloorByName, and observe transitions with the buildingChange event.