In order to get the application working correctly, the document body
needs 4 main elements:
div
element to display the Maptable
element to display the Data Tablescript
element to include the Google Maps Libraryscript
element for all of the code needed to fetch and process data.
The first 2 elements need to have a unique id
for the JavaScript selectors to point to the correct
elements.
The table
element should have both the thead
and tbody
sections that will be populated through the code.
The first script
element that include the Google Maps Library will require an API key to from the Google
Developer Console. You can find more information about Google Maps API Keys here.
The last script
element is where all of the code will go to fetch and process the data from IIR API. For
the sake of this demo, the script will be included in the main HTML document.
<html> <head> <title>IIR API Demo</title> </head> <body> <div id="map"></div> <table id="table"> <thead></thead> <tbody></tbody> </table> <script src="https://maps.googleapis.com/maps/api/js?key=[YOUR_API_KEY]"></script> <script> // The magic goes here </script> </body> </html>
To get the Map to display and be able to interact with it, there needs to be 3 items:
vairable
that will store the map instancefunction
declared to initialize the mapfunction
to get the map to display
This code
will be placed withing the script
tags above on line 13
.
The variable
that stores the map is initially just a placeholder and will be set by the initialization
function
. This variable
will continue to be used throughout the script to reference and
manipulate the map.
The declared function initMap
will draw the map in the element with the id demo-map
with the
defined center and zoom properties that result in a global view. You can find complete documentation of the Google Maps
Initialization here.
Finally, initMap()
is called to execute the declared function in the previous step and will result in the
map being drawn into the supplied element.
// UI variables let map; const initMap = () => { map = new google.maps.Map(document.getElementById('map'), { center: { lat: 26.422, lng: -14.921 }, zoom: 1, }); }; initMap();
To make a successful API call, the following 3 items are required:
bearer token
to authorize the API callAPI endpoint
of a specific data setquery parameters
to identify a subset of the data
The bearer token
is required for all API calls. It is passed with the headers: Authorization
prameter. To generate or learn more about IIR Bearer tokens, take a look at the documentation here.
This example is going to query the offlineevents/summary
endpoint to get a list of summarized offline events based on the query parameters
sent to the endpoint.
The query parameters
for this example include 4 types:
eventKind
eventStatusDesc
unitTypeID
industryCode
In the code provided, the API variables
are added to the top of the script to hold the lengthy
strings
needed to make successful API calls.
A new function
called getInitialData
is added to fetch the first set of data needed.
fetch()
is used to make a POST
request to the defined offlineEventsURL
endpoint.
When the fetch()
completes its call, it returns a response
to the .then()
method
which will convert the response
to JSON
and pass it to the next method.
The last .then()
method in the chain will be where the code for processing the initial data will go.
The getInitialData()
function gets called at the end of the initMap()
function to
keep the order of operations intact.
Note: The new JavaScript additions are added above initMap()
.
// API variables const barerToken = 'YOUR_BEARER_TOKEN', offlineEventsUrl = 'https://api.industrialinfo.com/idb/v1.1/offlineevents/summary?', offlineQueryParameters = 'eventKind=S&eventStatusDesc=Ongoing&unitTypeId=00203&industryCode=04'; // UI variables let map; const initMap = () => { ... getInitialData(); }; const getInitialData = () => { fetch(offlineEventsURL + offlineQueryParameters, { method: 'POST', headers: { Authorization: 'Bearer ' + bearerToken, }, 'Content-Type': 'application/json', }) .then((response) => { return response.json() }) .then((json) => { // process the JSON data response }) } initMap();
Now that the data has returned from the first fetch
call, the resulting JSON has 2 main sections:
The top level summary has information such as the totla result count, the returned result count, and the offset (used for pagination).
For this example, the list of data is all that will be used. Each API endpoint will have a different parameter for the returned data set.
Since Offline Events was requested, the parameter is offlineEvents
.
In the code provided, a new variable
is added to identify the Data Table element and a new function
called displayTableData
is added to process the data and display
in the table. It expects 1 parameter to be supplied: data
This function adds a table row (tr
) with table header cells (th
) to the inside of the empty thead
of the table element.
Then, the function loops through the JSON data using forEach
and adds table rows (tr
) with
table data cells (td
) to the inside of the empty tbody
of the table element.
The tbody
loop uses template literals
to access the information in each object
of the returned dataset, eg: ${event.unitName}
.
The displayTableData()
function gets called at the end of the final .then()
method of getInitialData()
function to
keep the order of operations intact.
Note: The new JavaScript additions are added above initMap()
.
{ limit: 100, offlineEvents: Array(3) [ {…}, {…}, {…} ], offset: 0, resultCount: 3, totalCount: 3 }
// UI variables let map, table = document.getElementById('table'); const getInitialData = () => { fetch(...) .then(...) .then((json) => { displayTableData(json.offlineEvents); }); } const displayTableData = (data) => { // add table head row table.tHead.innerHTML = ` <tr> <th>Unit Name</th> <th>Unit ID</th> <th>Offline Capacity</th> <th>Event Type</th> </tr>`; // add table body rows table.tBodies[0].innerHTML = ''; data.forEach((event) => { table.tBodies[0].innerHTML += ` <tr> <td>${event.unitName}</td> <td>${event.unitId}</td> <td>${event.offlineCapacity.capacityOffline} ${event.offlineCapacity.uom}</td> <td>${event.eventType}</td> </tr>`; }); } initMap();
Same as the first API call, the following 3 items are required: the bearer token
, an
API endpoint
and a set of query parameters
In the code provided, a new API variable
is added to the top of the script to hold the endpoint for the plant
details call.
Two new functions
are added. The first one, extractPlantIDs
, is used to create an array of unique plant IDs
based on a the data set provided to it. The second one, getPlantData
, preforms similar to the getInitialData
function above.
The only difference between the functions extractPlantIDs
and getPlantData
, is that the query parameter
string is built within the function of getPlantData
by joining the array of unique plant IDs.
The getPlantData()
function gets called at the end of the final .then()
method of getInitialData()
function to keep the order of operations intact.
Note: The new JavaScript additions are added above initMap()
.
// API variables const ..., plantDetailsUrl = 'https://api.industrialinfo.com/idb/v1.1/plants/detail?'; const getInitialData = () => { fetch(...) .then(...) .then((json) => { ... getPlantData(extractPlantIDs(json.offlineEvents)); }); } const extractPlantIDs = (data) => { return [ ...new Set( data.map((result) => { return result.plantId }) ) ]; } const getPlantData = (data) => { const plantIdQueryString = 'plantId=' + data.join('&plantId=') fetch(plantDetailsURL + plantIdQueryString, { method: 'POST', headers: { Authorization: 'Bearer ' + bearerToken, }, 'Content-Type': 'application/json', }) .then((response) => { return response.json() }) .then((json) => { // process plant details response }); } initMap();
The final step of this example is to process and display the returned plant data on the map.
With this latest API endpoint, notice that the parameter for the returned data set has changed.
Since Plants was requested, the parameter is now plants
.
In the code provided, a new function called displayPlantData
is added to process the data and display
the markers. It expects 1 parameter to be supplied: data
The displayPlantData()
function loops through the returned plant data using forEach
and creates
a Google Maps Marker on the map with an accompanying InfoWindow bound together with a click listener
.
Follow these links for more information on Google Maps Markers
and InfoWindows.
The displayPlantData()
function gets called at the end of the final .then()
method of
getPlantData()
function to keep the order of operations intact.
Note: The new JavaScript additions are added above initMap()
.
{ limit: 100, plants: Array(3) [ {…}, {…}, {…} ], offset: 0, resultCount: 3, totalCount: 3 }
const getPlantData = () => { fetch(...) .then(...) .then((json) => { displayPlantData(json.plants); }); } const displayPlantData = (data) => { data.forEach((plant) => { const marker = new google.maps.Marker({ position: { lat: plant.latitude, lng: plant.longitude }, map: map, title: plant.plantName }); const infowindow = new google.maps.InfoWindow({ content: plant.plantName }); marker.addListener('click', () => { infowindow.open(map, marker); }); }); } initMap();
<html> <head> <title>IIR API Demo</title> </head> <body> <div id="map"></div> <table id="table"> <thead></thead> <tbody></tbody> </table> <script src="https://maps.googleapis.com/maps/api/js?key=[YOUR_API_KEY]"></script> <script> // API variables const barerToken = 'YOUR_BEARER_TOKEN', offlineEventsUrl = 'https://api.industrialinfo.com/idb/v1.1/offlineevents/summary?', offlineQueryParameters = 'eventKind=S&eventStatusDesc=Ongoing&unitTypeId=00203&industryCode=04', plantDetailsUrl = 'https://api.industrialinfo.com/idb/v1.1/plants/detail?'; // UI variables let map, table = document.getElementById('table'); const initMap = () => { map = new google.maps.Map(document.getElementById('map'), { center: { lat: 26.422, lng: -14.921 }, zoom: 1, }); getInitialData(); }; const getInitialData = () => { fetch(offlineEventsURL + offlineQueryParameters, { method: 'POST', headers: { Authorization: 'Bearer ' + bearerToken, }, 'Content-Type': 'application/json', }) .then((response) => { return response.json() }) .then((json) => { displayTableData(json.offlineEvents); }); } const displayTableData = (data) => { // add table head row table.tHead.innerHTML = ` <tr> <th>Unit Name</th> <th>Unit ID</th> <th>Offline Capacity</th> <th>Event Type</th> </tr>`; // add table body rows table.tBodies[0].innerHTML = ''; data.forEach((event) => { table.tBodies[0].innerHTML += ` <tr> <td>${event.unitName}</td> <td>${event.unitId}</td> <td>${event.offlineCapacity.capacityOffline} ${event.offlineCapacity.uom}</td> <td>${event.eventType}</td> </tr>`; }); } const extractPlantIDs = (data) => { return [ ...new Set( data.map((result) => { return result.plantId }) ) ]; } const getPlantData = (data) => { const plantIdQueryString = 'plantId=' + data.join('&plantId=') fetch(plantDetailsURL + plantIdQueryString, { method: 'POST', headers: { Authorization: 'Bearer ' + bearerToken, }, 'Content-Type': 'application/json', }) .then((response) => { return response.json() }) .then((json) => { displayPlantData(json.plants); }) } const displayPlantData = (data) => { data.forEach((plant) => { const marker = new google.maps.Marker({ position: { lat: plant.latitude, lng: plant.longitude }, map: map, title: plant.plantName }); const infowindow = new google.maps.InfoWindow({ content: plant.plantName }); marker.addListener('click', () => { infowindow.open(map, marker); }); }); } initMap(); </script> </body> </html>