Mapwize.js

The SDK is built as a mapbox-gl 0.48.x plugin. Mapbox GL is included in the package so you don't have to worry about importing it. Mapwize.js is all you need.

The package is exposed as Mapwize.

Here are the specific instructions for using Mapwize. Please refer to the mapbox-gl 0.45 Doc for all the Mapbox related options.

Browser support

The SDK is tested against the following browsers:

Install Mapwize

You can install Mapwize in your web project using NPM

npm install mapwize

You can also download mapwize.js directly from your favourite CDN like
jsdelivr.com/package/npm/mapwize, or use the CDN url directly in your HTML page:

<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/mapwize@3.1.9/mapwize.js"></script>

Setup your API key

First of all, you have to setup your API key:

Mapwize.apiKey(<your_api_key>);

Your API keys can be managed in Mapwize Studio.

Display the Mapwize map

The simplest way to display a Mapwize map:

<html>
    <head>
        <script type="text/javascript" src="mapwize.js"></script>
        <style>
            #mapwize {
                height: 500px;
            }
        </style>
    </head>
    <body>
        <div id="mapwize"></div>
        <script>
            Mapwize.apiKey(<YOUR_MAPWIZE_API_KEY_HERE>)
            const map = new Mapwize.Map({
                container: 'mapwize'
            });

            map.on('mapwize:ready', () => {
                // Mapwize map is now ready to be used
            });
            map.on('mapwize:loaderror', err => {
                // Something bad happened during Mapwize loading
                console.error(err);
            });
        </script>
    </body>
</html>

There has to be a div for where the map is going to go. This div can have a css style like for example

    #myMapId {
        position:absolute; top:0; bottom:0; width:100%; height: 100%;
    }

for a full screen display. Pay attention to have <div id="myMapId"></div> and not <div id="myMapId"/> as the second case will NOT work.

The map view will display:

Map constructor

Options can be passed to the map when created

new Mapwize.Map(MapboxOptions, MapwizeOptions);
/*
 * MapboxOptions: The options for the map (see further for all possible options)
 * MapwizeOptions: The options for the map (see further for all possible options)
 */

All Mapbox options can be found here: https://www.mapbox.com/mapbox-gl-js/api/#map

Possible Mapwize options:

Limit the visible area

The area the user can browse can be limited to a given bound. To do so, use the Mapbox map options maxBounds and minZoom at initialization of the map. Example:

Center the map

Center on coordinates

You can center the map on given coordinates defined by

You can give the center and zoom options at creation time:

You can also use the flyTo, jumpTo or easeTo methods to move the map.

map.flyTo([longitude, latitude], eventData);
map.setZoom(19);

Center on venue

You can center the map on a venue by calling centerOnVenue.
Venue objects can be retrieved using the Mapwize.Api.getVenue('venueId').then(venue => {}) method.

centerOnVenue (venue, options, fn)

map.centerOnVenue('venueId');
map.centerOnVenue(venue);

Center on place

You can center the map on a given place by calling centerOnPlace. The floor is automatically selected based on the place. Place objects can be retrieved using the Mapwize.Api.getPlace method.

centerOnPlace (place, options, fn)

map.centerOnPlace('placeId');
map.centerOnPlace(place);

Fit a given area

You can set the map so that a given bound is completely displayed. This takes the margins into account.

map.fitBounds([
    [-74.227, 40.712],
    [-74.125, 40.774]
], [options, [eventData]]);

Besides the default options supported by Mapbox, options can also accept minZoom as an integer. Note that if minZoom is used, the entire bounds might not be displayed.

Floors

Venues usually have multiple floors. The floor controller let the user change floor. But the floors can also be controlled programatically.

Get

Get the displayed floor

var floor = map.getFloor(); // Return the floor of displayed venue else return null
var floor = map.getFloorForVenue(venueObject); // Return the active floor of targeted venue

Get the list of active floors on the current view. A floor is considered active if the geometry of one layer of that floor is intersecting with the visible region on the screen.

var floors = map.getFloors(); // Returns the floors of displayed venue as an array else return empty array
var floors = map.getFloorsForVenue(venueObject); // return the floors of targeted venue as an array

Set

Set the floor to be displayed

map.setFloor(floor[, eventParams]); // Set floor for displayed venue (floor must be an int or null)
map.setFloorForVenue(floor, venueObject[, eventParams]); // Set floor for targeted venue

eventParams is an optional object that is added to mapwize:floorchange event data

Promoting places

By default, places are displayed (or not) based on their isVisible attributes. Their display order is based on their order property. It is possible to modify the default behavior using the following methods.

You can promote places so they will be displayed on top of any other. The order in which promoted places are displayed is set by the order in the promotePlaces list. Please note that:

To add a single place in promoted list

map.addPromotedPlace(placeObject); // Add the place at the end of the list

To add a multiple places in promoted list

map.addPromotedPlaces(listOfplaceObjects); // Add places at the end of the list

To remove a place from promoted list

map.removePromotedPlace(placeObject);

To remove multiple places from promoted list

map.removePromotedPlaces(listOfplaceObjects);

To remove all promoted place for a venue

map.removePromotedPlacesForVenue(venueObject);

Display directions

You can display directions on the map, either between 2 points or through a list of waypoints, as long as all the points are in the same venue.

You can get the directions first using the API and then display all or portion of the directions using:

Mapwize.Api.getDirection({
    from: {},
    to: {},
    waypoints: [],
    options: {}
}).then(direction => map.setDirection(direction));

The from parameter is required and is an objects which can have the following properties:

{
    placeId: string (the Id of a place. If used, latitude/longitude/floor/venueId are ignored)
    latitude: number (if used, all latitude/longitude/floor are required)
    longitude: number (if used, all latitude/longitude/floor are required)
    floor: number (if used, all latitude/longitude/floor are required)
    venueId: string (the Id of the venue the latitude/longitude is in. Only required if the venue cannot be inferred from the to and the waypoints)
}

The to parameter is required. It can be an object, with the same structure as the From, so the destination is fixed. It can also be an array, and in that case, the closest destination is used. It can also be an object refering to a placeList, and in that case the closest place of the list if used:

{
    placeListId: string (the Id of a placeList)
}

For the waypoints, you can specify an array with objects with the same structure as the From.

The options parameter is an object supporting the following properties:

{
    isAccessible: boolean (if set to true, only routes and connectors accessible to people with disabilities are used in the computation. Default is false)
    waypointOptimize: boolean (if set to true, the order of the waypoints is optimized to minimize the total time of the directions. Default is false)
}

Directions is an object containing the following properties:

{
    from: from object as above,
    to: to object as above,
    distance: total distance in meters,
    traveltime: total time in seconds,
    bounds: bounds containing the total route,
    route: [ a list of paths on different floors
        floor: the floor number of the route
        path: the list of coordinates on the way points
        distance: the distance of the route in meter
        bounds: the bounds of the route
        isStart: if the route of the first one
        isEnd: if the route is the last one
        fromFloor: the floor of the route before
        toFloor: the floor of the route after
        connectorTypeTo: the type of connector used to go to the next floor
        connectorTypeFrom: the type of connector used to come from the previous floor
    ],
    waypoints: list of waypoints, ordered,
    subdirections: directions object with the same structure as the parent for each step between waypoints.
}

To remove the directions from the map, use the method removeDirection

map.removeDirection();

User position

Display user position

By default, if the user position is available, it is displayed. You can prevent the user location from being displayed by setting the userPosition map option to false:

Mapwize.apiKey(<YOUR_MAPWIZE_API_KEY_HERE>)
var map = new Mapwize.Map({
    container: 'myMapId',
    userPosition: false
});

If userPosition is not false, the control proposing the user to go to its position is displayed by default. You can disable it by setting the userPositionControl map option to false:

Mapwize.apiKey(<YOUR_MAPWIZE_API_KEY_HERE>)
var map = new Mapwize.Map({
    container: 'myMapId',
    userPositionControl: false
});

Use browser location

By default, the user position is acquired from the web browser if available. You can disable it by setting the useBrowserLocation map option to false:

Mapwize.apiKey(<YOUR_MAPWIZE_API_KEY_HERE>)
var map = new Mapwize.Map({
    container: 'myMapId',
    useBrowserLocation: false
});

Follow user mode

The follow user mode allows to have the map moving and/or rotating as the position is updated.
You can manage the followUserMode using the following commands:

map.getFollowUserMode();
map.setFollowUserMode('NONE'|'FOLLOW_USER'|'FOLLOW_USER_AND_HEADING');

Center map on user position

To center the map on the current user position, you can use the centerOnUser method.

map.centerOnUser();

Get user position

You can get the current user position using the method

map.getUserPosition();

The returned object has the following properties:

{
    latitude: the latitude
    longitude: the longitude
    floor: the floor (null if ouside a building or unknown)
    accuracy: the radius in meter in which the user has a high probability to actually be, on the current floor. There is no vertical accuracy.
    timestamp: the unix timestamp at which the position was acquired.
}

Setting the user position

You can manually set the user position by using the setUserPosition method:

map.setUserPosition({
    latitude: 40.712,
    longitude: -74.227,
    floor: 2,
    accuracy: 5
});

The accuracy is specified in meters. At this point the accuracy is only on horizontal position. There is no accuracy on floor.

If the followUserMode is enabled, then this methods will have as consequence to move the map. Otherwize, only the user position dot will be moved.

Using the setUserPosition method will override the location prodided by the browser.

User heading

When the device can provide the user's heading, the SDK is using it to display the heading on the map and allow the map to rotate with the user using the followUserMode.

You can disable this feature by setting useBrowserPosition to false in the map options.

You can get the user heading using the map.getUserHeading() method or by listening to the mapwize:userheadingchange event.

Parse a mapwize URL

Mapwize.Api.parseUrl(url);

The promise returns an error (if any) and the parsed object in the following format

{
    venue: the venue object to which the url relates.
    universe: the universe object if the ?u parameter is specified in the url
    language: the language code if the ?l parameter is specified in the url
    accessKey: the accessKey if the ?k parameter is specified in the url.
    floor: the value of the floor if specified in the url, or the floor of the place, or the start floor of the direction
    zoom: the zoom if ?z parameter is specified
    userPosition: a user position object with lat lon floor if the url is a beacon, or if the direction starts from the beacon
    from: object with the origin of the direction if direction url starting from the place.
    to: object with the venue, place or placelist for related urls or the destination of the direction.
    direction: direction object if it's a direction url, or null
    bounds: the bounds that should be set to the map to properly display the url
}

Example

Mapwize.Api.parseUrl(url).then(parsedUrl => {
    // Do something with parsedUrl
}).catch(err => {
    console.error(err);
});

Markers

Adding marker

You can add markers on the map to show a position of interest.

To add a marker, use the function

map.addMarker(position[, customMarker]).then(marker => {
    // do something or store marker reference
}).catch(err => {
    // Error, if any
});
// OR
map.addMarkerOnPlace(placeObject[, customMarker]).then(marker => {
    // do something or store marker reference
}).catch(err => {
    // Error, if any
});

where position is an object with the following properties (with same priority order):

{
    latitude: number
    longitude: number
    floor: number (can be null)
}

To use your own marker style, use the optional customMarker attribute. It must be a mapbox marker object.

Example:

const el = document.createElement('div');
el.className = 'marker my-custom-marker';
el.addEventListener('click', () => {
    // Listen click on your custom marker
});

const myCustomMarker = new mapboxgl.Marker(el);

map.addMarker({
    latitude:  40.712,
    longitude: -74.227,
    floor:  2,
}, myCustomMarker).then((marker => {
    // Marker as been added on map
}).catch(err => {
    return  console.error('addMarker failed', err);
});

Marker click

The event mapwize:markerclick is fired when a marker is clicked

map.on('mapwize:markerclick', e => {
    console.log('marker: ' + e.marker);
});

Remove marker

Remove one marker

To remove only one marker, use the function

map.removeMarker(marker);

marker is returned by addMarker promise

Remove all markers

To remove all the markers at once, use the function

map.removeMarkers();

Listen for events

The map will emit various events you can listen to.

All Mapbox events are triggered as usual. Feel free to use them.

Mapwize specific events are also triggered.

Ready

Fired when the Mapwize plugin is ready to be used. Any call to the plugin before this event might generate errors.

map.on('mapwize:ready', () => {
    console.log('Mapwize is ready');
});

Loading error

Fired when the Mapwize plugin gets an error during the initialization phase

This error is critical and blocks data loading. Map will be blank.

map.on('mapwize:loaderror', (e) => {
    console.log('There was an error during Mapwize loading', e);
});

Click

Fired when the user clicks (or taps) the map, a place or a venue icon.

map.on('mapwize:click', e => {
    console.log(e);
});

Where e is an object with the following properties:

{
    place: place object (can be null)
    venue: venue object (can be null)
    lnglat: lnglatlike
    floor: number (can be null)
}

Floor change

Fired when the currently viewed floor is changed.

map.on('mapwize:floorchange', e => {
    console.log('Floor changed to ' + e.floor);
});

Floors change

Fired when the list of available floors at the currently viewed location is changed.

map.on('mapwize:floorschange', e => {
    console.log('Available floors at currently viewed location changed to ' + e.floors);
});

Margins change

Fired when the map margins have changed

map.on('mapwize:marginschange', e => {
    console.log('margins: ' + e.margins);
});

Direction events

Direction start

Fired when a direction has just started

map.on('mapwize:directionstart', e => {
    console.log('directionstart: ', e);
});

Direction stop

Fired when direction has stopped

map.on('mapwize:directionstop', e => {
    console.log('directionstop');
});

User position change

Fired when the user position has changed.

map.on('mapwize:userpositionchange', e => {
    console.log('User position changed to ' + e.userPosition);
});

User heading change

Fired when the user heading has changed.

map.on('mapwize:userheadingchange', e => {
    console.log('User heading changed to ' + e.userHeading);
});

Venue will enter and venue enter

mapwize:venuewillenter is fired when map enters in venue and starts loading venue data
mapwize:venueenter is fired when venue is fully loaded and displayed on map
mapwize:venueentererror is fired if an error is encountered during venue load

map.on('mapwize:venuewillenter', venue => {
    console.log('Venue will enter: ' + venue);
});
map.on('mapwize:venueenter', venue => {
    console.log('Venue entered: ' + venue);
});
map.on('mapwize:venueentererror', error => {
    console.log('Venue enter failed: ' + error);
});

Venue refresh

Fired when displayed venue is refreshed (due to map.refresh() or granting access)

map.on('mapwize:venuerefresh', venue => {
    console.log('Venue refreshed: ' + venue);
});

Venue exit

Fired when leaving the venue that was previously entered

map.on('mapwize:venueexit', venue => {
    console.log('Venue exited: ' + venue);
});

Private venues

To be able to access the map of private venues, you need to use an API key or an Access key with read permissions.

The simplest solution is to give permissions to your API key. Permissions can be given in Mapwize Studio.

If you need to be able to add access dynamically to each user session, you will need to use access keys. You can create access keys in Mapwize Studio. Please note that if you ue access keys, a user cookie session need to be used by the SDK. TO grant access using an access key, use the grantAccess method.

map.grantAccess('key').then(() => {
    // NO error, key is valid
}).catch(err => {
    // ERROR, key is not valid
});

Custom main color

By default, Mapwize's color is used for the following elements of the interface:

To use your own color, simply set the color parameter in the map options. The color has to be a string with a valid CSS color like blue or #00FF00.

Mapwize.apiKey(<YOUR_MAPWIZE_API_KEY_HERE>)
var  map = new Mapwize.Map({
    container: 'myMapId',
    color: 'blue'
});

Margins

It often happens that part of the map is hidden by banners or controls on the top or on the bottom. For example, if you display a banner to show the details of the place you just clicked on, it's better to display the banner on top of the map than having to resize the map.

However, you want to make sure that the Mapwize controls are always visible, like the followUserMode button and the floor selector. Also, that if you make a fitBounds, the area will be completely in the visible part of the map.

For this purpose, you can set a top and a bottom margin on the map. We garantee that nothing important will be displayed in those margin areas.

To set the margins, you can pass them in pixels when you intialize the map:

Mapwize.apiKey(<YOUR_MAPWIZE_API_KEY_HERE>)
var  map = new Mapwize.Map({
    container: 'myMapId',
    marginTop: 50,
    marginBottom: 50,
    marginRight: 50,
    marginLeft: 50
});

Or you can change them at runtime

map.setTopMargin(50);
map.setBottomMargin(50);
map.setRightMargin(50);
map.setLeftMargin(50);

Modify Place Style

setPlaceStyle

The style of a place can be modifyed directly within the SDK and can then override the style sent by the server. This is the best way to make changes in real-time on the map as it does not require to contact the Mapwize servers. For example, this can be used to display the availability of a meeting room.

map.setPlaceStyle(place, style);

where place is a place object or place id
where style is an object with the format:

{
    markerUrl: string (An url to the icon of the marker. Must be an image, ideally png, square, 100*100 pixels)
    strokeColor: string (The color of the shape border as #hex)
    strokeOpacity: number (The opacity of the border, between 0 and 1)
    strokeWidth: number (The width of the border)
    fillColor: string (The color of the inside of the shape as #hex)
    fillOpacity: number (The opacity of the inside, between 0 and 1)
    markerVisible: boolean
    polygonVisible: boolean
}

Example:

{
    markerUrl: 'http://myserver.com/image.png',
    strokeColor: '#C51586',
    strokeOpacity: 1,
    strokeWidth: 2,
    fillColor: '#FFFFFF',
    fillOpacity: 0.3,
    markerVisible: true,
    polygonVisible: true
}

Note that if a parameter is null, the value defined on the server will be used.

setPlacesStyle

map.setPlacesStyle(styles);

where styles is an object with the format:

{
    'place id': { /* style object, see setPlaceStyle method */ },
    'place id': { /* style object, see setPlaceStyle method */ },
    ...
}

Multilingual venues

Venues can support multiple languages.
By default, venues are displayed in their default language configured on the backend-side.
Using the function

map.setPreferredLanguage(language);

it is possible to set the preferred language of the user. If a venue supports the preferred language, it will be displayed in that language.
Otherwise, it will be displayed in the default language.
Languages are defined using 2 letter codes like 'en', 'fr', ...
Setting the preferred language to null displays all venues in their default language.

Working with universes

Defining multiple universes for a venue let you show different views with different permission levels. By default, the first universe which the user has access to is displayed.

Set universe for venue

Tu display a specific universe for a venue, set it with the setUniverseForVenue method

map.setUniverseForVenue(universeObject, venueObject);

This automaticaly refreshes the map if needed.

Get universe for venue

To know wich universe is set for a venue use getUniverseForVenue method

var universe = map.getUniverseForVenue(venueObject);

returns the universe or null if no universe was previously set.

Api

You can access the Mapwize API with the SDK by using Mapwize.Api.

Venues

get

Mapwize.Api.getVenue(venueId);
Arguments
Example
Mapwize.Api.getVenue('aValidVenueId').then((venue) => {
    console.log(venue);
});

list

Get a list of venues

Mapwize.Api.getVenues(query);
Arguments
{
    pick: (Array[String], optional) list of the fields returned by the api, by default all fields are returned
    names: (Array[String], optional) search by a list of names
    name: (String, optional) search by name
    alias: (String, optional) search by alias
    organizationId: (String, optionnal) filter by organization
    isPublished: (Boolean, optional) true|false|all

    // filter by latitude, you should use both together
    latitudeMin: (Number, optional)
    latitudeMax: (Number, optional)

    // filter by longitude, you should use both together
    longitudeMin: (Number, optional)
    longitudeMax: (Number, optional)
}
Example
// with empty options
Mapwize.Api.getVenues({}).then((venues) => {
    // venues contain all venues you can access
    console.log(venues);
});

// In defined area
Mapwize.Api.getVenues({
    latitudeMin:  0,
    latitudeMax:  1,
    longitudeMin:  0,
    longitudeMax:  1
}).then((venues) => {
    // venues contain all venues in the defined area
    console.log(venues);
});

Places

get

Mapwize.Api.getPlace(placeId);
Arguments
Example
// Using venue id
Mapwize.Api.getPlace('aValidPlaceId').then((place) => {
    console.log(place);
});

list

Get a list of places

Mapwize.Api.getPlaces(query);
Arguments
{
    pick: (Array[String], optional) list of the fields returned by the api, by default all fields are returned
    organizationId: (String, optional) filter by organization
    venueId: (String, optional) filter by venue
    venueAlias: (String, optional) filter by venue
    universeId: (String, optional) filter by universe
    name: (String, optional) filter by name
    alias: (String, optional) filter by alias
    placeTypeId: (String, optional) filter by place type
    floor: (Number, optional) filter by floor, places on floor null are always returned

    search: (String, optional) search in name and translations
    sort: (String, optional) sort result by defined field. Default: `order` field

    isSearchable: (Boolean, optional)
    isClickable: (Boolean, optional)
    isVisible: (Boolean, optional)
    isPublished: (Boolean, optional) true|false|all

    // filter by latitude, you should use both together
    latitudeMin: (Number, optional)
    latitudeMax: (Number, optional)
    // filter by longitude, you should use both together
    longitudeMin: (Number, optional)
    longitudeMax: (Number, optional)

    page: (Number, optional) Default: 0
    pageSize: (Number, optional) Default: 10000

    data.*: (Any, optional) filter result by custom data field
}
Example
// with empty options
Mapwize.Api.getPlaces({}).then((places) => {
    // places contain all places you can access
    console.log(places);
});
// In defined area
Mapwize.Api.getPlaces({
    latitudeMin:  0,
    latitudeMax:  1,
    longitudeMin:  0,
    longitudeMax:  1,
    floor:  1
}).then((places) => {
    // places contain all places in the defined area on floor 1 (and floor outdoor (null))
    console.log(places);
});

Layers

list

Get a list of layers

Mapwize.Api.getLayers(query);
Arguments
{
    pick: (Array[String], optional) list of the fields returned by the api, by default all fields are returned
    organizationId: (String, optional) filter by organization
    venueId: (String, optional) filter by venue
    venueAlias: (String, optional) filter by venue
    universeId: (String, optional) filter by universe
    floor: (Number, optional)
    importJob: (Boolean, optional)

    isPublished: (Boolean, optional) true|false|all

    // filter by latitude, you should use both together
    latitudeMin: (Number, optional)
    latitudeMax: (Number, optional)
    // filter by longitude, you should use both together
    longitudeMin: (Number, optional)
    longitudeMax: (Number, optional)

    data.*: (Any, optional) filter result by custom data field
}
Example
// with empty options
Mapwize.Api.getLayers({}).then((layers) => {
    // layers contain all layers you can access
    console.log(layers);
});
// In defined area
Mapwize.Api.getLayers({
    latitudeMin:  0,
    latitudeMax:  1,
    longitudeMin:  0,
    longitudeMax:  1,
    floor:  1
}).then((layers) => {
    // layers contain all layers in the defined area on floor 1 (and floor outdoor (null))
    console.log(layers);
});

Connector places

list

Get a list of connectorPlace

Mapwize.Api.getConnectorPlaces(query);
Arguments
{
    venueId: (String, required) a valid venue id

    pick: (Array[String], optional) list of the fields returned by the api, by default all fields are returned
    floor: (Number, optional)

    isPublished: (Boolean, optional) true|false|all

    // filter by latitude, you should use both together
    latitudeMin: (Number, optional)
    latitudeMax: (Number, optional)
    // filter by longitude, you should use both together
    longitudeMin: (Number, optional)
    longitudeMax: (Number, optional)
}
Example
// with empty options
Mapwize.Api.getConnectorPlaces({
    venueId: 'AValidVenueId'
}).then((connectorPlaces) => {
    // connectorPlaces contain all connectorPlaces you can access
    console.log(connectorPlaces);
});

// In defined area
Mapwize.Api.getConnectorPlaces({
    venueId: 'AValidVenueId',
    latitudeMin:  0,
    latitudeMax:  1,
    longitudeMin:  0,
    longitudeMax:  1,
    floor:  1
}).then((connectorPlaces) => {
    // connectorPlaces contain all connectorPlaces in the defined area on floor 1 (and floor outdoor (null))
    console.log(connectorPlaces);
});

Search in places, placeLists and venues

Mapwize.Api.search(query, options, callback);

Arguments

{
    query: (String)

    organizationId: (String, optional), filter by organization
    venueId: (String, optional), filter by venue
    universeId: (String, optional), filter by universe
    objectClass: (Array[String], optional) can contain ['place', 'placeList', 'venue'] If empty, all type can be returned
}

Example

// with empty options
Mapwize.Api.search({
    query: 'what you want to find',
    venueId:  'aValidVenueId'
}).then((results) => {
    console.log(results);
});

Custom Mapwize server

If you have your own Mapwize server, specify your api url using:

Mapwize.apiUrl(<your_api_url>);

By defaul the API url is https://api.mapwize.io/v1.