Appearance
Floor Navigation
Programmatically move between floors, build a custom floor picker UI, and react to floor changes in real time.
Prerequisites
- A working map embed — complete Embed your first map first.
- The map must be ready before calling navigation methods. Put navigation calls inside the
onloadcallback. getFloors()returns aPromise— resolve it with.then()orawait. It also only returns floor data once the user has entered a building (outdoor view resolves to[]). CallselectEntity(buildingId)to drive into a building, then readgetFloors()after thefloorChangeevent fires.
Steps
1. Fetch the list of floors with getFloors
getFloors returns a Promise<FloorInfo[]> for the currently loaded building. Each FloorInfo object includes floorId, floorNumber, longName, and shortName. Both longName and shortName are MultiLangString objects (Record<string, string>) — locale codes map to display strings, e.g. { en: "Ground Floor", fr: "Rez-de-chaussée" }. Access the English label with floor.shortName['en'] ?? floor.longName['en'].
getFloors() returns a Promise — always resolve it with .then() or await. It only returns data once the user has entered a building (outdoor view resolves to []).
javascript
mapsted.maps.init({
element: document.getElementById("mapsted-map"),
propertyId: 603,
onload: function () {
// Enter a building first so getFloors() has data.
mapsted.maps.selectEntity(22); // CAW Student Centre
const unsub = mapsted.maps.once("floorChange", function () {
mapsted.maps.getFloors().then(function (floors) {
console.log(floors);
/*
[
{ floorId: 1355, shortName: { en: "L1" }, longName: { en: "Level 1" }, floorNumber: 1 },
{ floorId: 1356, shortName: { en: "L2" }, longName: { en: "Level 2" }, floorNumber: 2 },
…
]
*/
floors.forEach(function (floor) {
var label = floor.shortName['en'] ?? floor.longName['en'] ?? ('Floor ' + floor.floorNumber);
console.log('Floor ' + floor.floorId + ': ' + label + ' (floorNumber ' + floor.floorNumber + ')');
});
});
});
}
});2. Build a simple floor picker
Use the getFloors result to render buttons that drive navigation.
javascript
mapsted.maps.init({
element: document.getElementById("mapsted-map"),
propertyId: 603,
onload: function () {
const picker = document.getElementById("floor-picker");
function renderPicker(floors) {
picker.innerHTML = "";
floors.forEach(function (floor) {
const btn = document.createElement("button");
// shortName and longName are MultiLangString (Record<string, string>)
btn.textContent = floor.shortName['en'] ?? floor.longName['en'] ?? ('Floor ' + floor.floorNumber);
btn.addEventListener("click", function () {
mapsted.maps.navigateToFloorById(floor.floorId);
});
picker.appendChild(btn);
});
}
// Drive into a building so floors populate, then re-render the
// picker every time the floor changes.
mapsted.maps.selectEntity(22); // CAW Student Centre (property 603)
mapsted.maps.on("floorChange", function () {
mapsted.maps.getFloors().then(renderPicker);
});
}
});On your own page, add a container the picker can mount into:
html
<div id="floor-picker" style="position:absolute; top:16px; right:16px; z-index:10;"></div>Note. The in-page sandbox only ships a
#mapsted-mapcontainer. The embedded version above creates the picker dynamically as a positioned overlay; your own page can use the#floor-pickerdiv shown here.
3. Change floor by name with navigateToFloorByName
When you know the display name of the floor, pass it directly. The match is case-sensitive and must equal the English short name returned in shortName['en'] from getFloors().
javascript
mapsted.maps.navigateToFloorByName("L2");4. Change floor by ID with navigateToFloorById
Use the numeric floorId for a reliable match that is unaffected by localization or name changes.
javascript
mapsted.maps.navigateToFloorById(1356);V2/V3 floor navigation methods deprecated
mapsted.maps.changeFloorById() and mapsted.maps.changeFloorByName() are deprecated V2/V3 compatibility shims. They emit a console.warn and throw MAPSTED-1093 in strict mode. Use the canonical methods navigateToFloorById() and navigateToFloorByName() shown above.
5. Listen for floor changes
Subscribe to the floorChange event to keep your custom UI in sync whenever the floor changes — whether triggered by your code or by the built-in floor selector.
javascript
mapsted.maps.on("floorChange", function (payload) {
// FloorInfo: { floorId, floorNumber, longName: Record<string,string>, shortName: Record<string,string> }
var label = payload.shortName['en'] ?? payload.longName['en'] ?? ('Floor ' + payload.floorNumber);
console.log("Now on floor:", payload.floorId, label);
// highlight the matching button in your custom picker
document.querySelectorAll("#floor-picker button").forEach(function (btn) {
btn.classList.toggle("active", btn.textContent === label);
});
});6. Move to a different building
If your property has multiple buildings, select the building entity and recenter the map; floorChange fires once the building loads its default floor.
javascript
mapsted.maps.selectEntity(buildingId);
// Optionally recenter the viewport on the building's footprint.
// setViewport is the current method; setMapView is a legacy alias kept
// for backward compatibility.
mapsted.maps.setViewport({ mapCenter: buildingCenter });
mapsted.maps.on("floorChange", function () {
// fires once the building loads its default floor
// getFloors() returns a Promise<FloorInfo[]> — always await or .then()
mapsted.maps.getFloors().then(function (floors) {
console.log("New building floors:", floors);
});
});Expected output
Clicking a button in the custom floor picker animates the map to the selected floor. The browser console logs the floorChange event with the updated floorId and shortName['en']. The active button in the picker reflects the current floor at all times.
Next steps
- Place markers on a specific floor after navigating: Markers and popups
- Calculate walking distances between floors: Distance calculation
- Set up turn-by-turn routing: Indoor routing