Harvard Extension School
CSCI E-12 Fundamentals of Web Site Development | Fall 2019

# Session 11 - JavaScript, Part 4

Harvard Extension School
Fall 2019

Course Web Site: http://cscie12.dce.harvard.edu/

Instructor email: david_heitmeyer@harvard.edu
Course staff email: cscie12@dce.harvard.edu

### Topics

1. AJAX
2. Data Formats - JSON
3. JSON - Creating Content with jQuery
4. Let's make a more generic JS Function
5. Creating Content with Ajax, jQuery, and JSON
6. Same Origin Policy, CORS, and JSONP
7. Other Data Formats for Ajax
8. Javascript Templates
9. JavaScript Templates - Example
10. JavaScript Templates - Courses
11. Course Search Example - Live!
12. Handlebars - A few more notes
13. Handlebars - Compiled Templates
14. Maps
15. Google Maps JavaScript API
16. Map with Several Markers
17. Social Media Integration/3rd Party Tools
18. JavaScript Wrapup

slide1 slide2 slide3 slide4 slide5 slide6 slide7 slide8 slide9 slide10 slide11 slide12 slide13 slide14 slide15 slide16 slide17 slide18 slide19 slide20 slide21 slide22 slide23 slide24 slide25 slide26 slide27 slide28 slide29 slide30 slide31 slide32 slide33 slide34 slide35 slide36 slide37 slide38 slide39

- img
- img
- img
- img
- img

## AJAX

Ajax flow:

1. The browser makes an HTTP GET request for the search page
2. The server responds with the HTML content.
   Note that we are not showing browser requests for other page resources such as image, CSS, or JavaScript files
3. The user types in a search term and clicks the submit button (or presses "enter")
4. A JavaScript event handler is triggered on the form submit, and JavaScript sends an HTTP request via the browser to the server. This HTTP request contains the search term typed in by the user as a parameter sent to the server
5. A program on the server searches the course database for any courses that contain the search term.
6. The program (via the web server) returns the matching courses in a data format to the browser
7. The browser receives the data, hands it off to the JavaScript, and the JavaScript formats the data into HTML and updates the search area on the page

## What the browser does

The picture below outlines what we just saw:

- Initiates an HTTP request to server, and receives data
  An event handler in JavaScript for the form submit is triggered, and JavaScript sends an HTTP request to the server that includes the search term the user typed in. In an Ajax context, the response from the server is not necessarily HTML meant to be displayed directly, but is data.
- Formats and Displays Data on the Page
  The JavaScript that is part of the page is used to format the data into markup, and then place this newly created markup on the page itself so that it is displayed to the user.

## What the server does

The picture below outlines what we just saw:

The server is simply responding to HTTP requests, and sending responses back to the browser. The "how" of looking up courses in a database based on a keyword search term is beyond the scope of this lesson -- we will demystify that part later in the course.

## A Collection of Technologies

So we see Ajax is really a collection of technologies that are working together to send and receive data to and from the web server based on user actions, and to format and display this data to the user.

Some of the key technologies involved are:

- HTML
- CSS
- JavaScript
  - DOM (Document Object Model)
    The DOM is used to format the content and manipulate the content of the page that is displayed in the browser.
  - XHR object (XHR = XMLHttpRequestObject)
    This is the object in JavaScript that constructs and sends the request back to the server
- Data formats
  - JSON (JavaScript Object Notation)
  - XML (eXtensible Markup Language)
  - HTML
    Sometimes the server sends an already-formatted content snippet that can be displayed directly

## What can you do with Ajax?

- Partial update of page
- Periodic polling for new/changed data
- "Event"-driven interaction (instead of 'form submit'-driven)
  - click, mouseover, submit, etc.
- Incorporate data and functionality from other sites into your web site
  - Your data + functionality from elsewhere
  - Your functionality + data from elsewhere

Ajax is a term coined around 2005 - see Ajax: A New Approach to Web Applications by Jesse James Garrett

## The Rich Internet Application (RIA)

The Ajax approach has radically changed the way web applications work and have greatly improved the user experience for web-based applications -- allowing for the creation of Rich Internet Applications (RIAs) that to users "look and feel" just like desktop applications (e.g. Google Docs vs. Microsoft Word)

## JavaScript Applications and Widgets

In addition, the Ajax approach has allowed sophisticated functionality to be easily incorporated into pages by website authors via JavaScript applications or "widgets" (e.g. Google Maps, Twitter feeds).

## Data Formats - JSON

A data format widely used in Ajax is JSON -- this format is used to pass data from the web server to the browser, and it is in a format that is easily worked with in JavaScript.

We first need to take a look at the JSON format and how we can work with it, and then we'll see how this works together in Ajax.

The introduction to JSON from json.org is a great place to start:

JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate. It is based on a subset of the JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999. JSON is a text format that is completely language independent but uses conventions that are familiar to programmers of the C-family of languages, including C, C++, C#, Java, JavaScript, Perl, Python, and many others. These properties make JSON an ideal data-interchange language.

JSON is built on two structures:

- A collection of name/value pairs. In various languages, this is realized as an object, record, struct, dictionary, hash table, keyed list, or associative array.
- An ordered list of values. In most languages, this is realized as an array, vector, list, or sequence.

These are universal data structures. Virtually all modern programming languages support them in one form or another. It makes sense that a data format that is interchangeable with programming languages also be based on these structures.

FAQ

- How do you pronounce JSON?
  Like the name "Jason", as in "Jason and the Argonauts."
- Is it just for JavaScript?
  No. Don't let the "J" in JSON fool you. JSON is data-interchange format that is supported by a lengthy list of languages.

Let's take a look at the two data structures that JSON uses: objects and arrays.

### JSON object

In short, a JSON object is an unordered list of name/value pairs.

A JSON object example:

Note that the object (collection of name/value pairs) is enclosed in {curly braces}.
The name/value pair has a colon after the name (i.e. name: value), and the name/value pairs are separated by a comma.

So the object above represents the following:

Name | Value
--- | ---
lastName | Faust
firstName | Drew
email | president@harvard.edu

### JSON Array

In short, a JSON array is an ordered sequence of values. Values are strings (in quotes), numbers, arrays, objects, or boolean (true/false) values.

A JSON array example

### Strings, Objects, and Arrays are all Values!

In the examples above, we've shown the values as strings (e.g. "Spring" or "Faust"). But values can also be arrays or objects. Below is a more complex JSON object that includes two name/value pairs whose values are an array of strings ("seasons") and the other an array of objects ("days"):

There are several online JSON viewers and validators you can use that are helpful for exploring, writing, or validating JSON structures:

- Code Beautify JSON Viewer (JSON example above in Code Beautify)
- JSON Lint
- JSON Editor Online

## JSON - Creating Content with jQuery

Now that we have a sense of JSON and its "object" and "array" structures, let's see how we can create content from JSON using JavaScript.

We'll use the jQuery JavaScript library to build up markup based on data in the JSON structure, and then we'll place it on the page.

We'll use the "seasons" array to build an unordered list of seasons.

The JSON data:

The result we will build:

Let's take a look at the important parts:

HTML:

JavaScript:

- `var mydata = {"seasons":["Spring", "Summer", "Autumn", "Winter"]};`
  The JSON data structure. An object with a single name/value pair (name is "seasons" and value is the array of 4 strings)
- `var seasons = mydata.seasons;`
  Create a variable `seasons` that is equal to `mydata.seasons`. At this point, the variable `seasons` is equal to `["Spring", "Summer", "Autumn", "Winter"]`
- `var ul_node = $('<ul>');`
  Use jQuery syntax to create a `ul` node,
- `for (var i in seasons) {`
  Iterate through the array via index position. Remember that arrays in JavaScript (as in almost all programming languages) begin with an index of 0. Therefore, the first time through this loop, `i` will be `0`, the second time, `i` will be `1`, etc. And to access the value of the array, `seasons[i]` will be used — `seasons[0]` is `Spring` and `seasons[1]` is `Summer`, etc.
- `var li_node = $('<li>');`
  Use jQuery syntax to create an `li` node.
- `li_node.text(seasons[i]);`
  Set the text value of the `li` node to be the value of the array item (e.g. first time through the loop, this creates ``
- `ul_node.append(li_node);`
  Append the `li` node to the `ul` node (e.g. the first time through the loop, we will then have
- `}`
  this is the curly brace to close the close the loop started in `for (var i in seasons) {`
- `$('#seasons').append(ul_node);`
  Finally, once the `ul` is completed, we append it to the element whose id is `#seasons`

### All Together

- Seasons Example in JS Fiddle
- Seasons Example Standalone | download

Complete markup is:

## Let's make a more generic JS Function

So we have some jQuery that will take the "seasons" array and create an unordered list from it. Let's turn this into a generic JS function that will take any array and make an unordered list.

We'll build on the success of what we have -- we've done the work, we just need to organize it a bit differently. We'll define a JS function, "array_to_ul" that accepts an array as an argument (arguments are parameters that are passed to the function when we call it).

- Example in JS Fiddle
- Live Example | download

## Creating Content with Ajax, jQuery, and JSON

So now we'll bring Ajax into the picture by requesting data from the server. The server will return the seasons JSON data, and we will then pass array of seasons to our function that will create the unordered list.

The jQuery library makes working with Ajax requests very easy. jQuery has a `getJSON` method that makes requesting and receiving JSON data from the server easy. In the simplest case, we'll pass two parameters when we use the `getJSON` method: a URL that will be requested, and a "callback" function that will be called on a successful retrieval of JSON data. A simple case where we make a JSON request to the url "seasons.json" and simply log the data to the JS console looks like:

    $(document).ready(function(){
      $.getJSON("seasons.json",function(data) {
        console.log(data);
      });
    });

- `"seasons.json"`
  This is a relative URL that will be requested.
- `function(data){ console.log(data); }`
  This is the callback function that is called when the JSON request is successfully completed. Note the `data` is the data from the JSON request.

Example of getJSON in JSFiddle

### All together

So we take our previous example, where we built a list from a JSON data structure, and change it so that the JSON data comes from an Ajax request (using the `getJSON`) method of jQuery:

- Example in JS Fiddle
- Live Example | download

## Same Origin Policy, CORS, and JSONP

When working with Ajax, it is important to understand some basic concepts of web application security. Some concepts we'll briefly describe are:

- Same Origin Policy
- CORS (Cross Origin Resource Sharing)
- JSONP

These are important to understand since the browser restricts the Ajax calls allowed.

## Same Origin Policy

This is the simplest policy, and will cover all cases where the data you are requesting comes from the same hostname as the page making the request.

Under the same origin policy, a web browser will permit JavaScript contained in a web page to access data from the same origin -- or the same "hostname" of the URL.

So if your JavaScript and the data it is accessing all come from the same origin (hostname in the URL), the browser will permit this communication.

If the JavaScript and the data come from different origins (hostnames), then the browser will block this for security reasons.

For JavaScript to access data that comes from different origins, two techniques can be used: CORS and JSONP.

## CORS - Cross Origin Resource Sharing

CORS is a common and preferred method for handling cross-origin requests.

Using CORS, it is possible for the browser and server to determine whether or not to allow a cross-origin request. This happens as part of the HTTP request. The server can specify access control rules, which a browser will then use to determine whether a cross-origin request is permitted.

We won't go into how make the server-side CORS compatible right now. From the front-end perspective, it is enough to understand that you are using a CORS-enabled service. You don't need to do anything to enable CORS from within your JavaScript -- it already is there and is used by the browser.

For example, the service from "cdn.rawgit.com" (e.g. apples.json) uses CORS, which is why the "Pick Your Own Apples" example worked fine, despite the different origins between the page the JSON.

## JSONP

Note: the JSONP technique pre-dates CORS. JSONP is still in use, but CORS is the preferred approach.

With JSONP, a new "script" element is dynamically created (no restrictions on cross-origin requests for "script" elements), and the JSON returned is wrapped in a function, which you can then call to get the JSON. Since the JSON is wrapped in a function, the "P" is for the "padding". So depending on your perspective, JSONP exploits a back-door to the cross-origin issue, or it is a clever solution to the cross-origin issue.

## Other Data Formats for Ajax

So far, we've only discussed the JSON data format. While JSON is a very common format and easy to work with in JavaScript, it is not the only data interchange format used.

## XML - eXtensible Markup Language

XML gives a way of defining other markup languages (for example, HTML is a markup language that has an XML format). The "X" is for extensible, so XML is flexible in the data and documents that it can contain.

> There is essentially no computer in the world, desk-top, hand-held, or back-room, that doesn't process XML sometimes. This is a good thing, because it shows that information can be packaged and transmitted and used in a way that's independent of the kinds of computer and software that are involved. XML won't be the last neutral information-wrapping system; but as the first, it's done very well.
> Tim Bray (Sun Microsystems)

> Quote from the press release of the W3C XML 10 Celebration in 2008

An example of course data in XML format is:

When working with XML in JavaScript, you can use the DOM, or there are libraries to convert XML to JSON.

One important aspect of XML is that it is really a family of technologies that interoperate quite well -- once you are in the XML world and using XML technologies, working with XML can be easy, straightforward, and even fun. Examples of XML technolgoies are:

- Programming models: DOM and SAX
- Query: XQuery and XPath
- Transformation: XSLT
- Presentation format: Office document formats are XML based, SVG (graphics), XSL-FO (print), XHTML/HTML (web)

So an example where we have the seasons array in XML:

    <seasons>
      <season>Spring</season>
      <season>Summer</season>
      <season>Autumn</season>
      <season>Winter</season>
    </seasons>

We could process that in jQuery by:

    $.get("seasons.xml",function(data){
      var ul_node = $('<ul/>');
      console.log(data);
      $(data).find("season").each(function(){
        var season_string = $(this).text();
        console.log($(this));
        $('<li/>').text(season_string).appendTo(ul_node);
      });
      ul_node.replaceAll($('#seasonslist'));
    });

Full code:

Working Examples:

- Live Example - Seasons in XML
- Seasons XML in JS Fiddle

Which is better, JSON or XML ? There are quite a few strong opinions as to whether JSON is better than XML or XML is better than JSON. The answer, of course, is "it depends". For delivering data to a web browser to process with JavaScript and present on a web page, JSON comes out ahead of XML. However, there are many cases where XML will be judged the winner over JSON.

## HTML

Sometimes a snippet of HTML (not a full document) will be returned by an Ajax service -- this content just needs to be placed on a page. This approach is easy because formatting is not required on the client-side, but this approach is not flexible since changes in formatting have to be implemented on the server-side.

## Javascript Templates

Having the separation of data coming from the server-side in the form of JSON (or even some other format), and doing the work to display and present it on the client-side is a beneficial separation of concerns. If the formatting and display requirements change, it is a change to the front-end (client-side) code (HTML, CSS, JS) as opposed to the server-side. However, while the technique we've seen to process JSON into markup and place it on the page is entirely on the client-side (as opposed to server-side), a big drawback is that we've done this entirely in JavaScript.

For example, to build a list of seasons, we did something like:

Good News: We do have separation between front-end and back-end! Front-end does the structuring and display; the back-end provides the data.

Bad News: We have mixing of concerns between structure (markup) and function (JavaScript). We do not have good separation between structure (HTML), style (CSS), and function (JS) within the front-end. We have to read through the JavaScript to figure out how our data will be structured. If we want to change how the data is structured, we need to edit the JavaScript.

## Better with Templates!

Using JavaScript templates, building a list could look something like:

There are a variety of libraries for making templates in JavaScript. I'll mention four here, and we'll focus on one in our examples (Handlebars):

- Trimpath JavaScript Templates (JST)
- Mustache, "Logic-less" templates
- Handlebars, Handlebars provides the power necessary to let you build semantic templates effectively with no frustration.

KISS - Keep It Simple.
Before we get started with an example, I want to put a strong recommendation to follow the keep your templates simple principle. Trimpath JST and Mustache forces you to do this -- with Handlebars, you can keep your templates simple, but you can make them complex. Remember that the prime benefit we want to achieve with templates is for our presentation format to be defined separately from our JavaScript code. The more complex our templates get, the further we get from achieving that benefit.

## JavaScript Templates - Example

We'll focus on using the Handlebars template library. Other template systems will do similar things though, with different syntax.

With Handlebars, the key parts are:

- Write a Mustache template
- Load the Mustache JavaScript library
- Compile the template using Handlebars
- Evaluate the template, passing in the data
- Add the result of the processed template to the page

Handlebars syntax are based on double curly braces, like `{{ handlebar expression }}`.

So to iterate through the <code>seasons</code> array, our Handlebars template would look like:

    <ul>
      {{#seasons}}
      <li>{{.}}</li>
      {{/seasons}}
    </ul>

To re-implement our "seasons list" example using Handlebars, we could something like:

- The Mustache template is defined in Lines 32-38.
  This template iterates through the `seasons` array
  - `{{#seasons}}` starts the iteration
  - `{{/seasons}}` ends the iteration
  - Within the loop, `{{.}}` refers to item of the array
  Note that the template is marked as `display: none;` by CSS. There are other ways to include templates, which we'll discuss a bit later.
- Line 11. Load jQuery for Ajax request and DOM manipulations. We're using the jQuery CDN here.
- Line 12. Load Handlebars JS library from the cdnjs.com service.
- Line 15. Here we define the URL we'll get our seasons list from.
- Line 18. Use jQuery to make the Ajax request, and set the callback function to process the data
- Line 20. Get the template source (uses jQuery to select the `#seasonslisttemplate` and get the `html`
- Line 21. Use Handlebars to compile the template. This makes the template ready to process. Under the hood, the compile step turns our {{ handlebars template }} into JavaScript code.
- Line 22. Evaluate the template, passing in the data. The evaluation will return the markup generated.
- Line 23. Add the results of the template evaluation to the page. Note here we are using jQuery.

See the working examples:

- Handlebars - Seasons - Live example
- Handlebars - Seasons - JS Fiddle

## JavaScript Templates - Courses

Let's take a look at a Handlebars template that processes information about Courses from the Faculty of Arts & Sciences at Harvard University.

Courses - Example Courses - JSFiddle

Course data. First, here is a JSON string built based on a query of the course database for all the courses with a keyword of "food". It would be typical to have this query built from a form and return "live" results in JSON, but to keep things simpler for this example, we'll just use this static list: courses.json

Handlebars template. In this JSON structure, there is an array of course objects (the "name" part is `courses`, the value is the array of course objects). In Mustache, we'll need to iterate through the courses, and for each one, we'll output some information about the course. Assuming we pass the Mustache template the JSON object above, this would look something like:

    <div id="courselisttemplate" class="handlebars">
    <ul>
    {{#courses}}
        <li class="course">
        <span class="number">{{course_group}} {{num_int}}{{num_char}}</span>
        <br/>
        <span class="title">{{title}}</span>
        </li>
    {{/courses}}
    </ul>
    </div>

Notice how we can simply reference the "name" of a name/value pair in an object, like `{{title}}`.

The above template would render like:

We'll make this example a bit more complete by adding the `faculty_text` and `meeting_text` to the output. Also, we can add the number of courses returned by using `{{courses.length}}`.

    <div id="courselisttemplate" class="handlebars">
    <p>{{courses.length}} courses were found</p>
    <ul>
    {{#courses}}
        <li class="course">
        <span class="number">{{course_group}} {{num_int}}{{num_char}}</span>
        <br/>
        <span class="title">{{title}}</span>
        <br/>
        <span class="faculty">{{faculty_text}}</span>
        <br/>
        <span class="meeting">{{meeting_text}}</span>
        </li>
    {{/courses}}
    </ul>
    </div>

And the result would look like:

## Course Search Example - Live!

- Course Search - Live

### Data

- Base URL: `http://cscie12.dce.harvard.edu/ajax/course_search`
- Expects "keyword" parameter which is the search term and "output=json"
- Example URL:http://cscie12.dce.harvard.edu/ajax/course_search?keyword=China&output=json

### Markup (Form Part)

    <form id="course_search_form">
      <div>
          <input type="text" id="search_query" name="search_query" size="40" placeholder="Search by title, instructor, description" />
          <input type="submit" name="submit" value="Search" />
      </div>
      <div id="courselist">
          Course Listings will be updated here.
      </div>
    </form>

### JavaScript

    $(document).ready(function () {
        console.log("DOM READY!");
        var course_template_source = $('#courselisttemplate').html();
        var course_template_compiled = Handlebars.compile(course_template_source);

        console.log(course_template_source);
        console.log(course_template_compiled);

        $('#course_search_form').submit(function (e) {
            console.log("form submitted!")
            var search_term = $('#search_query').val();
            console.log("search term is: " + search_term);
            $.getJSON('/ajax/course_search', {
                    'keyword': search_term,
                    'output': 'json'
                },
                function (data) {
                    console.log("data retrieved is: ");
                    console.log(data);
                    var myresult = course_template_compiled(data);
                    $('#courselist').html(myresult);
                }
            )
            e.preventDefault();
        });
    });

### Handlebars Template

    <div id="courselisttemplate" class="handlebars">
    <p>{{courses.length}} courses were found</p>
    <ul>
        {{#courses}}
        <li class="course">
            <span class="number">{{course_group}} {{num_int}}{{num_char}}</span>
            <br/>
            <span class="title">{{title}}</span>
            <br/>
            <span class="faculty">{{faculty_text}}</span>
            <br/>
            <span class="meeting">{{meeting_text}}</span>
        </li>
        {{/courses}}
    </ul>
    </div>

## Handlebars - A few more notes

See: JSFiddle Example of Handlebars Loop Techniques

With Handlebars, you can also iterate explicitly with `{{#each }}`

With the context of our "seasons" JSON:

    {
      "seasons": [
        "Spring",
        "Summer",
        "Autumn",
        "Winter"
      ]
    }

We could do:

    <ul>
        {{#each seasons}}
        <li>{{.}}</li>
        {{/each}}
    </ul>

We can also specify the name of the parameter to be used within the loop:

    <ul>
        {{#each seasons as |season|}}
        <li>{{season}}</li>
        {{/each}}
    </ul>

Both of the above would produce:

If needed, you can also pass in the index position as well (remember that the first item in an array is index position = 0, second item is index position = 1, etc.).

    <ul>
        {{#each seasons as |season pos|}}
        <li>{{pos}} {{season}}</li>
        {{/each}}
    </ul>

Which would produce:

## Handlebars Conditionals

Sometimes we might want to format data based on certain conditions. For example, if an email address or URL exists for a person, we might want to include a `mailto:` link or a link to the URL. Handlebar conditionals allow to do that.

People in JSON:

    {
        "people": [
            {
                "name": "Drew Faust",
                "url": "http://president.harvard.edu/"
            },
            {
                "name": "Alan Garber",
                "url": "http://provost.harvard.edu/people/alan-m-garber"
            },
            {
                "name": "Katie Lapp"
            }
        ]
    };

For example, if we wanted to hyperlink a name if a URL exists, our Handlebars template could look something like:

    <ul>
    {{#each people as |person|}}
      <li>
      {{#if person.url }}
        <a href="{{person.url}}">{{person.name}}</a>
      {{else}}
        {{person.name}}
      {{/if}}
      </li>
    {{/each}}
    </ul>

And this would produce:

## Handlebars - Compiled Templates

It is possible to precompile your Handlebars template (the result is a JavaScript function), and then include the compiled templates via a `script` element.

Advantages of precompiling the templates include:

- Faster execution
- Can use lighter-weight Handlebars JS library (the "runtime" version, which doesn't have the compiler)

So here's an example where I've compiled the course list template into `courseslist.js`. Now there's no compile step, just a reference to `Handlebars.templates.courseslist` to access the template function. Note too that we are using the "runtime" version of the Handlebars library - `handlebars.runtime.min.js`

- Live Example - Handlebars Precompiled Template
- Handlebars Precompiled Template - JS Fiddle

Note the command to compile the template looked like:

    $ handlebars.js courseslist -f courseslist.js

where `courseslist` is the source template, and `courseslist.js` is the generated compiled JS file

## Maps

With JavaScript APIs for Google Maps, Bing Maps, and MapQuest, it is very easy to embed customized maps on your website.

We'll focus on using the JavaScript API for Google Maps, although similar capabilities exist with other map platforms. If we want to include a map on our website, there are a few possible ways to solve this problem:

- Embed a map created using Google's tools
- Use the JavaScript API

- Custom Data
- Use standards such as GeoRSS or KML

Each approach has some advantages and shortcomings. Essentially the trade-offs will be increased complexity with increased flexibility and control.

## Embed a map created using Google's Tools

You can create a map using Google's tools, and then simply click the cog icon and select "Share or embed". The "embed map" option will give you an `iframe` code you can use in your web page. It doesn't get much simpler than this. If you want to embed a map with the location of a single store or organization, then this technique will work well.

A map I created for the John Harvard Statue:

The `iframe` code provided by Google:

    <iframe style="border: 0;"
      src="https://www.google.com/maps/embed?pb=!1m14!1m8!1m3!1d1473.7541883076933!2d-71.11691195715973!3d42.37431548010373!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0%3A0x1b5299f9d1edac24!2sJohn+Harvard+Statue!5e0!3m2!1sen!2sus!4v1428381157098"
      width="600" height="450"></iframe>

And the map that is embedded:

For further information about the Google Map Embed API, please see
https://developers.google.com/maps/documentation/embed/guide

Cases where the embed approach wouldn't work so well:

- We need to create a map using information that changes
- We need to create a map using dynamically generated data

An example where a static embedded map would not work is with the Student Locations tool for this course. This tool allows students to enter their location information, and then the map is built dynamically based on this data. In addition, this tool displays different data, depending on whether the viewer is a student or an instructor. This is a case where we'll need more control over the map than a straightforward embed approach will allow.

The Google Maps JavaScript API will give us that control.

## Google Maps JavaScript API

There is extensive documentation for the Google Maps JavaScript API, at
https://developers.google.com/maps/documentation/javascript/tutorial that you can consult. But for now, it will be enough to walk through some examples.

We'll learn by example with a

- basic map
- map with a marker
- map with a marker with an information window
- map with several markers

### Basic Map

So first, we'll start with a map that is centered on the John Harvard statue in Harvard Yard.

To use the Google Maps JavaScript API, we'll need to load the Google Map JavaScript via a `script` element, and then we'll need to configure the map and then place it on the page.

Load the JavaScript:

    <script src="https://maps.googleapis.com/maps/api/js?v=3.exp"> </script>

Use the JavaScript:

    var map;
    /* John Harvard Statue
       42.374474,-71.117207 */
    var mylat = 42.374474;
    var mylng = -71.117207;
    function initialize_map() {
        var mapOptions = {
            zoom: 17,
            center: new google.maps.LatLng(mylat, mylng)
        };
        map = new google.maps.Map(document.getElementById('map-canvas'),
        mapOptions);
    }
    google.maps.event.addDomListener(window, 'load', initialize_map);

- Latitude and Longitude of the John Harvard statue is (42.374474,-71.117207)
- `google.maps.event.addDomListener` is the Google Maps way of adding an event handler.
  In this case, the event is the "load" event of the "window", and the handler is the function `initialize_map`
- In the `initialize_map` function:
  - `mapOptions` is a JS data structure. `zoom` level is how close (larger is closer)
  - `google.maps.LatLng` is the method that creates a Google Maps LatLng object. In this case, we are setting the center of the map to the location of the John Harvard statue
  - `google.maps.Map` is the method to create a Google Map. We pass in as parameters where to place it on the page (note the DOM method, `document.getElementById`), and the second parameter is the data structure of map options

Full example:

Basic Map working examples:

- Basic Map - Live example
- Basic Map - JS Fiddle

## Placing a Marker

To put a marker on the map, we'll create a `google.maps.Marker` object. When we create the marker, one of the parameters we'll pass in as part of the configuration data structure is the map we want to place it on.

So if we've created a `google.maps.Map` object as the variable `harvard_yard_map` and a `googlemaps.LatLng` object as the variable `latlng_statue`, the new JavaScript code to create a marker for the John Harvard statue would look like:

    var marker = new google.maps.Marker(
      {
        position: latlng_statue,
        map: harvard_yard_map,
        title: 'John Harvard Statue'
      }
    );

Note there is a single parameter passed to the `google.maps.Marker` method -- this parameter is a JavaScript data structure of name/value pairs.

Full example:

Map with Marker working examples:

- Map with Marker - Live example
- Map with Marker - JS Fiddle

Read more about Markers, Google JavaScript API documentation for additional information, such as using customized icons.

## Marker with an Information Window

Now that we have a marker on the map, we can add an information window.

There are three basic things to pay attention to:

- Create content for the information window
- Create the `google.maps.InfoWindow`
- Add a listener so that a click event on the marker causes the information window to open

These steps are shown below:

    /* Create content.  Here we are concatenating strings together with the JS "+" operator */
    var statue_info = "<strong>John Harvard Statue</strong><br/>" +
        "<a href='http://www.summer.harvard.edu/blog-news-events/3-lies-harvard'>3 Lies of Harvard</a>";

    /* Create the InfoWindow object; note we pass in the content */
    var statue_infowindow = new google.maps.InfoWindow({
        content: statue_info
    });

    /* Create the marker (we've seen this before) */
    var statue_marker = new google.maps.Marker({
      position: statue_latlng,
      map: harvard_yard_map,
      title: 'John Harvard Statue'
    });

    /* Create the listener so that the info window opens when the marker is clicked */
    google.maps.event.addListener(statue_marker, 'click', function() {
      statue_infowindow.open(harvard_yard_map,statue_marker);
    });

Full example:

Map with Marker working examples:

- Map with Marker + Info Window - Live example
- Map with Marker + Info Window - JS Fiddle

## Map with Several Markers

Now let's use JSON data to add several markers to a page.

Map with Ivy Schools from JSON Data - Live Example

The JSON data (schools.json) we'll use is a list of schools in the Ivy League -- which contains a latitude, longitude, name, and URL.

We'll use jQuery to get the JSON data, and we'll use the Google Maps API to create the map. The full code is shown below, but the key part to creating the markers is where iterate through the list of schools:

     for (var i in school_list) {
      var school = school_list[i];
      var mylatlng = new google.maps.LatLng(school.lat, school.lng);
      var marker = new google.maps.Marker({
                                           position: mylatlng,
                                           map: ivy_map,
                                           title: "school.name"
                                          });
    }

Full code:

## Social Media Integration/3rd Party Tools

We've seen the power of JavaScript, and the ease by which widgets are included on a page, and with a bit of knowledge, we can configure these widgets to work in customized ways.

With JavaScript widgets, it is easy to integrate tie-ins to social media into a site -- making it easy for users to share your site, or making it easy to integrate social media presence onto a site.

## ShareThis and AddThis

These services (ShareThis and AddThis) make it easy to add "sharing" buttons to your site.

They use the principles we've seen of using JavaScript to alter the page -- the JavaScript is provided by the service, and there are plenty of configuration and customization options to use.

These are configured in a "wizard-like" fashion, so the barrier to entry is quite low.

### ShareThis Example

- ShareThis Demo

### AddThis Example

- AddThis Demo

## Twitter

Twitter easily integrates into websites -- see Twitter for Websites. You can create "Tweet" and "Follow" buttons, as well as embed individual tweets and timelines.

Twitter provides the "wizard" tools, so you can easily configure what you want, and then have the code to use on your site.

## Facebook

Facebook also integrates easily into sites using their easily configured Social Plugins (Like, Share, Send buttons; you can also embed posts and parts of your page).

Configuration is through a wizard, and you'll get a combination of markup plus JavaScript to include in your page.

## Other JavaScript Functionality from 3rd Parties

With the power of JavaScript widgets, we've seen how it is possible to embed sophisticated mapping functionality on a site. There are plenty of other JavaScript widgets available that provide additional functionality.

Discussion and comment services can be used by embed this functionality on a site. All the "work" of the discussion / comments (authentication, storing, displaying, etc.) is handled by the third party. For example, comment functionality for WBUR and the Harvard Crimson use the service Disqus. Other examples include Livefyre and Intense Debate

## JavaScript Wrapup

At the beginning of the unit on JavaScript, our goals were:

- Understand basics of JavaScript
- Understand basics of jQuery
- Be able to use JavaScript widgets/solutions
- Be able to "hack" JavaScript and jQuery

### Where to from here?

For those who want more, I recommend the following resources:

- JavaScript Tutorials and Reference from MDN (Mozilla Developer Network)
- For those that like the "Head First" approach, there is Head First JavaScript Programming
  which is also available online through Harvard's Library.
- CSCI E-3, Introduction to Web Programming Using JavaScript
  Larry Bouthillier

Copyright © David Heitmeyer