MANO MARKS: Hi.
I'm Mano Marks.
Welcome to Google Maps Garage.
This is a regular show that we're doing on Google
Developers Live.
Google Maps Garage is where we talk about some of the
technical aspects of working with the Google Maps API,
delve into some code, and just sort through some common
design patterns and problems, things that come up for
developers.
So this week, I'm going to talk a little bit about
working with some common JSON objects, parsing through to
get out some data, and some gotchas that come up when
people do that, and things that we will often see people
ask questions about on Stack Overflow.
This is the basic map here that I'll be working with, or
at least the basic data.
So this is the Google West Campus, which is a part of the
main Googleplex here in Mountain View, California.
And I just highlighted three buildings that have large
numbers of geoengineers in here.
We fondly refer to this as the Geoplex.
And I'm just going to walk through a little
how I created that.
First, though, I wanted to show you my data source, very
simple file here.
This is the same data source I'm going to use in every one
of the examples today.
So you see here, I just created a file, WestCampus.js.
I created a variable West Campus, and then it has an
array of JSON objects.
Each has a name, latitude, and longitude.
It's a very common way for people to create their data
and load it into Google Maps or any other kind of
JavaScript application.
And I'm just going to say here that often, when we talk about
common problems that happen when building Google Maps
applications, they're actually common JavaScript problems.
There are a few things that are map-specific, but in
general, this is basically good JavaScript practice, so
these things will help you out with other things as well.
So if you'll take a look here, one thing you'll see that I
loaded a style sheet, which I do have created separately,
the JavaScript loader for the Google Maps API, and then
WestCampus.js, which is the file I was just showing you.
I created this Initialize function here
in this script tag.
Now, generally, best practice is to create a separate file
for all your JavaScripts.
Just for purposes of this video, I'm going to
show it in this way.
But basically, generally, best practice is create an HTML
file, create a CSS file, create at least one JavaScript
file for loading in your JavaScript.
That way, you get a separation of presentation,
styling, and your code.
So standard stuff here.
I create the map, and center it, and set the road type and
the zoom level.
We talked about that a lot in the last Google Maps Garage.
And then here, what I'm doing is I'm iterating over the
WestCampus array of objects, and so I do a for-in loop.
So I'm just saying for x in WestCampus, each time I loop,
it's going to create a new building object with
WestCampus, that particular reference to
that particular object.
Then I create a new Location Object, GoogleMaps.long,
building.lat, and building.lng.
And then I create a new marker that has the location and the
building name on it and set it onto the map.
And then you'll see here, a lot of people use body on load
to load their initialize function, but I prefer to use
a Google.Maps.events addDOMListener to the window
that waits for the page to load and then runs the
initialization.
That way, your body can continue to load, even if the
map hasn't loaded at that point.
So that is what you get right here.
And you notice that I used building.name for the title,
which means that as I hover over a particular one--
hopefully, this will show up on video--
I get a little tool tip there.
Not a very sophisticated one, like using an Info window, but
it gives you enough information without clicking
on it, just to see what that object is.
So I'm going to switch over now to adding in an Info
window and demonstrate at the same time a common problem.
So this looks the same.
This is my slightly different file.
I'm going to click on one here, and you'll see that
whichever one I click on, it's going to do West Campus 3 as
the Info window and load it up using that
position as its location.
So as I scroll through here, you can see we're doing pretty
much the same thing.
Then we're creating an Info window for each one, and for
the content, we're setting the content to the building name.
And you'll notice that the last one is West Campus 3, and
that's the one it's picking up for all the Info windows.
And then I am adding an event listener to each marker that
says, when clicked on, open up the Info window and set it to
the map and the marker.
Now, what were encountering here is a common JavaScript
scoping problem.
The problem is here that yes, you're creating a new Info
window object each time, and you would think that when you
create the event listener, you're actually telling it to
open up the Info window that you're creating in that loop.
The problem is that what's actually happening is that the
event listener is only firing when you click on the marker.
So what happens is it's picking up the last Info
window that was created, and that has the last
name for its content.
So that's a problem that's fairly easily solved, but it's
one that comes up because scope just works a little bit
differently than how you might expect if you're used to
working with some other programming languages.
So here's one way to fix the problem here.
What I've done is I've created a separate addMarker function.
And so I loop through in the same way that I was doing
before, and after I create the location, I create an
addMarker, where I pass the building name, the map, and
the location to that function.
And then in that function--
because this scope is by global or by function here--
what we're seeing is that that actually works.
So I create a new Info window in that scope and that
function, and the event listener is created there, so
it works just fine.
So now as I load that, I click on each one, and you'll see
that I get a separate Info window.
Now, what's interesting to note here is this doesn't work
in a way that most Maps applications you'll see out
there work.
Each Info window that's created doesn't automatically
close the other Info windows.
So one solution to that problem--
and by the way, some people do like to have multiple Info
windows up, which is why we allow you to do that.
You may remember back to V2, I believe the Google Maps API,
you could only have one Info window at a time.
So now, if we look at this function addMarker, what
you'll see is when I click on it, that's when I create the
Info window.
And I actually created a global variable called Info
Window, and then I check to see if that exists, and if it
does, then I close it.
Regardless of whether it exists at that point, once
I've closed it, it's gone away, and then I create a new
Info window at that location and pass
it the map and marker.
So the only time the Info window is
created is at event time.
So we look here, and you'll see it's closing existing Info
windows and opening up a new one.
So that's one good solution to this problem.
So I just have a couple more quick demos here.
This is creating a polyline using the same data set.
And what you'll see here is as I'm looping through, I create
these new Google Maps Lat Long objects, and then I push them
into an array that I created called Points, and then I
create a polyline, pass it the path at points and the map,
and then it puts that onto the map.
Now, this is a standard JavaScript array, and you'll
see here, I've created something that
looks exactly the same.
And what I've done instead of creating a standard JavaScript
array is create a Google Maps MVC array.
Now MVC, the Model View Controller objects within
Maps, that's something that we'll go into probably in a
later Google Maps Garage.
But the MVC array is basically an array object that's defined
within the JavaScript API that is much more optimized for use
with the Google Maps API.
And the reason you would want to use that is when you are
using large numbers of points, you will find you'll get
better performance using the Google Maps MVC array versus
the standard JavaScript array.
So I just wanted to call that out as a quick technique that
you can use.
And then finally today, I actually have just a little
trick for you.
I've got Google Earth open here.
Now often, when I'm constructing something by
hand, I have a little bit of trouble figuring out where
exactly things go.
So we can take a look here in Google Earth, and I'll show
you a little bit of what I've done.
When I was creating this, I didn't have the latitude and
longitude of the Google buildings.
What I did was I just went into Google Earth and created
a bunch of placemarks.
Let's see, I have here the two placemarks for these two
buildings, and also for the center here.
And I do that pretty easily just by centering Google Earth
where I want it, creating a placemark by pushing on the
little push pin right there, and then I can move that
around to position it exactly where I want.
And then I click OK, and then I just right click or control
click, and pull up Copy, create a new text document,
and I've created a little bit of KML here.
And so then what I can do is I can just go into the
Coordinates Tag and pull out the latitude and longitude
that I need for my map.
Now, the reason I am doing this is it saves a round trip
for geocoding if I wanted to geocode, say, the Google West
Campus one, two, and three.
One thing to note is that in Google Earth, there the
latitude and longitude are reversed from their positions
in Google Maps, so longitude comes first and then latitude.
So when you copy and paste those out, you need to just be
aware of that.
The other thing I do is Google Earth will give you a very
high level of precision on the coordinates.
I usually top that out at six decimal points.
So just copy the first six after the decimal point, and
take that and paste that into my code.
So that's just a neat little trick that I use when I'm
constructing my Google Maps apps when I need a latitude
and longitude right away.
All right.
That's all we have for you in this week's episode of Google
Maps Garage.
Please join us next time.
Thanks.