This Week’s Project
I decided it was time to take the GeoSandbox to the next level. As usual, I had multiple goals in mind for this project. Primarily, I wanted to learn how to use and write JavaScript. It’s been a long time since I’ve tried to write any kind of meaningful code, but I figured if I wanted to keep up with the big kids, it was time to take the plunge. I also wanted to get my map viewer into a state where I could make it useful enough to display my GIS projects, and help promote my business.
My Experience with Writing Code
My first exposure to computer programming was back in 1980 when I took a computer language class as an undergrad. I remember trying to write some code for a fictional car dealership inventory system, and saving it on a 8” floppy disc. I believe it was in Basic, but I really can’t remember. I never did get it to work. Since then I’ve played around with various versions of Visual Basic, but never got very far past the “Hello World” types of programs. I took a GIS class as a grad student back in 2001 where I used MapObjects to make a functional GIS program. That was fun, and I did get that to work, but I haven’t written any real code since then. Yes, I do read, use, and modify scripts in ArcGIS. That keeps me in tune with the basics of programming, but I don’t think it’s the same as writing real code.
The Goal
I wanted to make the following three enhancements to the GeoSandbox:
- Change the buttons in the toolbar
- Make the map window dynamically change size with changes to the browser window size
- Have the map window change its contents through links in order to showcase different projects
The first two items were fairly easy. I was able to read through the GeoExplorer.js script, and just delete the buttons I didn’t want showing on the toolbar. I also made some changes to the About box, and figured out how to generate a proper Google API key that allows the embedded 3D viewer to show. Dynamically resizing the map window was just a matter of doing a search, copying some code, and pasting it in the right place on the web page. Yes, I had to modify the <iframe> ID in the code, but that was simple enough.
I had it in my head that I wanted to make four maps available on the page, and to allow users to switch between these maps using a set of links along the top of the map. Seemed simple enough.
No, it wasn’t.
Setting up the webpage and the GeoServer maps was easy. Here’s what the page looks like:
And you can access the page using this link: www.donmeltz.com/maps
Changing iFrames
What I found out along the way was, banging your head against an <iframe> can really hurt.
I started out by putting a single <iframe> on the page. Since the src attribute of said <iframe> specifies the URL of the document to show in the <iframe>, I figured I’d just change the src attribute to point to the various GeoServer maps I wanted to show. That didn’t seem to work for me. What I found was, there are many different ways to change the <iframe> src. I must have tried them all, and I got most of them to work. The problem was, they didn’t work in every browser I tried. Here’s a list of the browsers I used in my tests:
- Firefox 3.1.15
- Internet Explorer 9 beta
- Chrome 9.0.597.107
- Safari 5.0.3
- Opera 10.10
Learning About iFrames
First, I’d like to mention the Dynamic Web Coding website has the most comprehensive and understandable information on scripting <iframes> that I’ve found: http://www.dyn-web.com/tutorials/iframes/
What I haven’t figured out yet is – Why do all of the examples used on that website (and many others I visited) work for them, but not for me? It just boggles my mind. In a nutshell, here are the various things I tried.
I started out by setting up some bare-bones test sites where I stripped out all of the css styling, and deleted all but two links in order to make it easy to modify and test the code, and see what I was doing. I have links to all of these test pages below each of the following paragraphs in case you want to check them out. You can right-click on each page and view the source if you want. Click on the upper part of the page, NOT on the <iframe> map.
(Please note, I have greatly simplified the syntax in these examples so they fit on one line. If you want to see the actual code, please visit the Dynamic Web Coding site, or right click on my test maps and view the source.)
I began by trying to set the <iframe> target directly in the link like this:
<a href=http://www.Maps.html#maps/2 target="mapiframe">link</a>
This worked in IE and Firefox, but only if I hit the browser refresh button after I clicked the link. Yes, I also went through many iterations of adding a variety of refresh functions to the code, but that only worked in one or two instances. And in some cases it made things even worse. Here’s a link to my test page for this trial: http://www.donmeltz.com/mapstest1.html
Next up was an attempt to set the iframe source (scr attribute) using some JavaScript code as in:
document.getElementById('MapFrame').src="http://Maps.html#maps/2"
I tried using both a function and embedding the code in the link using the onClick event. Results were similar to the previous attempt, and again, inserting a refresh function did not help. There are other variations of this, such as using “window.getElementById, etc. which I also tried, but to no avail. Here’s the link to my test page for this trial:
http://www.donmeltz.com/mapstest2.html
I then moved on to trying to assign the contents of the iframe using code like this:
contentWindow.location.assign("http://Maps.html#/2")
which worked in IE (again, with a browser refresh) but not in anything else. The trial page: http://www.donmeltz.com/mapstest3.html
What came closest to getting the task done was working with the <div> that holds the <iframe> instead of manipulating the <iframe> directly, as in:
<div id="MapContainer">
MapContainer.innerHTML = "<iframe id="MapFrame" src="http://Maps.html#maps/2">
This one worked for me in every browser except Firefox: http://www.donmeltz.com/mapstest4.html
In the end, what I wound up doing was placing four different iframes on the page. I then set the style.display property of the iframe to “none” (hide) or “block” (show) in order to hide or show each one based on which link is clicked on the web page and looks something like this:
document.getElementById("MapFrame").style.display="block";
Yes, “block” means “show”. Intuitive, I know. Here’s a link to my test page that shows how this one works: http://www.donmeltz.com/mapstest_adinfinitum.html
This works in every browser I’ve tried, but it does slow down the load times significantly. All four maps load when the page loads. It does make switching between maps faster once everything is loaded, though.
I Got It
So, where did all of this hacking get me? I got what I wanted. A workable map viewer that shows a few samples of my work, and an education in JavaScript. Even though I spent many hours, days even, working with this, I still think it was worthwhile. I’ve learned a lot, even though it doesn’t seem like I got very far. I can read JavaScript code, and understand it a lot better now than I did when I started. I’d still like to figure out if I’m doing something wrong. It seems like these options should work, as it looks like they work on other peoples pages. Yes, I’m still banging my head against the <iframe> once in a while 🙂
For now though, I think I’ll just kick back with a bottle of homebrew and a little Jimmy Cliff.
I’m anything but a JavaScript guru, but I have had some success with jQuery’s Ajax capabilities in instances in which I needed a page to load in the background while another page was loading. You might be able to load your other iframes while the first one is loading.
http://api.jquery.com/category/ajax/
I really appreciate you blogging your experience. The process is just as important as the result. I believe you have done some great work- for what it is worth.
My first experience writing code was as a fourth-grader in an after-school enrichment class. We had to make our own program in basic. Mine was a shopping program. I think it was definitely the precursor to Amazon.com. Ha! And I still have the dot-matrix print out of the 400-line “program.”
400 lines of code in the fourth grade? I’m impressed 🙂