Google Map Lists - Coding Started


I can't go into nearly as much detail as I did on my last post, but I got some stuff working today that's going to lead to a really great add on in the future - google mapped page lists.  Read on for a bit about how the system works, in abstract.

The project we are working on is pretty complex, and one of the main features of it is a front-end search interface for the custom objects based on state, zip code, or filtering by two different types of other custom objects that are associated with this custom object.  Last week I got all of the filtering stuff working, but I hadn't set it up with a map view yet. 

Back when I was working on the Occupy NDP project, one of the things that they wanted was the ability to add pages for community events to a map for that community.  There wasn't really anything in the marketplace that would work.  The closest was ScottC's Page Mapper add on, but that's a bit different.  For it to work, you have a dashboard page where you set up each map, adding icons manually one at a time and associating them with pages. Since people on the Occupy site wouldn't have dashboard access, and since they would all have to have access to the same maps, and all put their own pages onto that map, it didn't seem like it would work at all.

The way I wanted to do it was to create a 'geolocation' attribute, then use that to get the spot for the map pin.  Information from the page would be displayed in a tools file when you click on the icon - either pulling information from a getMapInfoWindowHTML() function on the page if it existed, or from a WYSIWYG rich text attribute if the method doesn't exist, or just a link to the page with the page title if that attribute doesn't exist.  Seems simple enough, I ended up architecting most of how I wanted it to work in my head, but since things didn't seem to really be heading anywhere with the Occupy site I didn't put any time into actually programming it.  It was kind of on a back burner - I meant to get around to programming it, but never really had the time and had other things I was more focused on, mostly social stuff - having fun with friends, going out and drinking and smoking and riding.

But now we had a project at work where I had to build pretty much exactly this functionality.  I _really_ didn't want to code it for work - I love my job, I think that we should release a lot code that we do as marketplace items, but I don't want everything that I release to be under the Hutman banner.  I've made over 2200 dollars so far this year selling marketplace items, nearly double what I made last year.  It may not be a lot, but it's still pretty significant.  I keep dreaming of making some 'killer' marketplace add on that pretty much everyone will want to use so I can make a lot more money, but I haven't really known what it would be. 

I have the feeling this mapping list might be it.

A couple of weeks ago as I was getting started on this project, I spent some time and got started on the geolocation attribute.  But I hadn't worked on the google maps part of it at all.  I'd done something similar several years ago on a bicycle related project, when Hennepin and First Avenue went in there was some pretty big outcry, and I made a website that would let you report on when and where people violated bike lanes.  At least, that's what I think it did. I honestly don't remember.  The way I was setting it up was to geocode a single line address attribute for each page.  Not really resource light.  But it worked - I could put pages on a google map and show an info window with links to the pages.

That code, even if I could find it now, was with an outdated version of google maps.  It was I think version 2, though it might have actually been version 1 because I think I was using a jquery library that no longer exists to display all the markers.  I knew that I was going to need to redo everything if I wanted to make it work now.

So after working on yesterday's post about custom objects, I put my whole day today into learning how to set up a map view to match up with the results coming from my search form for the site I was working on for the work project.  It turned out to be pretty easy to actually expand the filter functions I already had working to also make a second call to get a json object to populate the markers on the map. I just made a new function on the page controller, and used some javascript to create the map on the page and apply the new items as markers on the page and center the map around those markers.  I ended up using the plugin to set everything up.  It was pretty easy to get it to add the markers and then set those markers up to pass an ID to a tools file and display an infowindow of the results, but getting the zoom to work properly was pretty difficult.  Changing the filters in the sidebar would bring in different search results and update the map, but it wouldn't change the zoom level.  Trying a couple of different things when you update the marker array didn't really work, or they would work for only the times when it was more than one result, if you had only one result it would zoom in down to almost street level view which was far too close.  I did a lot of googling to figure out how to modify that - ended up checking if the number of markers was 1 then setting a default view centered on that marker.  I'm using a geolocation page attribute (the same for the other locations) to set the center for the parent map page, and if there are no results I set the map to center on that. Otherwise it would default out in the middle of the ocean.

At any rate, after 6 or 7 hours, I had everything working pretty much perfectly.  I modified the custom list object's zip code search to be more accurate.  Originally, I was using a zip code attribute on the pages associated with my custom objects to compare against the 'center' of whatever zip code was searched for. The code was ported from the Search Tools by matogertel. That add on showed me how to do a custom search by zip code on a page list, I just modified it to work with my custom object list.  The hard part was actually getting the zip code list imported properly - the system doesn't work without a table that has all the zip codes and their centers as the control that you search against. I downloaded a csv from a third party website but copying the dashboard single page code from Search Tools to import the csv file ended up with a different amount of rows in the mySQL database than in the csv file.  I'm not sure what caused that, I might look for a better source for my marketplace add on. The search tools uses either an address or a text attribute on the page to get a zip code, find out it's lat/lng, then compare that with a bunch of math to the zip code requested.  Instead of that, I set up the filter by radius function on my custom object list to pull in from the lat/lng from my custom geolocation address, so instead of it being just the center of whatever zip code the location was in to the center of whatever zip code was requested from the search form, it was actually using the exact geolocated address of the location object to whatever the center of the requested search zip code was.

There's still more I need to do - the geolocation attribute validates properly if you actually validate the value in PHP when you save the object, but not by default when you save a page attribute.  Unfortunately, when you save a page in concrete5, it doesn't actually validate that the attributes are valid.  I think this is a pretty big limitation of the system, I think it's probably something that should be looked at soon to make it more functional.  Since validation doesn't work by default, it's probably worth it to try and move to front-end validation like in the Letergo Advanced Text Attribute.  So that's one of the next things to do.  I wish validation was actually built into concrete5, though, that would be so much easier.  There are methods on the attributes to validate them against a set of values, so I don't see why it's _not_included.

Another thing I want to work on (which goes in hand with validation) is letting the attribute choose the icon displayed, which should be pretty simple.  I also want to have a link "Fine Tune Geolocation" that would open up a dialog window centered on whatever the address geocodes to, and update the attribute form on drag and drop of the pin for that location. 

Once that's done, you can pretty much make any page totally positioned via lat/lng very easily.  Now that I know a bit more about how to set up search for geolocation, it seems like making a search form that allows you to search by a bunch of different attributes and proximity to a location would be very easy.  So I'm thinking a page list block and a page search block, paired together to get results.  I'm sure I can build it, and probably make it better than any other system for mapping that concrete5 has.

There's just one small problem.  When I was researching making this plugin, I found some evidence that I needed to have a business license for google maps in order to distribute this type of add on.  I sent an email to them asking about it, and someone called me back.  He pretty much told me that what I want to make is against their terms of service.  The one way he said it might work, is if I set it up so it wouldn't work unless you added a map component, so that you had to choose Bing Maps or Google Maps or some other system in order to get it to work.  I'm going to set it up so that you have to have an actual API key for your domain and the system won't work without that, which hopefully should make it legal. I'll ask, I'm pretty sure it will.  Honestly, from what the guy I talked to was saying, it sounded like pretty much all the concrete5 and wordpress and drupal and any other cms plugins were illegal, the difference between what I was doing and what they were doing was the fact that I actually asked if it was legal or not.  So most add ons weren't legal.  But the license for maps is per domain, so setting up a system that didn't work unless they had a valid API key for google maps on that domain that wasn't tied to the add on code explicitly should make the difference.

At any rate, I'm getting a lot closer to another marketplace add on that I think will be really popular. There's still a lot more to do, but I'm on the right track.  Hopefully within the next couple of weeks I'll have a fully integrated system.  It's already working on the site I've been working on the last couple of weeks, making it work in a package for any and every site won't be hard.

I really wish I could post up screenshots of how cool this looks.