Bug 1427961 - Put the asterisk next to required fields. r?mattn
MozReview-Commit-ID: 9KMFB9bS9hD
--- a/browser/components/payments/res/containers/address-form.css
+++ b/browser/components/payments/res/containers/address-form.css
@@ -25,15 +25,20 @@ address-form[address-fields]:not([addres
}
address-form .error input,
address-form .error select,
address-form .error textarea {
border: 1px solid #ce001a;
}
+label[required] > span::after {
+ /* The asterisk should be localized, bug 1472278 */
+ content: "*";
+}
+
.error-text:not(:empty) {
border-radius: 2px;
background-color: #ce001a;
color: #f9e6e9;
padding: .1em .5em;
margin-inline-start: .1em;
}
--- a/browser/components/payments/res/containers/address-form.js
+++ b/browser/components/payments/res/containers/address-form.js
@@ -141,20 +141,27 @@ export default class AddressForm extends
// Adding a new record: default persistence to checked when in a not-private session
this.persistCheckbox.hidden = false;
this.persistCheckbox.checked = !state.isPrivate;
}
this.formHandler.loadRecord(record);
// Add validation to some address fields
- let postalCodeInput = this.form.querySelector("#postal-code");
- let addressLevel1Input = this.form.querySelector("#address-level1");
- for (let element of [postalCodeInput, addressLevel1Input]) {
- element.required = element.closest(`#${element.id}-container`).style.display != "none";
+ for (let formElement of this.form.elements) {
+ let container = formElement.closest(`#${formElement.id}-container`);
+ if (formElement.localName == "button" || !container) {
+ continue;
+ }
+ let required = formElement.required && !formElement.disabled;
+ if (required) {
+ container.setAttribute("required", "true");
+ } else {
+ container.removeAttribute("required");
+ }
}
let shippingAddressErrors = request.paymentDetails.shippingAddressErrors;
for (let [errorName, errorSelector] of Object.entries(this._errorFieldMap)) {
let container = document.querySelector(errorSelector + "-container");
let field = document.querySelector(errorSelector);
let errorText = (shippingAddressErrors && shippingAddressErrors[errorName]) || "";
container.classList.toggle("error", !!errorText);
--- a/browser/components/payments/test/mochitest/test_address_form.html
+++ b/browser/components/payments/test/mochitest/test_address_form.html
@@ -295,16 +295,31 @@ add_task(async function test_field_valid
let postalCodeInput = form.form.querySelector("#postal-code");
let addressLevel1Input = form.form.querySelector("#address-level1");
ok(!postalCodeInput.value, "postal-code should be empty by default");
ok(!addressLevel1Input.value, "address-level1 should be empty by default");
ok(!postalCodeInput.checkValidity(), "postal-code should be invalid by default");
ok(!addressLevel1Input.checkValidity(), "address-level1 should be invalid by default");
let countrySelect = form.form.querySelector("#country");
+ let requiredFields = [
+ form.form.querySelector("#given-name"),
+ form.form.querySelector("#street-address"),
+ form.form.querySelector("#address-level2"),
+ postalCodeInput,
+ addressLevel1Input,
+ countrySelect,
+ ];
+ for (let field of requiredFields) {
+ let container = field.closest("label");
+ ok(container.hasAttribute("required"), "Container should have required attribute");
+ let label = field.closest("label").querySelector("span");
+ is(getComputedStyle(label, "::after").content, "\"*\"", "Asterisk should be on " + field.id);
+ }
+
countrySelect.selectedIndex = [...countrySelect.options].findIndex(o => o.value == "US");
countrySelect.dispatchEvent(new Event("change"));
sendStringAndCheckValidity(addressLevel1Input, "MI", true);
sendStringAndCheckValidity(addressLevel1Input, "", false);
sendStringAndCheckValidity(postalCodeInput, "B4N4N4", false);
sendStringAndCheckValidity(addressLevel1Input, "Nova Scotia", true);
sendStringAndCheckValidity(postalCodeInput, "R3J 3C7", false);
--- a/browser/extensions/formautofill/content/autofillEditForms.js
+++ b/browser/extensions/formautofill/content/autofillEditForms.js
@@ -135,31 +135,36 @@ class EditAddress extends EditAutofillFo
"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"));
+ let containerInputs = [...container.querySelectorAll("input, textarea, select")];
+ containerInputs.forEach(function(input) { input.disabled = false; });
+ inputs.push(...containerInputs);
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";
+ for (let input of [...container.querySelectorAll("input, textarea, select")]) {
+ input.disabled = true;
+ }
}
}
updatePostalCodeValidation(postalCodePattern) {
let postalCodeInput = document.getElementById("postal-code");
if (postalCodePattern && postalCodeInput.style.display != "none") {
postalCodeInput.setAttribute("pattern", postalCodePattern);
} else {
--- a/browser/extensions/formautofill/content/editAddress.xhtml
+++ b/browser/extensions/formautofill/content/editAddress.xhtml
@@ -17,51 +17,51 @@
<script src="chrome://formautofill/content/autofillEditForms.js"></script>
</head>
<body dir="&locale.dir;">
<form id="form" autocomplete="off">
<div>
<div id="name-container">
<label id="given-name-container">
<span data-localization="givenName"/>
- <input id="given-name" type="text"/>
+ <input id="given-name" type="text" required="true"/>
</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"/>
+ <textarea id="street-address" rows="3" required="true"/>
</label>
<label id="address-level2-container">
<span data-localization="city"/>
- <input id="address-level2" type="text"/>
+ <input id="address-level2" type="text" required="true"/>
</label>
<label id="address-level1-container">
<span/>
- <input id="address-level1" type="text"/>
+ <input id="address-level1" type="text" required="true"/>
</label>
<label id="postal-code-container">
<span/>
- <input id="postal-code" type="text"/>
+ <input id="postal-code" type="text" required="true"/>
</label>
</div>
<label id="country-container">
<span data-localization="country"/>
- <select id="country">
+ <select id="country" required="true">
<option/>
</select>
</label>
<p id="country-warning-message" data-localization="countryWarningMessage2"/>
<label id="email-container">
<span data-localization="email"/>
<input id="email" type="email"/>
</label>