Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
* develop:
  Update branch alias for develop
  Add an option to configure country translation (#14)
  Issue #12: Fix typo in variable name
  Fixes #12: Trigger event on autocomplete creation
  Update autocomplete label and help text
  Indicate symfony 5 compatibility
  Fix AddressEmbeddable:__toString
  Code style fixes.
  Allow the user to override the autocomplete results
  • Loading branch information
daften committed Mar 19, 2022
2 parents 006d381 + 7deae6d commit 553de62
Show file tree
Hide file tree
Showing 7 changed files with 154 additions and 84 deletions.
11 changes: 9 additions & 2 deletions Entity/AddressEmbeddable.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,17 @@ class AddressEmbeddable extends Address
public function __toString(): string
{
return implode(', ', array_filter([
$this->getRecipient(),
implode(' ', \array_filter([
$this->getGivenName(),
$this->getAdditionalName(),
$this->getFamilyName(),
])),
$this->getAddressLine1(),
$this->getAddressLine2(),
$this->getPostalCode().' '.$this->getLocality(),
implode(' ', \array_filter([
$this->getPostalCode(),
$this->getLocality(),
])),
$this->getCountryCode(),
]));
}
Expand Down
22 changes: 8 additions & 14 deletions Form/Type/AddressEmbeddableGmapsAutocompleteType.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
/**
* A form used to have an Embeddable Address form with autocomplete with Gmaps.
*/
class AddressEmbeddableGmapsAutocompleteType extends AbstractType
class AddressEmbeddableGmapsAutocompleteType extends AddressEmbeddableType
{

/**
Expand All @@ -42,8 +42,10 @@ class AddressEmbeddableGmapsAutocompleteType extends AbstractType

public function __construct(
GmapsAutocompleteService $gmapsAutocompleteService,
AddressOutputService $addressOutputService
AddressOutputService $addressOutputService,
EventSubscriberInterface $addressEmbeddableTypeSubscriber
) {
parent::__construct($addressEmbeddableTypeSubscriber);
$this->gmapsAutocompleteService = $gmapsAutocompleteService;
$this->addressOutputService = $addressOutputService;
}
Expand All @@ -53,27 +55,19 @@ public function __construct(
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
$builder
->add('addressAutocomplete', TextType::class, [
'mapped' => false,
'label' => 'Address',
'label' => 'addressAutocomplete',
'help' => 'This field is used to search an address on Google and fill it out below. This could override other values!',
'attr' => [
'class' => 'address-autocomplete-input',
'data-language' => $this->gmapsAutocompleteService->getLocale(),
'data-allowed-countries' => implode('|', $options['allowed_countries']),
'data-api-key' => $this->gmapsAutocompleteService->getGmapsApiKey(),
],
])
->add('countryCode', HiddenType::class)
->add('addressLine1', HiddenType::class)
->add('addressLine2', HiddenType::class)
->add('postalCode', HiddenType::class)
->add('sortingCode', HiddenType::class) // TODO
->add('locality', HiddenType::class)
->add('dependentLocality', HiddenType::class)
->add('administrativeArea', HiddenType::class)
;
]);
parent::buildForm($builder, $options);

$builder->addEventListener(
FormEvents::POST_SET_DATA,
Expand Down
3 changes: 3 additions & 0 deletions Form/Type/AddressEmbeddableType.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public function buildForm(FormBuilderInterface $builder, array $options)
$countryCodeOptions['choice_loader'] = null;
}
$countryCodeOptions['preferred_choices'] = $options['preferred_countries'];
$countryCodeOptions['choice_translation_domain'] = $options['choice_translation_domain'];
$builder
->add('countryCode', CountryType::class, $countryCodeOptions);

Expand All @@ -74,11 +75,13 @@ public function configureOptions(OptionsResolver $resolver)
'allowed_countries' => [], // After updating to Symfony 5.1, make this a filter list based on country code.
'preferred_countries' => [],
'default_country' => null,
'choice_translation_domain' => false,
]);

$resolver->setAllowedTypes('allowed_countries', ['null', 'string[]']);
$resolver->setAllowedTypes('preferred_countries', ['null', 'string[]']);
$resolver->setAllowedTypes('default_country', ['null', 'string']);
$resolver->setAllowedTypes('choice_translation_domain', ['null', 'string', 'boolean']);
}

/**
Expand Down
1 change: 1 addition & 0 deletions Resources/config/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ services:
arguments:
- '@daften.service.gmaps_autocomplete_service'
- '@daften.service.address_output_service'
- '@daften.form.subscriber.address'
public: false
tags:
- form.type
Expand Down
189 changes: 126 additions & 63 deletions Resources/public/js/addressGmapsAutocomplete.js
Original file line number Diff line number Diff line change
@@ -1,82 +1,145 @@
var countryCodeChange = require('./countryCodeChange');
module.exports = {
initialize: function () {
countryCodeChange.initialize();

$(document).ready(function () {
$('.address-autocomplete-input').once('initiate-autocomplete').each(function () {
// The element to work with.
var autocompleteField = $(this);
var apiKey = $(this).attr('data-api-key');
var language = $(this).attr('data-language');
var allowedCountries = $(this).attr('data-allowed-countries').split('|');
initializeAutoComplete($(this));
});
});

// Load Google Maps Javascript API library and ensure it's only loaded once
if (typeof(apiLoaded) === 'undefined' || !apiLoaded) {
$.getScript('https://maps.googleapis.com/maps/api/js?key='+apiKey+'&language='+language+'&libraries=places', function () {
apiLoaded = true;
initiateAutocomplete();
});
} else {
initiateAutocomplete();
function initializeAutoComplete($autocompleteField, oldAutocomplete) {
var apiKey = $autocompleteField.attr('data-api-key');
var language = $autocompleteField.attr('data-language');
var allowedCountries = $autocompleteField.attr('data-allowed-countries').split('|');

// Load Google Maps Javascript API library and ensure it's only loaded once
if (typeof(apiLoaded) === 'undefined' || !apiLoaded) {
$.getScript('https://maps.googleapis.com/maps/api/js?key='+apiKey+'&language='+language+'&libraries=places', function () {
apiLoaded = true;
createAutoCompleteInstance();
});
} else {
createAutoCompleteInstance();
}

function createAutoCompleteInstance() {

var autocomplete,
componentForm = {
street_number: 'short_name',
route: 'long_name',
neighborhood: 'short_name',
locality: 'long_name',
administrative_area_level_1: 'short_name',
country: 'short_name',
postal_code: 'short_name'
},
address = {
street_number: '.street-number',
route: '[id$=_addressLine1]',
route_2: '[id$=_addressLine2]',
sublocality_level_1: '[id$=_dependentLocality]',
locality: '[id$=_locality]',
administrative_area_level_1: '[id$=_administrativeArea]',
country: '[id$=_countryCode]',
postal_code: '[id$=_postalCode]',
};

autocomplete = new google.maps.places.Autocomplete(
/** @type {!HTMLInputElement} */($autocompleteField[0]),
{types: ['geocode']});

// Set restrict to the list of available countries.
if (allowedCountries.length) {
autocomplete.setComponentRestrictions(
{'country': allowedCountries});
}
function initiateAutocomplete() {
autocomplete.addListener('place_changed', function() {
fillInAddress(autocomplete.getPlace());
});

var autocomplete,
componentForm = {
street_number: 'short_name',
route: 'long_name',
neighborhood: 'short_name',
locality: 'long_name',
administrative_area_level_1: 'short_name',
country: 'short_name',
postal_code: 'short_name'
},
address = {
street_number: '.street-number',
route: '[id$=_addressLine1]',
route_2: '[id$=_addressLine2]',
sublocality_level_1: '[id$=_dependentLocality]',
locality: '[id$=_locality]',
administrative_area_level_1: '[id$=_administrativeArea]',
country: '[id$=_countryCode]',
postal_code: '[id$=_postalCode]',
};
$autocompleteField.trigger('autoCompleteCreated', [autocomplete]);

autocomplete = new google.maps.places.Autocomplete(
/** @type {!HTMLInputElement} */(autocompleteField[0]),
{types: ['geocode']});
// Get wrapper.
var wrapper = $autocompleteField.closest('[id$=_address]');
wrapper.closest('form').on('countryCodeChanged', '.address-embeddable', function () {
$(this).find('.address-autocomplete-input').once('initiate-autocomplete').each(function () {
initializeAutoComplete($(this), true);
});
});

// Set restrict to the list of available countries.
if (allowedCountries.length) {
autocomplete.setComponentRestrictions(
{'country': allowedCountries});
if (oldAutocomplete) {
var geocoder = new google.maps.Geocoder();
geocoder.geocode({address: $autocompleteField.val()}, function (result, status) {
if (status == google.maps.GeocoderStatus.OK) {
fillInAddress(result[0]);
}
});
}

function fillInAddress(place)
{
if (typeof place.name === 'undefined') {
place.name = getPlaceName(place);
}
autocomplete.addListener('place_changed', fillInAddress);
// This event was triggered because the address
// changed. Check to see if we need to trigger a
// country code change.
$countryCodeField = wrapper.find('[id$=_countryCode]');
if (place && place.address_components) {
for (var i = 0; i < place.address_components.length; i++) {
var addressType = place.address_components[i].types[0];
if (addressType !== 'country') {
continue;
}

// Get wrapper
var wrapper = autocompleteField.closest('[id$=_address]');
if (componentForm[addressType]) {
var value = place.address_components[i][componentForm[addressType]];
if (value && value.length && $countryCodeField.val() !== value) {
$countryCodeField.val(value).trigger('change');
// No use filling in the rest of the
// fields as they might change because the
// country code change triggers an ajax
// call to update the form.
return;
}
}
}

function fillInAddress()
{
// Fill initial address fields.
var place = autocomplete.getPlace();
var country = wrapper.find('select.country').val();
if (place && place.address_components) {
// Get each component of the address from the place details
// and fill the corresponding field on the form.
for (var i = 0; i < place.address_components.length; i++) {
var addressType = place.address_components[i].types[0];
if (componentForm[addressType]) {
var value = place.address_components[i][componentForm[addressType]];
// The place.name == "StreetName StreetNumber".
value = addressType == 'route' ? place.name : value;
if (value.length) {
wrapper.find(address[addressType]).val(value);
}
// Get each component of the address from the place details
// and fill the corresponding field on the form.
for (var i = 0; i < place.address_components.length; i++) {
var addressType = place.address_components[i].types[0];
if (componentForm[addressType]) {
var value = place.address_components[i][componentForm[addressType]];
// The place.name == "StreetName StreetNumber".
value = addressType == 'route' ? place.name : value;
if (value && value.length) {
wrapper.find(address[addressType]).val(value);
}
}
}
}
}
});
});

function getPlaceName(place) {
var street = '', streetNumber = '';
for (var i = 0; i < place.address_components.length; i++) {
switch (place.address_components[i].types[0]) {
case 'route':
street = place.address_components[i].long_name;
break;

case 'street_number':
streetNumber = place.address_components[i].long_name;
break;
}
}
return [street, streetNumber].join(' ');
}
}
}
}
};
4 changes: 3 additions & 1 deletion Resources/public/js/countryCodeChange.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ module.exports = {
$address.replaceWith(
$(html).find('#' + id)
);
$form.find('#' + id + '_countryCode').change(onCountryCodeChange);
var $countryCode = $form.find('#' + id + '_countryCode');
$countryCode.change(onCountryCodeChange);
$countryCode.closest('.address-embeddable').trigger('countryCodeChanged');
}
});
};
Expand Down
8 changes: 4 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
}
],
"require": {
"php": "^7.0.8",
"php": "^7.2.8",
"commerceguys/addressing": "^1",
"doctrine/orm": "^2.6",
"symfony/form": "^4.0",
"symfony/framework-bundle": "^4.0"
"symfony/form": "^4.4 | ^5.3",
"symfony/framework-bundle": "^4.4 | ^5.3"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.10",
Expand All @@ -32,7 +32,7 @@
},
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
"dev-develop": "1.0-dev"
}
}
}

0 comments on commit 553de62

Please sign in to comment.