Canvas is not supported in your browser, please install a newer HTML5 compactible browser

Google autocomplete address box in sugarCRM

Hi Guys and Gals,

I have been developing on the sugarCRM and when I was recently going through the kind of data we have and the one thing I found very inconsistent in general were the addresses. Different people have different ways of writing addresses, which becomes a problem when you have to segregate the data for any purpose. For example, someone writes United States of America, as USA or US or States. To solve this particular problem, one of the way is give the users to auto complete the data and what’s a better source than Google.

I will show you how I implemented this in sugarCRM, but this can be implemented in any system in general.

In sugarCRM we have a special field for address, which basically is shown as a single field but in technical terms is a combination of different fields stored in the database.
1) Address
2) City
3) State
4) Postal Code
5) Country

Google does return the data in somewhat this way, but we need to improve it to show it in sugar.

First we need to include the javascript in the contact create view in order to execute custom javascript code.

To do so, navigate to custom/modules/Contacts/metadata/, if there is a file named “editviewdefs.php” then open it, if it doesn’t exist, please copy it from modules/Contacts/metadata/

Under the templateMeta array add this

'includes' =>
    				array (
    						0 =>
    						array (
    								'file' => 'custom/modules/Contacts/js/addressautocomplete.js',
        ),
      ),

The complete file should look like this

<?php
/*********************************************************************************
 * SugarCRM Community Edition is a customer relationship management program developed by
 * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License version 3 as published by the
 * Free Software Foundation with the addition of the following permission added
 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Affero General Public License along with
 * this program; if not, see http://www.gnu.org/licenses or write to the Free
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301 USA.
 * 
 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
 * 
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 * 
 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
 * these Appropriate Legal Notices must retain the display of the "Powered by
 * SugarCRM" logo. If the display of the logo is not reasonably feasible for
 * technical reasons, the Appropriate Legal Notices must display the words
 * "Powered by SugarCRM".
 ********************************************************************************/

$viewdefs['Contacts']['EditView'] = array(
    'templateMeta' => array('form'=>array('hidden'=>array('<input type="hidden" name="opportunity_id" value="{$smarty.request.opportunity_id}">',
    											          '<input type="hidden" name="case_id" value="{$smarty.request.case_id}">',
    											          '<input type="hidden" name="bug_id" value="{$smarty.request.bug_id}">',
    											          '<input type="hidden" name="email_id" value="{$smarty.request.email_id}">',
    											          '<input type="hidden" name="inbound_email_id" value="{$smarty.request.inbound_email_id}">')),
							'maxColumns' => '2',
                            'widths' => array(
                                            array('label' => '10', 'field' => '30'),
                                            array('label' => '10', 'field' => '30'),
                                        ),
    		
    		'includes' =>
    				array (
    						0 =>
    						array (
    								'file' => 'custom/modules/Contacts/js/addressautocomplete.js',
        ),
      ),
),


    'panels' =>
    array (
      'lbl_contact_information' =>
      array (
        array (
          array (
            'name' => 'first_name',
            'customCode' => '{html_options name="salutation" id="salutation" options=$fields.salutation.options selected=$fields.salutation.value}' 
	      . '&nbsp;<input name="first_name"  id="first_name" size="25" maxlength="25" type="text" value="{$fields.first_name.value}">',
	      ),
          

        ),
        array (
          array (
            'name' => 'last_name',
          ),
          array (
            'name' => 'phone_work',
            'comment' => 'Work phone number of the contact',
            'label' => 'LBL_OFFICE_PHONE',
          ),
        ),

        array (

          array (
            'name' => 'title',
            'comment' => 'The title of the contact',
            'label' => 'LBL_TITLE',
          ),
          array (
            'name' => 'phone_mobile',
            'comment' => 'Mobile phone number of the contact',
            'label' => 'LBL_MOBILE_PHONE',
          ),

        ),

        array (
          'department',
          array (
            'name' => 'phone_fax',
            'comment' => 'Contact fax number',
            'label' => 'LBL_FAX_PHONE',
          ),
        ),
        array(
          array (
            'name' => 'account_name',
            'displayParams' =>
            array (
              'key' => 'billing',
              'copy' => 'primary',
              'billingKey' => 'primary',
              'additionalFields' =>
              array (
                'phone_office' => 'phone_work',
              ),
            ),
          ),
        ),

        array (

          array (
            'name' => 'primary_address_street',
            'hideLabel' => true,
            'type' => 'address',
            'displayParams' =>
            array (
              'key' => 'primary',
              'rows' => 2,
              'cols' => 30,
              'maxlength' => 150,
            ),
          ),

          array (
            'name' => 'alt_address_street',
            'hideLabel' => true,
            'type' => 'address',
            'displayParams' =>
            array (
              'key' => 'alt',
              'copy' => 'primary',
              'rows' => 2,
              'cols' => 30,
              'maxlength' => 150,
            ),
          ),
        ),

        array (

          array (
            'name' => 'email1',
            'studio' => 'false',
            'label' => 'LBL_EMAIL_ADDRESS',
          ),
        ),

        array (

          array (
            'name' => 'description',
            'label' => 'LBL_DESCRIPTION',
          ),
        ),
      ),


      'LBL_PANEL_ADVANCED' =>
      array (

        array (

          array (
            'name' => 'report_to_name',
            'label' => 'LBL_REPORTS_TO',
          ),

          array (
            'name' => 'sync_contact',
            'comment' => 'Synch to outlook?  (Meta-Data only)',
            'label' => 'LBL_SYNC_CONTACT',
          ),
        ),

        array (

          array (
            'name' => 'lead_source',
            'comment' => 'How did the contact come about',
            'label' => 'LBL_LEAD_SOURCE',
          ),

          array (
            'name' => 'do_not_call',
            'comment' => 'An indicator of whether contact can be called',
            'label' => 'LBL_DO_NOT_CALL',
          ),
        ),

        array (
	      'campaign_name',
        ),
      ),



      'LBL_PANEL_ASSIGNMENT' =>
      array (
        array (
          array (
            'name' => 'assigned_user_name',
            'label' => 'LBL_ASSIGNED_TO_NAME',
          ),
        ),
      ),
    )
);
?>

Basically the thing of interest is

'file' => 'custom/modules/Contacts/js/addressautocomplete.js',

add the javascript file at the file mentioned above with the code.

 $.getScript("https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&libraries=places&callback=initialize");
function initialize() {	
	var input = (document.getElementById('primary_address_street'));
	var options = {
			  types: ['establishment']
			};
	var autocomplete = new google.maps.places.Autocomplete(input);
	google.maps.event.addListener(autocomplete, 'place_changed', function() {		
		 var place = autocomplete.getPlace();
		 jQuery("#primary_address_city").val("");
		 jQuery("#primary_address_state").val("");
		 jQuery("#primary_address_country").val("");
		 jQuery("#primary_address_postalcode").val("");
		 jQuery("#primary_address_street").val("");
		 var street_name = "";
		 street_name = place.name
		 $.each(place.address_components,function(key,element){			
			 if(jQuery.inArray("street_number", element.types) !== -1){
				 street_name += " ,"+element.long_name;
			 }
			 if(jQuery.inArray("route", element.types) !== -1){
				 street_name += " ,"+element.long_name;
			 }
			 if(jQuery.inArray("neighborhood", element.types) !== -1){
				 street_name += " ,"+element.long_name;
			 }
			 if(jQuery.inArray("administrative_area_level_2", element.types) !== -1 || jQuery.inArray("locality", element.types) !== -1){			
					 jQuery("#primary_address_city").val(element.long_name);
			 }
			 if(jQuery.inArray("administrative_area_level_1", element.types) !== -1){
				 jQuery("#primary_address_state").val(element.long_name);
			 }
			 if(jQuery.inArray("country", element.types) !== -1){
				 jQuery("#primary_address_country").val(element.long_name);
			 }
			 if(jQuery.inArray("postal_code", element.types) !== -1){
					jQuery("#primary_address_postalcode").val(element.long_name);
			 }		
		 });
		   window.setTimeout(function() {
			   jQuery("#primary_address_street").val(street_name);
	           jQuery("#primary_address_country").focus();
	        }, 200);
	});
	
}

Now after this if you do a repair and rebuild, you will see something like this

The field turns to autocomplete. When you start typing a name, for example “Google Plex” you get a suggestion, when you select the suggestion, the javascript code written above basically splits that data into the particular fields

If you face any problems, just drop a comment and I will try to help you out.

Posted in Javascript, jQuery, PHP, SugarCRM.