4.2 Toggle an array of place marks

The following “toggleArrayLayer” function turns all objects inside of an array on and off.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//toggle array layers on/off
yoh.toggleArrayLayer = function(arraylayer)
{
    if (arraylayer) {
        for (i in arraylayer) {                
            if (arraylayer[i].getVisible() == true)
            {
                arraylayer[i].setMap(null);
                arraylayer[i].visible = false;
            }
            else
            {
                arraylayer[i].setMap(map);
                arraylayer[i].visible = true;
            }
        }
    }
}

This function requests an array layer, checks to see if it exists, then loops through every object in the array and turns it on or off. Furthermore, it sets the “.visible” parameter to “true” and “false”, which allows the function to know whether the object is on or off each time the request is made.

Building layers based on the Metro API

Using the Metro API, let’s build a site that maps three of their routes, and then add a checkbox for each of the routes to allow users to turn them on and off individually.

Because we want to make each route a separate layer, we’ll need to create a separate array for each route. We can do it manually like this:

1
2
3
var bus_2 = [];
var bus_4 = [];
var bus_720 = [];

However, this is not a very efficient method, because every time we create a new route, we have to manually create the variable. Instead, let’s create a single array, and use it as a 2 dimensional array (more on this later).

1
var busstop = [];

Also, let’s add a DIV in the side panel where we can add the checkbox’s:

1
<div id="stoplist"></div>

So far, this is no different from our previous tutorials. Now, in our side panel, we want to dynamically create each checkbox for each stop that is requested. For this, we will add some “append” code to the “mapBusStops” function that will dynamically generate a checkbox for each bus route requested.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//map bus stops
yoh.mapBusStops = function(busnum)
{
    bounds = new google.maps.LatLngBounds ();
   
    //add the checkbox display
    $('#stoplist').append('<input type="checkbox" id="toggle'+busnum+'" onClick="yoh.toggleArrayLayer(busstop['+busnum+'])"> bus number '+busnum + '<br>');

    $.getJSON('http://api.metro.net/agencies/lametro/routes/' + busnum + '/sequence/callback=?',
        function(data)
        {
            $.each(data.items, function(i,item){
                yoh.createStop(i,item.latitude,item.longitude,item.display_name,busnum);
            });                
        }
    );
}

There are a few changes to this function. First, we are dynamically creating an input checkbox based on the bus number requested. The input checkbox also has an “onClick” call to the “toggleArrayLayer” function. Second, in the “createStop” call, we are adding another parameter to the function call for the “busnum”, so that the createStop function knows what busnum it is creating markers for (remember that we want the markers to know which route each marker created for belongs to).

Now, let’s look at the modified “createStop” function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//Function to create busstop
yoh.createStop = function(i,latitude,longitude,title,busnum)
{
    var markerLatLng = new google.maps.LatLng(latitude,longitude);
    bounds.extend (markerLatLng);
   
    //if busstop busnum is not defined, define it as an empty array first
    if (typeof busstop[busnum] == "undefined") busstop[busnum] = [];
   
    //create the marker, but DO NOT map it
    busstop[busnum][i] = new google.maps.Marker({
        position: markerLatLng,            
        title: title,
        icon: 'http://www.yohman.com/students/yoh/bus.png',
        zIndex: i
    });
   
    //set the visible toggle to false
    busstop[busnum][i].visible = false;
   
    //add an click even
    google.maps.event.addListener(busstop[busnum][i], 'click', function() {
      infowindow.setContent(title);
      infowindow.open(map,busstop[busnum][i]);
    });
    map.fitBounds(bounds);
}

The main change is that we will use a two dimensional array to define the route. First, the function checks to see if the route array exists. If not, it creates an empty array for it. For example, to create stops for bus number “2”, it defines the array for this route as:

1
busstop[2]

Then, each stop created for bus number “2” is added through the second dimension of the array:

1
2
3
4
busstop[2][0]
busstop[2][1]
busstop[2][2]
...

If this were another route, say, bus number “720”, it would be:

1
2
3
4
busstop[720][0]
busstop[720][1]
busstop[720][2]
...

Since we want all bus stops turned off by default, the function then sets each bus stop’s “visible” status as “false”.

Calling the functions to map bus routes and create checkboxes

Now that we have all the functions ready, we can make calls to map specific bus routes via the “mapBusStops” function. In the initialize function, you can generate calls to map bus routes like this:

1
2
3
4
//Draw metro stops
yoh.mapBusStops(2);
yoh.mapBusStops(4);
yoh.mapBusStops(720);

To summarize…

  • use mapBusStops to create a layer for a route (ex: yoh.mapBusStops(2))
  • mapBusStops automatically creates the checkbox for the route requested and calls function “createStop” to create each stop on the route
  • createStop creates an array for the requested bus route, and then creates and maps each bus stop marker, putting each marker in the array for that route

(sample code)

Leave a Reply