Bug 1383687 - Order edit dialog fields based on country selected. r=lchang,steveck

MozReview-Commit-ID: 1qPxvHhNGtK

--HG--
extra : rebase_source : 12d892ce9c30f70b3fb5dd48c17744e23f45a604
This commit is contained in:
Scott Wu 2017-11-03 16:24:30 +08:00
parent 8512de2ea7
commit cefdf5737a
7 changed files with 274 additions and 66 deletions

View File

@ -657,6 +657,7 @@ this.FormAutofillUtils = {
* {
* {string} addressLevel1Label
* {string} postalCodeLabel
* {object} fieldsOrder
* }
*/
getFormFormat(country) {
@ -664,6 +665,7 @@ this.FormAutofillUtils = {
return {
"addressLevel1Label": dataset.state_name_type || "province",
"postalCodeLabel": dataset.zip_name_type || "postalCode",
"fieldsOrder": this.parseAddressFormat(dataset.fmt || "%N%n%O%n%A%n%C, %S %Z"),
};
},

View File

@ -13,38 +13,42 @@
</head>
<body>
<form id="form" autocomplete="off">
<label id="given-name-container">
<span data-localization="givenName"/>
<input id="given-name" type="text"/>
</label>
<label id="additional-name-container">
<span data-localization="additionalName"/>
<input id="additional-name" type="text"/>
</label>
<label id="family-name-container">
<span data-localization="familyName"/>
<input id="family-name" type="text"/>
</label>
<label id="organization-container">
<span data-localization="organization2"/>
<input id="organization" type="text"/>
</label>
<label id="street-address-container">
<span data-localization="streetAddress"/>
<textarea id="street-address" rows="3"/>
</label>
<label id="address-level2-container">
<span data-localization="city"/>
<input id="address-level2" type="text"/>
</label>
<label id="address-level1-container">
<span/>
<input id="address-level1" type="text"/>
</label>
<label id="postal-code-container">
<span/>
<input id="postal-code" type="text"/>
</label>
<div>
<div id="name-container">
<label id="given-name-container">
<span data-localization="givenName"/>
<input id="given-name" type="text"/>
</label>
<label id="additional-name-container">
<span data-localization="additionalName"/>
<input id="additional-name" type="text"/>
</label>
<label id="family-name-container">
<span data-localization="familyName"/>
<input id="family-name" type="text"/>
</label>
</div>
<label id="organization-container">
<span data-localization="organization2"/>
<input id="organization" type="text"/>
</label>
<label id="street-address-container">
<span data-localization="streetAddress"/>
<textarea id="street-address" rows="3"/>
</label>
<label id="address-level2-container">
<span data-localization="city"/>
<input id="address-level2" type="text"/>
</label>
<label id="address-level1-container">
<span/>
<input id="address-level1" type="text"/>
</label>
<label id="postal-code-container">
<span/>
<input id="postal-code" type="text"/>
</label>
</div>
<label id="country-container">
<span data-localization="country"/>
<select id="country">

View File

@ -120,6 +120,10 @@ class EditDialog {
this.handleKeyPress(event);
break;
}
case "change": {
this.handleChange(event);
break;
}
}
}
@ -180,6 +184,15 @@ class EditDialog {
this._elements.controlsContainer.removeEventListener("click", this);
document.removeEventListener("input", this);
}
// An interface to be inherited.
localizeDocument() {}
// An interface to be inherited.
handleSubmit(event) {}
// An interface to be inherited.
handleChange(event) {}
}
class EditAddress extends EditDialog {
@ -194,11 +207,42 @@ class EditAddress extends EditDialog {
* @param {string} country
*/
formatForm(country) {
// TODO: Use fmt to show/hide and order fields (Bug 1383687)
const {addressLevel1Label, postalCodeLabel} = FormAutofillUtils.getFormFormat(country);
const {addressLevel1Label, postalCodeLabel, fieldsOrder} = FormAutofillUtils.getFormFormat(country);
this._elements.addressLevel1Label.dataset.localization = addressLevel1Label;
this._elements.postalCodeLabel.dataset.localization = postalCodeLabel;
FormAutofillUtils.localizeMarkup(AUTOFILL_BUNDLE_URI, document);
this.arrangeFields(fieldsOrder);
}
arrangeFields(fieldsOrder) {
let fields = [
"name",
"organization",
"street-address",
"address-level2",
"address-level1",
"postal-code",
];
let inputs = [];
for (let i = 0; i < fieldsOrder.length; i++) {
let {fieldId, newLine} = fieldsOrder[i];
let container = document.getElementById(`${fieldId}-container`);
inputs.push(...container.querySelectorAll("input, textarea, select"));
container.style.display = "flex";
container.style.order = i;
container.style.pageBreakAfter = newLine ? "always" : "auto";
// Remove the field from the list of fields
fields.splice(fields.indexOf(fieldId), 1);
}
for (let i = 0; i < inputs.length; i++) {
// Assign tabIndex starting from 1
inputs[i].tabIndex = i + 1;
}
// Hide the remaining fields
for (let field of fields) {
let container = document.getElementById(`${field}-container`);
container.style.display = "none";
}
}
localizeDocument() {
@ -220,6 +264,20 @@ class EditAddress extends EditDialog {
await this.saveRecord(this.buildFormObject(), this._record ? this._record.guid : null);
window.close();
}
handleChange(event) {
this.formatForm(event.target.value);
}
attachEventListeners() {
this._elements.country.addEventListener("change", this);
super.attachEventListeners();
}
detachEventListeners() {
this._elements.country.removeEventListener("change", this);
super.detachEventListeners();
}
}
class EditCreditCard extends EditDialog {

View File

@ -26,13 +26,11 @@ select {
flex: 0 1 50%;
}
#family-name-container,
#organization-container,
#address-level2-container,
#tel-container {
padding-inline-end: 50%;
}
#name-container,
#street-address-container,
#email-container {
flex: 0 1 100%;

View File

@ -9,13 +9,17 @@ p {
display: flex;
}
form {
form,
div {
flex-wrap: wrap;
}
form {
/* Add extra space to ensure invalid input box is displayed properly */
padding: 2px;
}
form > label,
form label,
form > p {
margin: 0 0 0.5em !important;
}

View File

@ -34,32 +34,41 @@ add_task(async function test_saveAddress() {
ok(true, "Edit address dialog is closed");
resolve();
}, {once: true});
EventUtils.synthesizeKey("VK_TAB", {}, win);
EventUtils.synthesizeKey(TEST_ADDRESS_1["given-name"], {}, win);
EventUtils.synthesizeKey("VK_TAB", {}, win);
EventUtils.synthesizeKey(TEST_ADDRESS_1["additional-name"], {}, win);
EventUtils.synthesizeKey("VK_TAB", {}, win);
EventUtils.synthesizeKey(TEST_ADDRESS_1["family-name"], {}, win);
EventUtils.synthesizeKey("VK_TAB", {}, win);
EventUtils.synthesizeKey(TEST_ADDRESS_1.organization, {}, win);
EventUtils.synthesizeKey("VK_TAB", {}, win);
EventUtils.synthesizeKey(TEST_ADDRESS_1["street-address"], {}, win);
EventUtils.synthesizeKey("VK_TAB", {}, win);
EventUtils.synthesizeKey(TEST_ADDRESS_1["address-level2"], {}, win);
EventUtils.synthesizeKey("VK_TAB", {}, win);
EventUtils.synthesizeKey(TEST_ADDRESS_1["address-level1"], {}, win);
EventUtils.synthesizeKey("VK_TAB", {}, win);
EventUtils.synthesizeKey(TEST_ADDRESS_1["postal-code"], {}, win);
EventUtils.synthesizeKey("VK_TAB", {}, win);
EventUtils.synthesizeKey(TEST_ADDRESS_1.country, {}, win);
EventUtils.synthesizeKey("VK_TAB", {}, win);
EventUtils.synthesizeKey(TEST_ADDRESS_1.email, {}, win);
EventUtils.synthesizeKey("VK_TAB", {}, win);
EventUtils.synthesizeKey(TEST_ADDRESS_1.tel, {}, win);
EventUtils.synthesizeKey("VK_TAB", {}, win);
EventUtils.synthesizeKey("VK_TAB", {}, win);
info("saving address");
EventUtils.synthesizeKey("VK_RETURN", {}, win);
let doc = win.document;
// Verify labels
is(doc.querySelector("#address-level1-container > span").textContent, "State",
"US address-level1 label should be 'State'");
is(doc.querySelector("#postal-code-container > span").textContent, "Zip Code",
"US postal-code label should be 'Zip Code'");
// Input address info and verify move through form with tab keys
const keyInputs = [
"VK_TAB",
TEST_ADDRESS_1["given-name"],
"VK_TAB",
TEST_ADDRESS_1["additional-name"],
"VK_TAB",
TEST_ADDRESS_1["family-name"],
"VK_TAB",
TEST_ADDRESS_1.organization,
"VK_TAB",
TEST_ADDRESS_1["street-address"],
"VK_TAB",
TEST_ADDRESS_1["address-level2"],
"VK_TAB",
TEST_ADDRESS_1["address-level1"],
"VK_TAB",
TEST_ADDRESS_1["postal-code"],
"VK_TAB",
TEST_ADDRESS_1.country,
"VK_TAB",
TEST_ADDRESS_1.email,
"VK_TAB",
TEST_ADDRESS_1.tel,
"VK_TAB",
"VK_TAB",
"VK_RETURN",
];
keyInputs.forEach(input => EventUtils.synthesizeKey(input, {}, win));
}, {once: true});
});
let addresses = await getAddresses();
@ -95,3 +104,109 @@ add_task(async function test_editAddress() {
addresses = await getAddresses();
is(addresses.length, 0, "Address storage is empty");
});
add_task(async function test_saveAddressCA() {
await new Promise(resolve => {
let win = window.openDialog(EDIT_ADDRESS_DIALOG_URL);
win.addEventListener("load", () => {
win.addEventListener("unload", () => {
ok(true, "Edit address dialog is closed");
resolve();
}, {once: true});
let doc = win.document;
// Change country to verify labels
doc.querySelector("#country").focus();
EventUtils.synthesizeKey("Canada", {}, win);
is(doc.querySelector("#address-level1-container > span").textContent, "Province",
"CA address-level1 label should be 'Province'");
is(doc.querySelector("#postal-code-container > span").textContent, "Postal Code",
"CA postal-code label should be 'Postal Code'");
// Input address info and verify move through form with tab keys
doc.querySelector("#given-name").focus();
const keyInputs = [
TEST_ADDRESS_CA_1["given-name"],
"VK_TAB",
TEST_ADDRESS_CA_1["additional-name"],
"VK_TAB",
TEST_ADDRESS_CA_1["family-name"],
"VK_TAB",
TEST_ADDRESS_CA_1.organization,
"VK_TAB",
TEST_ADDRESS_CA_1["street-address"],
"VK_TAB",
TEST_ADDRESS_CA_1["address-level2"],
"VK_TAB",
TEST_ADDRESS_CA_1["address-level1"],
"VK_TAB",
TEST_ADDRESS_CA_1["postal-code"],
"VK_TAB",
TEST_ADDRESS_CA_1.country,
"VK_TAB",
TEST_ADDRESS_CA_1.email,
"VK_TAB",
TEST_ADDRESS_CA_1.tel,
"VK_TAB",
"VK_TAB",
"VK_RETURN",
];
keyInputs.forEach(input => EventUtils.synthesizeKey(input, {}, win));
}, {once: true});
});
let addresses = await getAddresses();
for (let [fieldName, fieldValue] of Object.entries(TEST_ADDRESS_CA_1)) {
is(addresses[0][fieldName], fieldValue, "check " + fieldName);
}
await removeAllRecords();
});
add_task(async function test_saveAddressDE() {
await new Promise(resolve => {
let win = window.openDialog(EDIT_ADDRESS_DIALOG_URL);
win.addEventListener("load", () => {
win.addEventListener("unload", () => {
ok(true, "Edit address dialog is closed");
resolve();
}, {once: true});
let doc = win.document;
// Change country to verify labels
doc.querySelector("#country").focus();
EventUtils.synthesizeKey("Germany", {}, win);
is(doc.querySelector("#postal-code-container > span").textContent, "Postal Code",
"DE postal-code label should be 'Postal Code'");
is(doc.querySelector("#address-level1-container").style.display, "none",
"DE address-level1 should be hidden");
// Input address info and verify move through form with tab keys
doc.querySelector("#given-name").focus();
const keyInputs = [
TEST_ADDRESS_DE_1["given-name"],
"VK_TAB",
TEST_ADDRESS_DE_1["additional-name"],
"VK_TAB",
TEST_ADDRESS_DE_1["family-name"],
"VK_TAB",
TEST_ADDRESS_DE_1.organization,
"VK_TAB",
TEST_ADDRESS_DE_1["street-address"],
"VK_TAB",
TEST_ADDRESS_DE_1["postal-code"],
"VK_TAB",
TEST_ADDRESS_DE_1["address-level2"],
"VK_TAB",
TEST_ADDRESS_DE_1.country,
"VK_TAB",
TEST_ADDRESS_DE_1.email,
"VK_TAB",
TEST_ADDRESS_DE_1.tel,
"VK_TAB",
"VK_TAB",
"VK_RETURN",
];
keyInputs.forEach(input => EventUtils.synthesizeKey(input, {}, win));
}, {once: true});
});
let addresses = await getAddresses();
for (let [fieldName, fieldValue] of Object.entries(TEST_ADDRESS_DE_1)) {
is(addresses[0][fieldName], fieldValue, "check " + fieldName);
}
await removeAllRecords();
});

View File

@ -1,5 +1,5 @@
/* exported MANAGE_ADDRESSES_DIALOG_URL, MANAGE_CREDIT_CARDS_DIALOG_URL, EDIT_ADDRESS_DIALOG_URL, EDIT_CREDIT_CARD_DIALOG_URL,
BASE_URL, TEST_ADDRESS_1, TEST_ADDRESS_2, TEST_ADDRESS_3, TEST_ADDRESS_4, TEST_ADDRESS_5,
BASE_URL, TEST_ADDRESS_1, TEST_ADDRESS_2, TEST_ADDRESS_3, TEST_ADDRESS_4, TEST_ADDRESS_5, TEST_ADDRESS_CA_1, TEST_ADDRESS_DE_1,
TEST_CREDIT_CARD_1, TEST_CREDIT_CARD_2, TEST_CREDIT_CARD_3, FORM_URL, CREDITCARD_FORM_URL,
FTU_PREF, ENABLED_AUTOFILL_ADDRESSES_PREF, AUTOFILL_CREDITCARDS_AVAILABLE_PREF, ENABLED_AUTOFILL_CREDITCARDS_PREF,
SYNC_USERNAME_PREF, SYNC_ADDRESSES_PREF, SYNC_CREDITCARDS_PREF, SYNC_CREDITCARDS_AVAILABLE_PREF, CREDITCARDS_USED_STATUS_PREF,
@ -67,6 +67,33 @@ const TEST_ADDRESS_5 = {
tel: "+16172535702",
};
const TEST_ADDRESS_CA_1 = {
"given-name": "John",
"additional-name": "R.",
"family-name": "Smith",
organization: "Mozilla",
"street-address": "163 W Hastings\nSuite 209",
"address-level2": "Vancouver",
"address-level1": "BC",
"postal-code": "V6B 1H5",
country: "CA",
tel: "+17787851540",
email: "timbl@w3.org",
};
const TEST_ADDRESS_DE_1 = {
"given-name": "John",
"additional-name": "R.",
"family-name": "Smith",
organization: "Mozilla",
"street-address": "Geb\u00E4ude 3, 4. Obergeschoss\nSchlesische Stra\u00DFe 27",
"address-level2": "Berlin",
"postal-code": "10997",
country: "DE",
tel: "+4930983333000",
email: "timbl@w3.org",
};
const TEST_CREDIT_CARD_1 = {
"cc-name": "John Doe",
"cc-number": "1234567812345678",