Here is how we would break down the AM3 app:
input
, textarea
,
button
, etc.) to provide the way for user to enter it, as well
as some Javascript/jQuery code to collect the information and user it further.The interface for gathering user input has only three elements: input
,
textarea
and a button
. All of them were styled with CSS to
change their appearance to fit the page look. For the purposes of building the app,
you don't need to deal with the CSS at this point.
The elements are showing step-by-step on the page, because they are hidden with the property
display : none
. When a user presses "enter" on the keyboard, the next
elements becomes visible. To detect that an "enter" event was triggered, we use the
onkeypress
event attribute in combination with the ASCII code for the
"enter" key, which is 13. If you have never come across the ASCII code before,
here is
a very short summary.
Here is a short example of using the onkeypress
event, which shows how
the function can take an optional parameters, e
that refers to the event
being handled.
Type some text in the box and see the ASCII code for each of them.
var input = document.getElementById("box"); var p = document.getElementById("text"); input.onkeypress = function (e) { p.innerHTML += "Key code is: " + e.which + " Character is: " + String.fromCharCode(e.which) + "<br>"; };
I have also prepared a jsFiddle where you can play and change this example. Knowing that the chode for "enter" is 13, you can perform a test to make something happen on the page.
The AM3 app uses two API: the Wikipedia API to retrieve information about a city/town, and the Google Maps API to find the geolocation of cities as well as calculate the distance between them.
To use the Wiki API we send an HTTP request as we did for the apps in AM1. Wiki API doesn't support CORS, thus, we'll need to use the JSONP method discussed in the AM1 notes. Below is how the URL of the request looks like:
http://en.wikipedia.org/w/api.php?format=json&action=query&generator=search&gsrsearch=Boston&gsrlimit=1&prop=pageimages|extracts&exintro&explaintext&exsentences=3&callback=functionNameHere
You can look at the results of this URL by clicking on this link.
Working with the Wikipedia API is a bit tricky, because their documentation is not very user-friendly. I was able to find what I needed in StackOverflow. Here are some things to have in mind:
gsrsearch=Boston
and appending at the end of the URL. This
means that you'll need to break the URL into parts, in order to concatenate the name of
each different city. The other bold parameter values are things you can change and
correspond to number of results, number of sentences to extract from the page, and the
name of your callback function to process the data. We will look at the Google Maps API requests on the next set of notes, given that we make such requests through the library provided by Google.
As you remember from AM1 and AM2, the response from the API will come in a JSON format. Often, you don't need everything that is stored in the response. However, you might want to store the response to avoid having to recall the API for multiple times. You can use arrays or objects of objects to store your information. You already know what arrays are (an array (Java) and a list (Python)) and that they store data sequentially. You need an index (0, 1, ..., length-1) to access every element.
An object of objects is often how the JSON data from an API will look like. The screenshot below shows the Wikipedia answer for the request in the previous section.
Notice how to access the information for Boston, we need to write query.pages["24437894"]
,
but, in general, we will not know in advance the id of a result. Thus, we will need to use a for loop
to iterate through the results to access every object in turn. Below is an example to try out. Try to
guess what the results will be, then, try it out on the console.
var merchItems = { "101": {"name": "Blue Socks", "price": 5.99}, "112": {"name": "Red Dress", "price": 34.99}, "245": {"name": "White Shirt", "price": 27.99} } for (var key in merchItems){ console.log(merchItems[key].name); }
Objects of objects can be used to store information too, that is easy to access if one knows the key. For example, in AM3 I have stored the town names in an array, and I stored the Wikipedia results in an object, where every property is the name of a city, and the value for each of them is the formatted results of the response (I have stored the HTML I want to show up in the info window). Similarly, I store the geocoding information for every city in an object of objects (see example below). Then, to show markers of every city, I take one element from the city names array, and use it as a key to retrieve the information from the stored Wikipedia results, and the coordinates from the Google results.
You might ask why store results? Because of delay (or latency). If we send the requests for information on the moment we want to show the markers on the page, it will take several milliseconds for the answer to appear. In fact, you can verify this in the screencast, by noticing how all the images (which are not on our computer) are displayed after the text.
In AM3, we use markers on the Google Map to display a location. Markers are objects in the Google Maps API that are easy to create and attach to the map.
Then, we use info windows attached to a marker to display HTML code within the window.
There is only one info window object that is used by the app. All markers share
that same object. This is why we only see one info window open a a time. If you
click on a different marker, the info window moves from one marker to the other. The object
info window has a method .setContent()
to which we can pass as an argument
a string that contains HTML code which we have prepared from the Wikipedia data, using
tags such as h1
for the name of the city, img
for the city photo,
and p
or span
to show the text. We can apply CSS to these elements,
in the same way we do for our normal page.
Finally, the names of the cities and the distances from the hometown to each of them are displayed in a transparent stripe at the bottom of the map. Each name + distance is stored in a div to which we can apply a simple CSS class where the text color is changed. By adding or removing this class, we give the impression of moving from one div to the other.
The images returned by Wikipedia have a really small size, usually around 30-50 pixels.
However, the URL of the image can be changed to identify the need for a larger width. You
will need to write code that uses the value of the property width to find the portion of
the URL you can change with the string .replace()
method.
The animation feature (slideshow effect by moving from one city to another automatically)
is created with the built-in Javascript function setInterval()
. This function takes
two parameters:
setInterval(function_to_invoke, milliseconds);
The function starts a cound-down timer and at the end of it runs the provided function.
This is repeated forever, unless we invoke clearInterval
. To do that, we neet
to call setInterval like in the example below:
var intervalID = setInterval(function_to_invoke, millseconds); // do other things // if some conditions is fulfilled (e.g., we visited all cities), clear the interval clearInterval(intervalID);
You can see an example of the setInterval
function in action in
jsFiddle I created.
setInterval
setInterval
to not invoke it by adding the parentheses. Try this out to see what happens. In the above jsFiddle,
go and change var intervalID = setInterval(showBoxes, 1000);
to
var intervalID = setInterval(showBoxes(), 1000);
. What happens?var myInterval = setInterval(function() {doSomething("wendy", 2018);}, 1500);
setTimeout
method has a "sister" method, setTimeout
, which wait for
a certain amount of time and then executes a function. This is a good trick to have your code stop
for a moment, while you wait for something else to happen. To do that, you invoke setTimeout
with an empty function:
setTimeout(function(){ }, 2000);
W3 Schools has some examples and more background on setInterval
and setTimeout
: