In the previous article of this series we have done Siebel configuration, as well as presentation model and presentation renderer modifications, required for the bidirectional Siebel OpenUI – Google Maps integration. In this final article, let us have a look at what remains to be done to have a fully-fledged solution.
The original script of the Location Picker plug-in defines the structure of returned address in the following way:
function GMapContext(domElement, options) {
var _map = new google.maps.Map(domElement, options);
var _marker = new google.maps.Marker({
position: new google.maps.LatLng(54.19335, -3.92695),
map: _map,
title: "Drag Me",
draggable: options.draggable
});
return {
map: _map,
marker: _marker,
circle: null,
location: _marker.position,
radius: options.radius,
locationName: options.locationName,
addressComponents: {
formatted_address: null,
addressLine1: null,
addressLine2: null,
streetName: null,
streetNumber: null,
city: null,
state: null,
stateOrProvince: null
},
settings: options.settings,
domContainer: domElement,
geodecoder: new google.maps.Geocoder()
}
}
And here is how the address structure is populated with values returned by the Google Maps engine:
address_component_from_google_geocode: function(address_components) {
var result = {};
for (var i = address_components.length-1; i>=0; i--) {
var component = address_components[i];
// Postal code
if (component.types.indexOf('postal_code') >= 0) {
result.postalCode = component.short_name;
}
// Street number
else if (component.types.indexOf('street_number') >= 0) {
result.streetNumber = component.short_name;
}
// Street name
else if (component.types.indexOf('route') >= 0) {
result.streetName = component.short_name;
}
// City
else if (component.types.indexOf('sublocality') >= 0) {
result.city = component.short_name;
}
// State \ Province
else if (component.types.indexOf('administrative_area_level_1') >= 0) {
result.stateOrProvince = component.short_name;
}
// State \ Province
else if (component.types.indexOf('country') >= 0) {
result.country = component.short_name;
}
}
result.addressLine1 = [result.streetNumber, result.streetName].join(' ').trim();
result.addressLine2 = '';
return result;
}
There are a few things that can potentially be a subject of modification here:
The complete list of address property types returned by Google Maps API is available here, if you are interested.
In our case, the code shown above has been extended in the following way:
function GMapContext(domElement, options) {
var _map = new google.maps.Map(domElement, options);
var _marker = new google.maps.Marker({
position: new google.maps.LatLng(54.19335, -3.92695),
map: _map,
title: "Drag Me",
draggable: options.draggable
});
return {
map: _map,
marker: _marker,
circle: null,
location: _marker.position,
radius: options.radius,
locationName: options.locationName,
addressComponents: {
formatted_address: null,
addressLine1: null,
addressLine2: null,
streetName: null,
streetNumber: null,
city: null,
state: null,
stateOrProvince: null,
political: null,
administrative_area_level_2: null,
administrative_area_level_3: null,
administrative_area_level_4: null,
administrative_area_level_5: null,
colloquial_area: null,
sublocality_level_1: null,
sublocality_level_2: null,
sublocality_level_3: null,
sublocality_level_4: null,
sublocality_level_5: null
},
settings: options.settings,
domContainer: domElement,
geodecoder: new google.maps.Geocoder()
}
}address_component_from_google_geocode: function(address_components) {
var result = {};
for (var i = address_components.length-1; i>=0; i--) {
var component = address_components[i];
// Postal code
if (component.types.indexOf('postal_code') >= 0) {
result.postalCode = component.short_name;
}
// Street number
else if (component.types.indexOf('street_number') >= 0) {
result.streetNumber = component.short_name;
}
// Street name
else if (component.types.indexOf('route') >= 0) {
result.streetName = component.short_name;
}
// City
else if (component.types.indexOf('locality') >= 0) {
result.city = component.short_name;
}
// State \ Province
else if (component.types.indexOf('administrative_area_level_1') >= 0) {
result.stateOrProvince = component.short_name;
}
// State \ Province
else if (component.types.indexOf('country') >= 0) {
result.country = component.short_name;
}
else if (component.types.indexOf('political') >= 0) {
result.political = component.short_name; // Specially for Finland
}
else if (component.types.indexOf('administrative_area_level_2') >= 0) {
result.administrative_area_level_2 = component.short_name;
}
else if (component.types.indexOf('administrative_area_level_3') >= 0) {
result.administrative_area_level_3 = component.short_name;
}
else if (component.types.indexOf('administrative_area_level_4') >= 0) {
result.administrative_area_level_4 = component.short_name;
}
else if (component.types.indexOf('administrative_area_level_5') >= 0) {
result.administrative_area_level_5 = component.short_name;
}
else if (component.types.indexOf('colloquial_area') >= 0) {
result.colloquial_area = component.short_name;
}
else if (component.types.indexOf('sublocality_level_1') >= 0) {
result.sublocality_level_1 = component.short_name;
}
else if (component.types.indexOf('sublocality_level_2') >= 0) {
result.sublocality_level_2 = component.short_name;
}
else if (component.types.indexOf('sublocality_level_3') >= 0) {
result.sublocality_level_3 = component.short_name;
}
else if (component.types.indexOf('sublocality_level_4') >= 0) {
result.sublocality_level_4 = component.short_name;
}
else if (component.types.indexOf('sublocality_level_5') >= 0) {
result.sublocality_level_5 = component.short_name;
}
}
result.addressLine1 = [result.streetNumber, result.streetName].join(' ').trim();
result.addressLine2 = '';
return result;
}
As you can clearly see, a number of properties have been introduced – because sublocality and locality were empty in case of, for instance, Finland and it wasn’t really clear, which one will contain municipality or city. So what we did was to include all the properties that seemed suitable, and then to print them to the console; apparently, the city is passed in a property named political, so a little bit of magic has been added to the successGeoloc() function (see Part 2, a piece of code highlighted in red) in order to show the city information correctly for both Latvia and Finland.
All in all the kind of changes that are required to integrate Siebel OpenUI with Google Maps proved to create no additional hassle when it comes to verifying the changes and debugging the code along the way. Basically, everything boils down to some pretty standard JavaScript development tools and techniques.
The development described in this series of articles has been performed on the files residing in folders of a dedicated Siebel client. All the changes applied instantly without any compilation – you just need to remember to press Ctrl-R, so that the browser refreshes the current page.
“Inspect element” feature and JS console of the latest Google Chrome browser provide a rather sufficient set of instruments for debugging, so you probably won’t need anything else on top of that. After everything is OK on a local client, the files can be copied over to the web server, and the results will show even without a server restart.
Different countries have different structure of the address used in their application. And the format of address returned by Google Maps API is also different from country to country. The common approach for integrating addresses returned by Google Maps in any country could go along these lines:
Having implemented the bidirectional integration solution outlined above, we now have a fully functional applet that looks like this:
After pressing the Pick Address button, we have an address from Google Maps saved in our new fields in Siebel.
As an idea for further development and improvement, we could check whether such an address already exists in our system, and if it does, save its ID on the component, but if it doesn’t – create a new record in CUT Address and, again, save its ID on our component. That kind of improvement, however, deserves and article of its own, so we’ll leave it at that for now...
About the author: Ilja Dubovskis has deep technical expertise in Siebel CRM. For 9 years he has been working for clients in Telecommunications, Finance, Insurance, Industry and Public Sector areas. In addition to working for clients, he leads Siebel Core Developer School at IPR, as well as acts as a coach for newcomers. He has been with Idea Port Riga since September 2009. |