Skip to content

Commit fc43e28

Browse files
committed
Merge remote-tracking branch 'origin/MC-36060' into 2.4-develop-pr34
2 parents 52b9333 + 78ef828 commit fc43e28

File tree

3 files changed

+256
-15
lines changed

3 files changed

+256
-15
lines changed

app/code/Magento/Checkout/view/frontend/web/js/region-updater.js

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,10 @@ define([
157157
regionInput = $(this.options.regionInputId),
158158
postcode = $(this.options.postcodeId),
159159
label = regionList.parent().siblings('label'),
160-
container = regionList.parents('div.field');
160+
container = regionList.parents('div.field'),
161+
regionsEntries,
162+
regionId,
163+
regionData;
161164

162165
this._clearError();
163166
this._checkRegionRequired(country);
@@ -168,8 +171,14 @@ define([
168171
// Populate state/province dropdown list if available or use input box
169172
if (this.options.regionJson[country]) {
170173
this._removeSelectOptions(regionList);
171-
$.each(this.options.regionJson[country], $.proxy(function (key, value) {
172-
this._renderSelectOption(regionList, key, value);
174+
regionsEntries = _.pairs(this.options.regionJson[country]);
175+
regionsEntries.sort(function (a, b) {
176+
return a[1].name > b[1].name ? 1 : -1;
177+
});
178+
$.each(regionsEntries, $.proxy(function (key, value) {
179+
regionId = value[0];
180+
regionData = value[1];
181+
this._renderSelectOption(regionList, regionId, regionData);
173182
}, this));
174183

175184
if (this.currentRegionOption) {
@@ -193,7 +202,7 @@ define([
193202
regionList.hide();
194203
container.hide();
195204
} else {
196-
regionList.show();
205+
regionList.removeAttr('disabled').show();
197206
}
198207
}
199208

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
/*
2+
* Copyright © Magento, Inc. All rights reserved.
3+
* See COPYING.txt for license details.
4+
*/
5+
/*eslint-disable max-nested-callbacks*/
6+
/*jscs:disable jsDoc*/
7+
define([
8+
'jquery',
9+
'Magento_Checkout/js/region-updater'
10+
], function ($) {
11+
'use strict';
12+
13+
var regionJson = {
14+
'config': {
15+
'show_all_regions': true,
16+
'regions_required': [
17+
'US'
18+
]
19+
},
20+
'US': {
21+
'1': {
22+
'code': 'AL',
23+
'name': 'Alabama'
24+
},
25+
'2': {
26+
'code': 'AK',
27+
'name': 'Alaska'
28+
},
29+
'3': {
30+
'code': 'AS',
31+
'name': 'American Samoa'
32+
}
33+
},
34+
'DE': {
35+
'81': {
36+
'code': 'BAY',
37+
'name': 'Bayern'
38+
},
39+
'82': {
40+
'code': 'BER',
41+
'name': 'Berlin'
42+
},
43+
'83': {
44+
'code': 'BRG',
45+
'name': 'Brandenburg'
46+
}
47+
}
48+
},
49+
defaultCountry = 'GB',
50+
countries = {
51+
'': '',
52+
'US': 'United States',
53+
'GB': 'United Kingdom',
54+
'DE': 'Germany'
55+
},
56+
regions = {
57+
'': 'Please select a region, state or province.'
58+
},
59+
countryEl,
60+
regionSelectEl,
61+
regionInputEl,
62+
postalCodeEl,
63+
formEl,
64+
containerEl;
65+
66+
function createFormField() {
67+
var fieldWrapperEl = document.createElement('div'),
68+
labelEl = document.createElement('label'),
69+
inputControlEl = document.createElement('div'),
70+
i;
71+
72+
fieldWrapperEl.appendChild(labelEl);
73+
fieldWrapperEl.appendChild(inputControlEl);
74+
75+
for (i = 0; i < arguments.length; i++) {
76+
inputControlEl.appendChild(arguments[i]);
77+
}
78+
labelEl.setAttribute('class', 'label');
79+
fieldWrapperEl.setAttribute('class', 'field required');
80+
inputControlEl.setAttribute('class', 'control');
81+
82+
return fieldWrapperEl;
83+
}
84+
85+
function buildSelectOptions(select, options, defaultOption) {
86+
var optionValue,
87+
optionEl;
88+
89+
defaultOption = typeof defaultOption === 'undefined' ? '' : defaultOption;
90+
91+
// eslint-disable-next-line guard-for-in
92+
for (optionValue in options) {
93+
if (options.hasOwnProperty(optionValue)) {
94+
optionEl = document.createElement('option');
95+
optionEl.setAttribute('value', optionValue);
96+
optionEl.textContent = countries[optionValue];
97+
// eslint-disable-next-line max-depth
98+
if (defaultOption === optionValue) {
99+
optionEl.setAttribute('selected', 'selected');
100+
}
101+
select.add(optionEl);
102+
}
103+
}
104+
}
105+
106+
function init(config) {
107+
var defaultConfig = {
108+
'optionalRegionAllowed': true,
109+
'regionListId': '#' + regionSelectEl.id,
110+
'regionInputId': '#' + regionInputEl.id,
111+
'postcodeId': '#' + postalCodeEl.id,
112+
'form': '#' + formEl.id,
113+
'regionJson': regionJson,
114+
'defaultRegion': 0,
115+
'countriesWithOptionalZip': ['GB']
116+
};
117+
118+
$(countryEl).regionUpdater($.extend({}, defaultConfig, config || {}));
119+
}
120+
121+
beforeEach(function () {
122+
containerEl = document.createElement('div');
123+
formEl = document.createElement('form');
124+
regionSelectEl = document.createElement('select');
125+
regionInputEl = document.createElement('input');
126+
postalCodeEl = document.createElement('input');
127+
countryEl = document.createElement('select');
128+
regionSelectEl.setAttribute('id', 'region_id');
129+
regionSelectEl.setAttribute('style', 'display:none;');
130+
regionInputEl.setAttribute('id', 'region');
131+
regionInputEl.setAttribute('style', 'display:none;');
132+
countryEl.setAttribute('id', 'country');
133+
postalCodeEl.setAttribute('id', 'zip');
134+
formEl.setAttribute('id', 'test_form');
135+
formEl.appendChild(createFormField(countryEl));
136+
formEl.appendChild(createFormField(regionSelectEl, regionInputEl));
137+
formEl.appendChild(createFormField(postalCodeEl));
138+
containerEl.appendChild(formEl);
139+
buildSelectOptions(regionSelectEl, regions);
140+
buildSelectOptions(countryEl, countries, defaultCountry);
141+
document.body.appendChild(containerEl);
142+
});
143+
144+
afterEach(function () {
145+
$(containerEl).remove();
146+
formEl = undefined;
147+
containerEl = undefined;
148+
regionSelectEl = undefined;
149+
regionInputEl = undefined;
150+
postalCodeEl = undefined;
151+
countryEl = undefined;
152+
});
153+
154+
describe('Magento_Checkout/js/region-updater', function () {
155+
it('Check that default country is selected', function () {
156+
init();
157+
expect($(countryEl).val()).toBe(defaultCountry);
158+
});
159+
it('Check that region list is not displayed when selected country has no predefined regions', function () {
160+
init();
161+
$(countryEl).val('GB').change();
162+
expect($(regionInputEl).is(':visible')).toBe(true);
163+
expect($(regionInputEl).is(':disabled')).toBe(false);
164+
expect($(regionSelectEl).is(':visible')).toBe(false);
165+
expect($(regionSelectEl).is(':disabled')).toBe(true);
166+
});
167+
it('Check country that has predefined and optional regions', function () {
168+
init();
169+
$(countryEl).val('DE').change();
170+
expect($(regionSelectEl).is(':visible')).toBe(true);
171+
expect($(regionSelectEl).is(':disabled')).toBe(false);
172+
expect($(regionSelectEl).hasClass('required-entry')).toBe(false);
173+
expect($(regionInputEl).is(':visible')).toBe(false);
174+
expect(
175+
$(regionSelectEl).find('option')
176+
.map(function () {
177+
return this.textContent;
178+
})
179+
.get()
180+
).toContain('Berlin');
181+
});
182+
it('Check country that has predefined and required regions', function () {
183+
init();
184+
$(countryEl).val('US').change();
185+
expect($(regionSelectEl).is(':visible')).toBe(true);
186+
expect($(regionSelectEl).is(':disabled')).toBe(false);
187+
expect($(regionSelectEl).hasClass('required-entry')).toBe(true);
188+
expect($(regionInputEl).is(':visible')).toBe(false);
189+
expect(
190+
$(regionSelectEl).find('option')
191+
.map(function () {
192+
return this.textContent;
193+
})
194+
.get()
195+
).toContain('Alaska');
196+
});
197+
it('Check that region fields are not displayed for country with optional regions if configured', function () {
198+
init({
199+
optionalRegionAllowed: false
200+
});
201+
$(countryEl).val('DE').change();
202+
expect($(regionSelectEl).is(':visible')).toBe(false);
203+
expect($(regionInputEl).is(':visible')).toBe(false);
204+
});
205+
});
206+
});

lib/web/mage/adminhtml/form.js

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ define([
133133
this.config = regions.config;
134134
delete regions.config;
135135
this.regions = regions;
136+
this.sortedRegions = this.getSortedRegions();
136137
this.disableAction = typeof disableAction === 'undefined' ? 'hide' : disableAction;
137138
this.clearRegionValueOnDisable = typeof clearRegionValueOnDisable === 'undefined' ?
138139
false : clearRegionValueOnDisable;
@@ -246,11 +247,13 @@ define([
246247
* Update.
247248
*/
248249
update: function () {
249-
var option, region, def, regionId;
250+
var option, selectElement, def, regionId, region;
250251

251-
if (this.regions[this.countryEl.value]) {
252+
selectElement = this.regionSelectEl;
253+
254+
if (this.sortedRegions[this.countryEl.value]) {
252255
if (this.lastCountryId != this.countryEl.value) { //eslint-disable-line eqeqeq
253-
def = this.regionSelectEl.getAttribute('defaultValue');
256+
def = selectElement.getAttribute('defaultValue');
254257

255258
if (this.regionTextEl) {
256259
if (!def) {
@@ -259,26 +262,27 @@ define([
259262
this.regionTextEl.value = '';
260263
}
261264

262-
this.regionSelectEl.options.length = 1;
265+
selectElement.options.length = 1;
263266

264-
for (regionId in this.regions[this.countryEl.value]) { //eslint-disable-line guard-for-in
265-
region = this.regions[this.countryEl.value][regionId];
267+
this.sortedRegions[this.countryEl.value].forEach(function (item) {
268+
regionId = item[0];
269+
region = item[1];
266270

267271
option = document.createElement('OPTION');
268272
option.value = regionId;
269273
option.text = region.name.stripTags();
270274
option.title = region.name;
271275

272-
if (this.regionSelectEl.options.add) {
273-
this.regionSelectEl.options.add(option);
276+
if (selectElement.options.add) {
277+
selectElement.options.add(option);
274278
} else {
275-
this.regionSelectEl.appendChild(option);
279+
selectElement.appendChild(option);
276280
}
277281

278282
if (regionId == def || region.name.toLowerCase() == def || region.code.toLowerCase() == def) { //eslint-disable-line
279-
this.regionSelectEl.value = regionId;
283+
selectElement.value = regionId;
280284
}
281-
}
285+
});
282286
}
283287

284288
if (this.disableAction == 'hide') { //eslint-disable-line eqeqeq
@@ -340,6 +344,28 @@ define([
340344
display ? marks[0].show() : marks[0].hide();
341345
}
342346
}
347+
},
348+
349+
/**
350+
* Sort regions from JSON by name
351+
*
352+
* @returns {*[]}
353+
*/
354+
getSortedRegions: function () {
355+
var country, regionsEntries, regionsByCountry;
356+
357+
regionsByCountry = [];
358+
359+
for (country in this.regions) { //eslint-disable-line guard-for-in
360+
regionsEntries = Object.entries(this.regions[country]);
361+
regionsEntries.sort(function (a, b) {
362+
return a[1].name > b[1].name ? 1 : -1;
363+
});
364+
365+
regionsByCountry[country] = regionsEntries;
366+
}
367+
368+
return regionsByCountry;
343369
}
344370
};
345371

0 commit comments

Comments
 (0)