├── Block
└── Address
│ └── Autocomplete.php
├── Helper
└── Data.php
├── README.md
├── Screenshot
└── address-autocomplete.gif
├── composer.json
├── etc
├── acl.xml
├── adminhtml
│ ├── menu.xml
│ └── system.xml
├── config.xml
└── module.xml
├── registration.php
└── view
└── frontend
├── layout
└── default.xml
├── requirejs-config.js
├── templates
└── address
│ └── autocomplete.phtml
└── web
└── js
├── address-autofill.js
└── checkout-address-autofill.js
/Block/Address/Autocomplete.php:
--------------------------------------------------------------------------------
1 | addressAutocompleteHelperData = $addressAutocompleteHelperData;
47 | $this->_localeResolver = $localeResolver;
48 | parent::__construct($context);
49 | }
50 |
51 | /**
52 | * Retrieve the address autocomplete status
53 | *
54 | * @return boolean
55 | */
56 | public function showAddressAutocomplete()
57 | {
58 | $moduleName = $this->getRequest()->getModuleName();
59 | $controllerName = $this->getRequest()->getControllerName();
60 | $actionName = $this->getRequest()->getActionName();
61 | $currentPage = $moduleName.'_'.$controllerName.'_'.$actionName;
62 | $array = [
63 | 'customer_account_create',
64 | 'customer_address_edit',
65 | 'customer_address_new',
66 | 'customer_address_form',
67 | 'checkout_index_index'
68 | ];
69 | if (in_array($currentPage, $array)
70 | && $this->addressAutocompleteHelperData->getAddressAutocompleteStatus()
71 | ) {
72 | return true;
73 | }
74 | return false;
75 | }
76 |
77 | /**
78 | * Check if the current page is the checkout page
79 | *
80 | * @return boolean
81 | */
82 | public function isCheckoutPage()
83 | {
84 | $moduleName = $this->getRequest()->getModuleName();
85 | $controllerName = $this->getRequest()->getControllerName();
86 | $actionName = $this->getRequest()->getActionName();
87 | $currentPage = $moduleName.'_'.$controllerName.'_'.$actionName;
88 | $array = [
89 | 'checkout_index_index'
90 | ];
91 | if (in_array($currentPage, $array)) {
92 | return true;
93 | }
94 | return false;
95 | }
96 |
97 | /**
98 | * Retrieve the API Key
99 | *
100 | * @return string
101 | */
102 | public function getApiKey()
103 | {
104 | return $this->addressAutocompleteHelperData->getApiKey();
105 | }
106 |
107 | /**
108 | * Retrieve the locate
109 | *
110 | * @return string
111 | */
112 | public function getLocate()
113 | {
114 | return $this->_localeResolver->getLocale();
115 | }
116 |
117 | /**
118 | * Retrieve the countries code allowed
119 | *
120 | * @return string
121 | */
122 | public function getCountriesAllowed()
123 | {
124 | return $this->addressAutocompleteHelperData->getCountriesAllowed();
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/Helper/Data.php:
--------------------------------------------------------------------------------
1 | scopeConfig->getValue(
47 | self::GOOGLE_API_KEY,
48 | \Magento\Store\Model\ScopeInterface::SCOPE_STORE
49 | );
50 | if (!$apiKey) {
51 | $apiKey = 'AIzaSyAo4tEzHqBYcQQtBYYKFoZXhy3j_SX-osU';
52 | }
53 | return $apiKey;
54 | }
55 |
56 | /**
57 | * Retrieve the address autocomplete status
58 | *
59 | * @return boolean
60 | */
61 | public function getAddressAutocompleteStatus()
62 | {
63 | return $this->scopeConfig->isSetFlag(
64 | self::ADDRESS_AUTOCOMPLETE_STATUS,
65 | \Magento\Store\Model\ScopeInterface::SCOPE_STORE
66 | );
67 | }
68 |
69 | /**
70 | * Retrieve the countries code allowed
71 | *
72 | * @return string
73 | */
74 | public function getCountriesAllowed()
75 | {
76 | return $this->scopeConfig->getValue(
77 | self::COUNTRIES_CODE_ALLOWED,
78 | \Magento\Store\Model\ScopeInterface::SCOPE_STORE
79 | );
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Customer Address Autocomplete Extension for Magento 2
2 | In this module, I used the Maps Javascript API of the Google for autocompleting the customer address. When the customer enter the address in the street field, a list of addresses will be suggested by Google Maps Javascript API.
3 |
4 | ## How to install or upgrade this extension?
5 | + Under the root of your website, please run the command lines bellowing:
6 | - Before installing this extension, make sure that you have installed the PHPCuong_Core module, If you don't install this module yet, please install it by running the command line: **composer require php-cuong/magento2-module-core**
7 | - Install the PHPCuong_CustomerAddressAutocomplete module:
8 | - **composer require php-cuong/magento2-customer-address-autocomplete**
9 | - **php bin/magento setup:upgrade**
10 | - **php bin/magento setup:static-content:deploy**
11 | - **php bin/magento setup:di:compile**
12 | - **php bin/magento indexer:reindex**
13 | - **php bin/magento cache:flush**
14 |
15 | ## How to see the results?
16 |
17 | ### - On the Backend:
18 | - Go to the Admin Panel of the Magento Store and navigate to the GiaPhuGroup → Address Autocomplete
19 |
20 | ### - On the Storefront:
21 | - Go to the Edit Address page
22 | - Go to the Add New Address page
23 | - Go to the Create New Customer Account page
24 | - Go the the checkout page.
25 |
26 | ## The screenshot of this extension
27 |
28 | ### - On the Storefront:
29 |
30 | #### *The interface used for the customer creates new customer account page*
31 | 
32 |
--------------------------------------------------------------------------------
/Screenshot/address-autocomplete.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/php-cuong/magento2-customer-address-autocomplete/f309034275cafadeaa2c391cf61555febc716a3a/Screenshot/address-autocomplete.gif
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "php-cuong/magento2-customer-address-autocomplete",
3 | "description":"Magento2 Customer Address Autocomplete Extension Free",
4 | "keywords": [
5 | "magento 2",
6 | "magento 2 extension",
7 | "extension free",
8 | "address autofill",
9 | "Customer Address Autocomplete",
10 | "Address Autocomplete",
11 | "Maps Javascript API",
12 | "Google Maps"
13 | ],
14 | "require": {
15 | "php": "~5.6.0|7.0.2|~7.0.6|~7.0.13|~7.1.0",
16 | "magento/module-backend": "100.0.*|100.1.*|101.0.*|100.2.*",
17 | "magento/framework": "100.0.*|100.1.*|101.0.*|100.2.*",
18 | "php-cuong/magento2-module-core": "2.2.*"
19 | },
20 | "type": "magento2-module",
21 | "version": "2.1.1",
22 | "license": [
23 | "OSL-3.0",
24 | "AFL-3.0"
25 | ],
26 | "authors": [
27 | {
28 | "name": "Cuong NQ",
29 | "email": "bestearnmoney87@gmail.com",
30 | "role": "Developer"
31 | }
32 | ],
33 | "autoload": {
34 | "files": [
35 | "registration.php"
36 | ],
37 | "psr-4": {
38 | "PHPCuong\\CustomerAddressAutocomplete\\": ""
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/etc/acl.xml:
--------------------------------------------------------------------------------
1 |
2 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/etc/adminhtml/menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
23 |
24 |
28 |
29 |
--------------------------------------------------------------------------------
/etc/adminhtml/system.xml:
--------------------------------------------------------------------------------
1 |
2 |
23 |
24 |
25 |
26 |
27 | phpcuong
28 | PHPCuong_CustomerAddressAutocomplete::config_address_autocomplete
29 |
30 |
31 |
32 |
33 | Magento\Config\Model\Config\Source\Yesno
34 |
35 |
36 |
37 | Create API key, please <a href="https://developers.google.com/places/web-service/get-api-key" target="_blank">click here</a>.
38 | required-entry
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/etc/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
23 |
24 |
25 |
26 |
27 | 0
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/etc/module.xml:
--------------------------------------------------------------------------------
1 |
2 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/registration.php:
--------------------------------------------------------------------------------
1 |
2 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/view/frontend/requirejs-config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * GiaPhuGroup Co., Ltd.
3 | *
4 | * NOTICE OF LICENSE
5 | *
6 | * This source file is subject to the GiaPhuGroup.com license that is
7 | * available through the world-wide-web at this URL:
8 | * https://www.giaphugroup.com/LICENSE.txt
9 | *
10 | * DISCLAIMER
11 | *
12 | * Do not edit or add to this file if you wish to upgrade this extension to newer
13 | * version in the future.
14 | *
15 | * @category PHPCuong
16 | * @package PHPCuong_CustomerAddressAutocomplete
17 | * @copyright Copyright (c) 2018-2019 GiaPhuGroup Co., Ltd. All rights reserved. (http://www.giaphugroup.com/)
18 | * @license https://www.giaphugroup.com/LICENSE.txt
19 | */
20 |
21 | var config = {
22 | map: {
23 | '*': {
24 | addressAutofill: 'PHPCuong_CustomerAddressAutocomplete/js/address-autofill',
25 | checkoutAddressAutofill: 'PHPCuong_CustomerAddressAutocomplete/js/checkout-address-autofill'
26 | }
27 | }
28 | };
29 |
--------------------------------------------------------------------------------
/view/frontend/templates/address/autocomplete.phtml:
--------------------------------------------------------------------------------
1 | showAddressAutocomplete();
25 | $apiKey = $block->getApiKey();
26 | ?>
27 |
28 |
37 |
52 |
53 |
--------------------------------------------------------------------------------
/view/frontend/web/js/address-autofill.js:
--------------------------------------------------------------------------------
1 | /**
2 | * GiaPhuGroup Co., Ltd.
3 | *
4 | * NOTICE OF LICENSE
5 | *
6 | * This source file is subject to the GiaPhuGroup.com license that is
7 | * available through the world-wide-web at this URL:
8 | * https://www.giaphugroup.com/LICENSE.txt
9 | *
10 | * DISCLAIMER
11 | *
12 | * Do not edit or add to this file if you wish to upgrade this extension to newer
13 | * version in the future.
14 | *
15 | * @category PHPCuong
16 | * @package PHPCuong_CustomerAddressAutocomplete
17 | * @copyright Copyright (c) 2018-2019 GiaPhuGroup Co., Ltd. All rights reserved. (http://www.giaphugroup.com/)
18 | * @license https://www.giaphugroup.com/LICENSE.txt
19 | */
20 | define([
21 | 'jquery',
22 | 'googleMapPlaceLibrary'
23 | ], function ($) {
24 | "use strict";
25 | $.widget('phpcuong.addressAutofill', {
26 | options: {
27 | componentForm: {
28 | street_number: 'street_1',
29 | route: 'route',
30 | locality: 'city',
31 | administrative_area_level_2: 'city',
32 | administrative_area_level_1: 'region',
33 | country: 'country',
34 | postal_code: 'zip'
35 | },
36 | autocomplete: null
37 | },
38 |
39 | /**
40 | *
41 | * @private
42 | */
43 | _create: function () {
44 | var self = this;
45 | this.options.autocomplete = new google.maps.places.Autocomplete(
46 | document.getElementById('street_1'),
47 | {types: ['geocode']}
48 | );
49 | // When the user selects an address from the dropdown, populate the address
50 | // fields in the form.
51 | this.options.autocomplete.addListener('place_changed', function() {
52 | // Get the place details from the autocomplete object.
53 | var place = self.options.autocomplete.getPlace();
54 | // Get each component of the address from the place details
55 | // and fill the corresponding field on the form.
56 | for (var i = place.address_components.length-1; i >= 0; i--) {
57 | var addressType = place.address_components[i].types[0];
58 | var long_name = place.address_components[i].long_name;
59 | var short_name = place.address_components[i].short_name;
60 | if (self.options.componentForm[addressType] && long_name) {
61 | if (self.options.componentForm[addressType] == 'country') {
62 | $('#'+self.options.componentForm[addressType]).val(short_name).trigger('change');
63 | } else if (self.options.componentForm[addressType] == 'region') {
64 | $('#'+self.options.componentForm[addressType]).val(long_name).trigger('change');
65 | if ($('#region_id option:contains('+long_name+')')) {
66 | $('#region_id option:contains('+long_name+')').prop('selected', true);
67 | }
68 | } else if (self.options.componentForm[addressType] == 'route') {
69 | $('#street_1').val(long_name).trigger('keyup');
70 | } else if (self.options.componentForm[addressType] == 'street_1') {
71 | $('#'+self.options.componentForm[addressType]).val(long_name + ' '+ $('#'+self.options.componentForm[addressType]).val());
72 | } else {
73 | $('#'+self.options.componentForm[addressType]).val(long_name).trigger('keyup');
74 | }
75 | }
76 | }
77 | });
78 | this.options.autocomplete.setComponentRestrictions({'country': this._getCountriesCodeArray()});
79 | },
80 |
81 | /**
82 | * Convert countries code to array
83 | *
84 | * @private
85 | */
86 | _getCountriesCodeArray() {
87 | var countries = this.options.countries;
88 | return countries.split(',');
89 | }
90 | });
91 | return $.phpcuong.addressAutofill;
92 | });
93 |
--------------------------------------------------------------------------------
/view/frontend/web/js/checkout-address-autofill.js:
--------------------------------------------------------------------------------
1 | /**
2 | * GiaPhuGroup Co., Ltd.
3 | *
4 | * NOTICE OF LICENSE
5 | *
6 | * This source file is subject to the GiaPhuGroup.com license that is
7 | * available through the world-wide-web at this URL:
8 | * https://www.giaphugroup.com/LICENSE.txt
9 | *
10 | * DISCLAIMER
11 | *
12 | * Do not edit or add to this file if you wish to upgrade this extension to newer
13 | * version in the future.
14 | *
15 | * @category PHPCuong
16 | * @package PHPCuong_CustomerAddressAutocomplete
17 | * @copyright Copyright (c) 2018-2019 GiaPhuGroup Co., Ltd. All rights reserved. (http://www.giaphugroup.com/)
18 | * @license https://www.giaphugroup.com/LICENSE.txt
19 | */
20 | define([
21 | 'jquery',
22 | 'googleMapPlaceLibrary'
23 | ], function ($) {
24 | "use strict";
25 | $.widget('phpcuong.checkoutAddressAutofill', {
26 | options: {
27 | loopShipping: 0,
28 | loopBilling: 0,
29 | componentForm: {
30 | street_number: 'street_1',
31 | route: 'route',
32 | locality: 'city',
33 | administrative_area_level_2: 'city',
34 | administrative_area_level_1: 'region',
35 | country: 'country',
36 | postal_code: 'zip'
37 | },
38 | shippingAutocomplete: null,
39 | billingAutocomplete: null,
40 | billingStreetFound: false,
41 | billingFunction: null
42 | },
43 |
44 | /**
45 | *
46 | * @private
47 | */
48 | _create: function () {
49 | var self = this;
50 |
51 | // Fill in shipping address
52 | this.options.shippingFunctions = setInterval(function() {
53 | var street = $('#shipping-new-address-form').find('input[name="street[0]"]')[0];
54 | if (street) {
55 | self.options.shippingAutocomplete = new google.maps.places.Autocomplete(
56 | street,
57 | {types: ['geocode']}
58 | );
59 | self.options.shippingAutocomplete.inputId = street.id;
60 | self.options.shippingAutocomplete.setComponentRestrictions({'country': self._getCountriesCodeArray()});
61 | google.maps.event.addListener(self.options.shippingAutocomplete, 'place_changed', function () {
62 | // Get the place details from the autocomplete object.
63 | var place = self.options.shippingAutocomplete.getPlace();
64 | // Get each component of the address from the place details
65 | // and fill the corresponding field on the form.
66 | for (var i = place.address_components.length-1; i >= 0; i--) {
67 | var addressType = place.address_components[i].types[0];
68 | var long_name = place.address_components[i].long_name;
69 | var short_name = place.address_components[i].short_name;
70 | if (self.options.componentForm[addressType] && long_name) {
71 | if (self.options.componentForm[addressType] == 'country') {
72 | $('#shipping-new-address-form select[name="country_id"]').val(short_name).trigger('change');
73 | } else if (self.options.componentForm[addressType] == 'region') {
74 | $('#shipping-new-address-form input[name="region"]').val(long_name).trigger('keyup');
75 | if ($('#shipping-new-address-form select[name="region_id"] option:contains('+long_name+')')) {
76 | $('#shipping-new-address-form select[name="region_id"] option:contains('+long_name+')').prop('selected', true).trigger('change');
77 | }
78 | } else if (self.options.componentForm[addressType] == 'route') {
79 | $('#shipping-new-address-form input[name="street[0]"]').val(long_name).trigger('keyup').trigger('keyup');
80 | } else if (self.options.componentForm[addressType] == 'street_1') {
81 | $('#shipping-new-address-form input[name="street[0]"]').val(long_name + ' '+ $('#shipping-new-address-form input[name="street[0]"]').val()).trigger('keyup');
82 | } else if (self.options.componentForm[addressType] == 'zip') {
83 | $('#shipping-new-address-form input[name="postcode"]').val(long_name).trigger('keyup');
84 | } else {
85 | $('#shipping-new-address-form input[name="'+self.options.componentForm[addressType]+'"]').val(long_name).trigger('keyup');
86 | }
87 | }
88 | }
89 | });
90 | clearInterval(self.options.shippingFunctions);
91 | }
92 | self.options.loopShipping = self.options.loopShipping + 1;
93 | if (self.options.loopShipping >= 11) {
94 | clearInterval(self.options.shippingFunctions);
95 | }
96 | }, 2000);
97 |
98 | $(document).on('change', 'select[name="billing_address_id"]', function() {
99 | if ($(this).find('option:last').prop('selected')) {
100 | self._fillInBillingAddress();
101 | }
102 | });
103 |
104 | $(document).on('click', 'input[name="billing-address-same-as-shipping"], .action-edit-address', function() {
105 | if ($(this).find('option:last').prop('selected')) {
106 | self._fillInBillingAddress();
107 | }
108 | });
109 | },
110 |
111 | /**
112 | * Fill in billing address
113 | *
114 | * @private
115 | */
116 | _fillInBillingAddress() {
117 | var self = this;
118 | if (!this.options.billingStreetFound) {
119 | this.options.billingFunctions = setInterval(function() {
120 | var street = $('#billing-new-address-form').find('input[name="street[0]"]')[0];
121 | if (street) {
122 | self.options.billingAutocomplete = new google.maps.places.Autocomplete(
123 | street,
124 | {types: ['geocode']}
125 | );
126 | self.options.billingAutocomplete.inputId = street.id;
127 | self.options.billingAutocomplete.setComponentRestrictions({'country': self._getCountriesCodeArray()});
128 | google.maps.event.addListener(self.options.billingAutocomplete, 'place_changed', function () {
129 | // Get the place details from the autocomplete object.
130 | var place = self.options.billingAutocomplete.getPlace();
131 | // Get each component of the address from the place details
132 | // and fill the corresponding field on the form.
133 | for (var i = place.address_components.length-1; i >= 0; i--) {
134 | var addressType = place.address_components[i].types[0];
135 | var long_name = place.address_components[i].long_name;
136 | var short_name = place.address_components[i].short_name;
137 | if (self.options.componentForm[addressType] && long_name) {
138 | if (self.options.componentForm[addressType] == 'country') {
139 | $('#billing-new-address-form select[name="country_id"]').val(short_name).trigger('change');
140 | } else if (self.options.componentForm[addressType] == 'region') {
141 | $('#billing-new-address-form input[name="region"]').val(long_name).trigger('keyup');
142 | if ($('#billing-new-address-form select[name="region_id"] option:contains('+long_name+')')) {
143 | $('#billing-new-address-form select[name="region_id"] option:contains('+long_name+')').prop('selected', true).trigger('change');
144 | }
145 | } else if (self.options.componentForm[addressType] == 'route') {
146 | $('#billing-new-address-form input[name="street[0]"]').val(long_name).trigger('keyup').trigger('keyup');
147 | } else if (self.options.componentForm[addressType] == 'street_1') {
148 | $('#billing-new-address-form input[name="street[0]"]').val(long_name + ' '+ $('#billing-new-address-form input[name="street[0]"]').val()).trigger('keyup');
149 | } else if (self.options.componentForm[addressType] == 'zip') {
150 | $('#billing-new-address-form input[name="postcode"]').val(long_name).trigger('keyup');
151 | } else {
152 | $('#billing-new-address-form input[name="'+self.options.componentForm[addressType]+'"]').val(long_name).trigger('keyup');
153 | }
154 | }
155 | }
156 | });
157 | clearInterval(self.options.billingFunctions);
158 | self.options.billingStreetFound = true;
159 | }
160 | self.options.loopBilling = self.options.loopBilling + 1;
161 | if (self.options.loopBilling >= 11) {
162 | clearInterval(self.options.billingFunctions);
163 | }
164 | }, 2000);
165 | }
166 | },
167 |
168 | /**
169 | * Convert countries code to array
170 | *
171 | * @private
172 | */
173 | _getCountriesCodeArray() {
174 | var countries = this.options.countries;
175 | return countries.split(',');
176 | }
177 | });
178 | return $.phpcuong.checkoutAddressAutofill;
179 | });
180 |
181 |
--------------------------------------------------------------------------------