WK3 Handout
WK3 Handout
Overview
In this workshop, you will develop a simple Web app, which retrieves real-time MTR train data
via the MTR Next Train Open Data API. As shown in Fig. 1, the app provides two drop-down
selection lists for selecting an MTR line and the target station on that MTR line.
Fig. 1
Instead of listing all stations, you will design a selection menu that lists only the stations on
that selected MTR line. For example, Fig. 2. and Fig. 3 show the lists of stations on the Airport
Express line and Tseung Kwan O line respectively.
Fig. 2 Fig. 3
You will practice retrieving the JSON data using the fetch() promise call and extract the data
from the returned JSON data file. Then present the data at the space beneath the “Get Train
Data” button as shown in Fig. 4.
Fig. 4
Before using the API to access real-time MTR data, please download the two documents:
Data dictionary for Next Train API and Next Train API Specification.
https://opendata.mtr.com.hk/doc/Next_Train_DataDictionary_v1.2.pdf
https://opendata.mtr.com.hk/doc/Next_Train_API_Spec_v1.2.pdf
These two documents contain necessary information for you to understand the structure of
the returned JSON string and the meanings of various data objects (and terms) carried in the
JSON string.
For example, in the API specification document, it gives an example of the response JSON
string when the HTTP request is successful (as shown in Fig. 5) and another example of the
response when no data is available for that line/station (as shown in Fig. 6).
Fig. 6
Fig. 5
In the data dictionary document, we can find the required variables for using the API and the
meanings of various terms and objects in the returned JSON data. Fig. 7 gives you the screen
capture of the description of the UP/DOWN fields.
Fig. 7
For example, to query the next train arrival schedule of the Diamond station on the Tuen Ma
line, we need this URL:
https://rt.data.gov.hk/v1/transport/mtr/getSchedule.php?line=TML&sta=DIH
Copy this URL and paste it to the Chrome browser and then the Firefox browser; you should
find that Firefox presents the returned JSON data in a more visually useful way.
Fig. 8
Fig. 9
Use the same mechanism to create more requests to practice getting data on different lines and
stations.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>MTR Next Train</title>
<style>
span {
margin-right: 1.5em;
}
</style>
</head>
<body>
<h1>Using fetch to access MTR Next Train API</h1>
<label for="line">Choose the MTR line:</label>
<select name="line" id="line">
</select>
<br><br>
<label for="station">Choose the Station:</label>
<select name="station" id="station">
</select>
<br><br>
<button id="bttn">Get Train Data</button>
<div id="output" style="margin-top: 1rem"></div>
<script>
</script>
</body>
</html>
When the page (http://localhost:9080/WK3/) is loaded, both the selection lists are empty.
Fig. 10
Step 1: Fill in the selection options for selecting a line out of the five MTR lines. For example,
the following option is for selecting the Airport Express line and it is the default option.
<option value="AEL" selected>Airport Express</option>
The other options are: ‘TCL’ for the Tung Chung line, ‘TML’ for the Tuen Ma line, ‘TKL’ for the
Tseung Kwan O line, and ‘EAL’ for the East Rail line.
Step 2: Fill in the selection options for selecting a station out of the five stations on the
Airport Express line. For example, the following option is for selecting the Hong Kong station
on the Airport Express line.
<option class="AEL" value="HOK">Hong Kong</option>
To differentiate different stations on different lines, we add the class attribute and set its value
to “AEL” for all stations on the Airport Express line.
When done, the two selection lists will look as follows:
Fig. 11
Currently, we only have the stations on the Airport Express line, we need to use JavaScript to
change the set of stations from the AEL set to another set if the user selects another MTR line.
Step 3: We have five MTR lines and each line has its own set of stations. We are going to use
JavaScript to dynamically load the set of stations and set up the selection options by fetching
a “local” JSON file – lines.json, which contains the set of stations in all five MTR lines.
Use fetch() API to retrieve the lines.json file from the local server, i.e., localhost:9080, then
convert it to a JavaScript object. Enter the following code between the <script> tags.
<script>
STEP 4
STEP 5
})
})
</script>
Step 4: Use JavaScript to build a JavaScript object (Stations) that contains sets of selection
options for all MTR lines. The object contains five key/value pairs. Each key maps to the set of
station options for one MTR line. The result object would like as follows:
{
'AEL':
'<option class="AEL" value="HOK">Hong Kong</option>
:
<option class="AEL" value="AWE">AsiaWorld Expo</option>',
'TCL':
'<option class="TCL" value="HOK">Hong Kong</option>
:
<option class="TCL" value="TUC">Tung Chung</option>',
'TML':
'<option class="TML" value="WKS">Wu Kai Sha</option>
:
<option class="TML" value="TUM">Tuen Mun</option>',
'TKL':
'<option class="TKL" value="NOP">North Point</option>
:
<option class="TKL" value="POA">Po Lam</option>',
'EAL':
'<option class="EAL" value="ADM">Admiralty</option>
:
<option class="EAL" value="LMC">Lok Ma Chau</option>'
};
In addition, construct an associative array (stnList) for mapping a station’s acronym to the
station’s full name while parsing the lines.json object.
{ "HOK": "Hong Kong", "KOW": "Kowloon", "TSY": "Tsing Yi", "AIR": "Airport", "AWE": "AsiaWorld
Expo", "HOK": "Hong Kong", "KOW": "Kowloon", . . . ., "LHP": "LOHAS Park", "HAH": "Hang Hau",
"POA": "Po Lam" };
Step 5: Use JavaScript to check whether the user has selected a different MTR line. When
detecting there is a change of the selection option, an event handler will be executed to switch
the list of stations from the current set to the target set of stations according to the change.
let currentClass="AEL"; //assume Airport Express line initially
let line = document.getElementById('line');
line.addEventListener('change', (evt) => {
let select = line.value;
if (select != currentClass) { //there is a change
let station = document.querySelector('#station');
station.innerHTML = Stations[select];
currentClass=select;
}
});
Based on the selected MTR line, we access the Stations object to get the new set of station
options and replace the previous set. Be remembered to keep track of the selected MTR line.
Load the index.html file to the browser, you should see that the two selection lists working as
shown in Fig. 2 and Fig. 3.
Register an event handler for the “Get Train Data” button. Upon clicking on the button, a fetch()
request will be sent to the server with the correct ‘line’ and ‘sta’ parameters. When the
response returns, check whether the response status is successful; if it is successful, extract
the data from the returned JSON string and output the data to the <div> block with id=”output”.
The basic idea is to first check the return status of that line&station. If that line&station is
operating, the status is 1; otherwise, the status is 0. However, even the status is 1, the returned
data may not contain any train information, this would be reflected by the isdelay key. For
normal cases, the returned data may contain a set of train data for both the UP and DOWN
routes, or just UP/DOWN route as it depends on the station.
function fRequest() {
let line = document.getElementById('line').value; //get the MTR line
let station = document.getElementById('station').value; //get the station
fetch(`https://rt.data.gov.hk/v1/transport/mtr/getSchedule.php?line=${line}&sta=${station}`)
.then( response => {
if (response.status == 200) { //receive response successfully
response.json().then( schedule => {
let output = "";
} else {
if (schedule.isdelay == 'Y') { //Data Absence
//will handle this later
STEP 7
Load the index.html file to the browser and test the program by selecting an MTR line and a
station on that line, then click on the “Get Train Data” button to retrieve the data.
When received a successful response but with the returned JSON status code equals zero, the
MTR line is in special arrangement status or your query parameter(s) is/are not correct. Then
output the returned message and URL (if available).
output += schedule.message;
if (schedule.url)
output += `<br><a href='${schedule.url}'>${schedule.url}</a>`;
When received a successful response but with the returned JSON data ‘isdelay’ field equals
“Y”, this indicates the absence of data. Then output the following message.
output = "No data is available";
Now the program should be able to retrieve the next train arrival timings of the stations along
the five MTR lines. Also, it should be able to handle special cases.