Bug 1656057, implement form validation and disable form for an invalid event r=mstriemer,sfoster,fluent-reviewers,flod

Disables all elements in the form except for those within the invalid section.
Hides the form until printers become available.

Differential Revision: https://phabricator.services.mozilla.com/D86989
This commit is contained in:
Emma Malysz 2020-08-17 23:10:40 +00:00
parent 8103eaba24
commit f68ef97340
4 changed files with 39 additions and 8 deletions

View file

@ -262,11 +262,18 @@ input[type="text"] {
content: url("chrome://global/content/portrait.svg"); content: url("chrome://global/content/portrait.svg");
} }
select:invalid,
input[type="number"]:invalid { input[type="number"]:invalid {
border: 1px solid #D70022; border: 1px solid #D70022;
box-shadow: 0 0 0 1px #D70022, 0 0 0 4px rgba(215, 0, 34, 0.3); box-shadow: 0 0 0 1px #D70022, 0 0 0 4px rgba(215, 0, 34, 0.3);
} }
.error-message {
font-size: 12px;
color: #D70022;
margin-top: 4px;
}
#percent-scale { #percent-scale {
appearance: textfield; appearance: textfield;
margin-inline-start: 4px; margin-inline-start: 4px;

View file

@ -54,6 +54,7 @@
autocomplete="off" disabled required> autocomplete="off" disabled required>
</span> </span>
</div> </div>
<p id="error-invalid-scale" hidden="true" data-l10n-id="printui-error-invalid-scale" class="error-message"></p>
</div> </div>
</template> </template>

View file

@ -415,6 +415,7 @@ class DestinationPicker extends PrintUIControlMixin(HTMLSelectElement) {
if (e.type == "available-destinations") { if (e.type == "available-destinations") {
this.setOptions(e.detail); this.setOptions(e.detail);
this.required = true;
} }
} }
} }
@ -509,33 +510,52 @@ customElements.define("copy-count-input", CopiesInput, {
extends: "input", extends: "input",
}); });
class PrintUIForm extends PrintUIControlMixin(HTMLElement) { class PrintUIForm extends PrintUIControlMixin(HTMLFormElement) {
initialize() { initialize() {
super.initialize(); super.initialize();
this.addEventListener("submit", this); this.addEventListener("submit", this);
this.addEventListener("click", this); this.addEventListener("click", this);
this.addEventListener("input", this);
} }
handleEvent(e) { handleEvent(e) {
if (e.target.id == "open-dialog-link") { if (e.target.id == "open-dialog-link") {
this.dispatchEvent(new Event("open-system-dialog", { bubbles: true })); this.dispatchEvent(new Event("open-system-dialog", { bubbles: true }));
return;
} }
if (e.type == "submit") { if (e.type == "submit") {
e.preventDefault(); e.preventDefault();
switch (e.submitter.name) { switch (e.submitter.name) {
case "print": case "print":
if (!this.checkValidity()) {
return;
}
this.dispatchEvent(new Event("print", { bubbles: true })); this.dispatchEvent(new Event("print", { bubbles: true }));
break; break;
case "cancel": case "cancel":
this.dispatchEvent(new Event("cancel-print", { bubbles: true })); this.dispatchEvent(new Event("cancel-print", { bubbles: true }));
break; break;
} }
} else if (e.type == "input") {
let isValid = this.checkValidity();
let section = e.target.closest(".section-block");
for (let element of this.elements) {
// If we're valid, enable all inputs.
// Otherwise, disable the valid inputs other than the cancel button and the elements
// in the invalid section.
element.disabled =
element.hasAttribute("disallowed") ||
(!isValid &&
element.validity.valid &&
element.name != "cancel" &&
element.closest(".section-block") != section);
}
} }
} }
} }
customElements.define("print-form", PrintUIForm); customElements.define("print-form", PrintUIForm, { extends: "form" });
class ScaleInput extends PrintUIControlMixin(HTMLElement) { class ScaleInput extends PrintUIControlMixin(HTMLElement) {
get templateId() { get templateId() {
@ -546,10 +566,11 @@ class ScaleInput extends PrintUIControlMixin(HTMLElement) {
super.initialize(); super.initialize();
this._percentScale = this.querySelector("#percent-scale"); this._percentScale = this.querySelector("#percent-scale");
this._percentScale.addEventListener("input", this);
this._shrinkToFitChoice = this.querySelector("#fit-choice"); this._shrinkToFitChoice = this.querySelector("#fit-choice");
this._scaleChoice = this.querySelector("#percent-scale-choice"); this._scaleChoice = this.querySelector("#percent-scale-choice");
this._scaleError = this.querySelector("#error-invalid-scale");
this._percentScale.addEventListener("input", this);
this.addEventListener("input", this); this.addEventListener("input", this);
} }
@ -558,6 +579,7 @@ class ScaleInput extends PrintUIControlMixin(HTMLElement) {
this._shrinkToFitChoice.checked = shrinkToFit; this._shrinkToFitChoice.checked = shrinkToFit;
this._scaleChoice.checked = !shrinkToFit; this._scaleChoice.checked = !shrinkToFit;
this._percentScale.disabled = shrinkToFit; this._percentScale.disabled = shrinkToFit;
this._percentScale.toggleAttribute("disallowed", shrinkToFit);
// If the user had an invalid input and switches back to "fit to page", // If the user had an invalid input and switches back to "fit to page",
// we repopulate the scale field with the stored, valid scaling value. // we repopulate the scale field with the stored, valid scaling value.
@ -568,27 +590,24 @@ class ScaleInput extends PrintUIControlMixin(HTMLElement) {
} }
handleEvent(e) { handleEvent(e) {
e.stopPropagation();
if (e.target == this._shrinkToFitChoice || e.target == this._scaleChoice) { if (e.target == this._shrinkToFitChoice || e.target == this._scaleChoice) {
this.dispatchSettingsChange({ this.dispatchSettingsChange({
shrinkToFit: this._shrinkToFitChoice.checked, shrinkToFit: this._shrinkToFitChoice.checked,
}); });
this._scaleError.hidden = true;
return; return;
} }
window.clearTimeout(this.invalidTimeoutId); window.clearTimeout(this.invalidTimeoutId);
if (this._percentScale.checkValidity() && e.type == "input") { if (this._percentScale.checkValidity() && e.type == "input") {
// TODO: set the customError element to hidden ( Bug 1656057 )
this.invalidTimeoutId = window.setTimeout(() => { this.invalidTimeoutId = window.setTimeout(() => {
this.dispatchSettingsChange({ this.dispatchSettingsChange({
scaling: Number(this._percentScale.value / 100), scaling: Number(this._percentScale.value / 100),
}); });
}, INVALID_INPUT_DELAY_MS); }, INVALID_INPUT_DELAY_MS);
} }
// TODO: populate a customError element with erorMessage contents this._scaleError.hidden = this._percentScale.validity.valid;
} }
} }
customElements.define("scale-input", ScaleInput); customElements.define("scale-input", ScaleInput);

View file

@ -54,3 +54,7 @@ printui-primary-button-save = Save
printui-cancel-button = Cancel printui-cancel-button = Cancel
printui-loading = Preparing Preview printui-loading = Preparing Preview
## Error messages shown when a user has an invalid input
printui-error-invalid-scale = Scale must be a number between 10 and 200.