Additional Blogs by SAP
Showing results for 
Search instead for 
Did you mean: 
0 Kudos

This is the last part of a 4-part blog series. Please also take a look at Developing composite applications with PHP - consuming ESA Services, Developing composite applications with PHP - Upgrading to Web 2.0 and Developing composite applications with PHP - Advanced AJAX.

welcome to the fourth and last part of my little blog series. I was busy with other projects so this blog is a tiny bit delayed. I hope the content makes up for it. A little reminder, in the first part I presented the Customer Fact Sheet (CFS) scenario and the SAP Webservice consumption, while in Part two and Part three I explained quite a bit of the underlying JavaScript. Given modern frameworks this is more of a voluntary understanding of what happens below the surface than that I expect you'll really write such low-level code in normal, bigger applications.

Today I'll make it a bit more interesting and do a more mashup-like scenario by including an external service. And what service would be best to show (especially to impress managers 🙂 than Google Maps? I admit it, it's not new - it has been done for Salesforce and Gregory Wolf also did it Geocode Business Partner with Google Maps - though he used BSP and a plugin geocoder. I'll do it anyways, using the Google geocoder and, what a surprise, PHP.

Google Maps is not a 'Webservice' in the classical meaning - WS-* and such. And it is not even one if you include JSON in the definition. I understand a Webservice as something I'm calling from my application under the cover, aggregating the data and show them combined, without the user seeing where the individual data actually comes from. Google Maps is more like a Widget - you give it some space on your screen and it displays the map, taking completely care of it by itself. But it wouldn't be me if I wouldn't add some interaction elements also, so keep on reading.

A word of warning beforehand: Googles license terms are quite private-user-friendly: you can use the service, completely, free of charge, but you must also give everyone full access to what you do with it. So a business use where the mashup is only useable in the intranet, displaying sensitive company data and thus requiring an employee logon is not permitted. I expect no problems from small demonstrations like this, but if you intend to use it in a closed environment ask your legal department first 🙂

The second warning is about the geocoder I used - the one provided by Google itself. Geocoding refers to the process of 'finding the address', i.e. transforming an address the postman would find to a latitude/longitude coordinate which can be used to put the flag onto the Google Map. Given that it works for the whole world, the geocoder is quite good, but it does have its flaws and even though I only used demo data here some results were quite a bit off. There are no separate entry fields for the street, zip, city, but only one combined field. It sometimes happens the city isn't found and it actually uses the street name as city. For a pure demo this is acceptable, but if you really want to send out your sales agents, you probably better get a commercial mapping service. I believe that, among others, Map 24 provides such a service (together with Map display and routing services, but as it's commercial it is, well, not for free).

For Google Maps you need a 'developer key', a string of characters you can get for free when you register with Google (e.g. using your GMail account) and provide the URL you intend to use. I assume that's for internal tracking how widely used their service is and potentially to selectively disable certain sites. For development it proved very useful to register 'localhost' 🙂 but sometimes you need an URL you can give to colleagues to show off your work, so I created a function getGMapsKey(), which selects the correct key from a hardcoded list of keys so that you can both develop it locally and deploy it on your server without having to take care of the correct key. Of course you still need to register for the keys for each URL you want to use.

Single Customer Display

Using the Google Maps API is very simple and straightforward. The Google Maps Documentation offers small samples for each step, so I won't repeat too much of it here. Please take a look at the source code and the documentation, it should be pretty self explanatory.

My first scenario is a map with a single customer displayed in it. This map could then be displayed in our CFS popup window, or it could be put on a standalone site and shown in the SAP Portal as an IView. I actually had some colleagues from a different team build a similar CFS scenario in WebDynpro using the portal and I provided a map view for them - my page being displayed in a frame and given the customer ID as HTTP GET parameter. Next step would be to get their SSO-Token as well, but we haven't implemented that in this demo. See the file CFS_Map.php for this variant.

If you look at the CFS_Map.php file you have the bare map functionality. The first thing it does is making a call to getBasicData with the customer ID given in the GET parameter. Again I used a hardcoded user for this, in the above scenario a Single-Sign-On Logonticket could be given as second parameter, for example. The address is then inserted into the generated JavaScript, which will make the call to the geocoder from the browser. I added a 'maplevel' flag so that when a certain street in a city couldn't be found then the geocoding would be repeated with just the city, to at least give a rough view to where in the world the customer sits. Due to the sometimes bad geocoding results this wasn't as useful as I hoped, but the idea could be taken up with a better geocoder.

The Google Maps API (a JavaScript object) allows to set markers on the map (I set one for the current customer) and to show a single 'Information Window', usually when you click on a marker. The frame style is given, but the content can be freely defined, so I put the customer basic data inside it and for this single customer example also opened it by default.

The popup window, displayed from CFSpopup.php works similarly and adds the Google Map to the tabbed display. My colleague Vasil wanted to include routing information there, too, but we didn't finish this.

Multiple Customer Display

Now comes the fun part: showing all customers on the same map. At least all returned by the search query. For this I first added the map in a default view (showing good ol' Germany) while waiting for the user to enter his search query. When the results come in the map is shifted to the right (scaling it down horizontally while keeping the center, as this looks more natural). We already have an asynchronous loading of customer basic data in JavaScript and I now added a second phase to it, where each returned address is fed into the geocoder. This again uses a function closure, as it's a network operation and may take some time (in my case of a simple R/3 demo system against full Google power it was way quicker than thebasic data lookup). For each found address a marker is set on the map.

Thanks to Vasil the map resizes to browser window resizing and after all search results are geocoded the JavaScript code also tries to pan&zoom the map in a meaningful way to display all customers.

Clicking on a marker in the map opens the info window (there is always only one), which is filled with the customer basic data, or at least with as much as is filled out in the backend system. Additionally the link to open the CFS popup is displayed. The user now has the possibility to choose the customer from either the list (which can be sorted) or the map, using the geographical position. I think this is very nice.

Now about the interaction I promised. When a customer on the list is selected (clicked on), the map pans to it and opens the info window. So it's easy to find where a specific customer is on the map. The Google code automatically moves the map so that the info window is fully visible, but this sometimes leads to the marker not being in the middle of the map though the space would suffice for it. So I had to implement a little trick: I first open the info window (which automatically does the panning to display it, but not necessarily in the center), then I center the marker and afterwards - using a moveendlistener I redisplay the info window, as for small browser windows it might actually be necessary to be off-center to fully display the info window.

The other half of interaction - where the map influences the list - is rather trivial. I simply highlight the appropriate line, using the highlight function. Scrolling in a large (perhaps paginated) list or opening a detail view might be more useful variants, but I simply wanted to show how it's done.

As a little gimmick and to prove that the icons for the markers can be freely chosen I added a hardcoded list of all SAP Germany locations, which can be toggled via a JavaScript link at the bottom of the map. This list is in the util.php file and could easily be also gathered from the backend.

I will upload the full source code of this demo on SDN soon, so that you can take a close look at how I implemented this. Most Google Maps related code is in the file cfsgoogle.js.php. If you want to try it you have to add your Google Maps developer key to the function getGMapsKeys() in the file util.php, and also specify the logon credentials to the backend system in backend.php. The Webservice URLs must be entered in the individual files in the generated-folder.

I hope you had some fun with this tutorial. For questions please feel free to mail me or leave a comment here.

You can grab the source here: CFS4 Archive

1 Comment