From 9d51f6ae8e6765ecc021c208387e917fd46e94ff Mon Sep 17 00:00:00 2001 From: ksenia Date: Fri, 31 May 2019 08:37:37 -0400 Subject: [PATCH 1/3] Issue #2725: bugform validation improvements --- .eslintrc.json | 3 +- tests/functional/reporting-non-auth.js | 65 +++- webcompat/static/css/src/form.css | 17 +- webcompat/static/js/lib/bugform-validation.js | 48 +++ webcompat/static/js/lib/bugform.js | 312 ++++++++++-------- webcompat/templates/home-page/form.html | 42 +-- webcompat/templates/layout.html | 3 +- 7 files changed, 311 insertions(+), 179 deletions(-) create mode 100644 webcompat/static/js/lib/bugform-validation.js diff --git a/.eslintrc.json b/.eslintrc.json index a46226cb2..f4af4aaee 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -33,7 +33,8 @@ "require": true, "wcEvents": true, "wcTmpl": true, - "WindowHelpers": true + "WindowHelpers": true, + "Validation": true }, "rules": { "eqeqeq": [2, "smart"], diff --git a/tests/functional/reporting-non-auth.js b/tests/functional/reporting-non-auth.js index c1aa43506..46df38f36 100755 --- a/tests/functional/reporting-non-auth.js +++ b/tests/functional/reporting-non-auth.js @@ -28,10 +28,10 @@ registerSuite("Reporting (non-auth)", { ".js-report-buttons" ) .findAllByCssSelector(".js-report-buttons button") - .getAttribute("class") - .then(function(classNames) { - classNames.forEach(function(className) { - assert.include(className, "is-disabled"); + .getAttribute("disabled") + .then(function(values) { + values.forEach(function(value) { + assert.isNotNull(value); }); }) .end(); @@ -75,6 +75,10 @@ registerSuite("Reporting (non-auth)", { .click() .type("http:// example.com") .end() + .execute(function() { + var elm = document.querySelector("#url"); + WindowHelpers.sendEvent(elm, "blur"); + }) .sleep(500) .findByCssSelector(".form-message-error"); }, @@ -90,11 +94,15 @@ registerSuite("Reporting (non-auth)", { .type("sup") .end() .sleep(500) + .execute(function() { + var elm = document.querySelector("#url"); + WindowHelpers.sendEvent(elm, "blur"); + }) .findByCssSelector(".form-message-error") .getVisibleText() - .then(function(text) { + .then(function(texts) { assert.include( - text, + texts, "A valid URL is required", "URL validation message is shown" ); @@ -115,13 +123,16 @@ registerSuite("Reporting (non-auth)", { url("/issues/new"), ".js-report-buttons" ) - .findByCssSelector("#description") + .findByCssSelector("#url") + .type("http://coolguy.biz") + .end() + // pick a problem type + .findByCssSelector("[for=problem_category-0]") + .click() + .end() + .findByCssSelector(".js-Button-wrapper") .click() .end() - .execute(function() { - var elm = document.querySelector("#description"); - WindowHelpers.sendEvent(elm, "input"); - }) .sleep(500) .findByCssSelector(".form-message-error") .getVisibleText() @@ -250,10 +261,10 @@ registerSuite("Reporting (non-auth)", { .sleep(250) // now make sure the buttons aren't disabled anymore .findAllByCssSelector(".js-report-buttons button") - .getAttribute("class") - .then(function(classNames) { - classNames.forEach(function(className) { - assert.notInclude(className, "is-disabled"); + .getAttribute("disabled") + .then(function(values) { + values.forEach(function(value) { + assert.isNull(value); }); }) .end() @@ -412,6 +423,30 @@ registerSuite("Reporting (non-auth)", { ); }) .end(); + }, + "Submitting form without filling anything"() { + return FunctionalHelpers.openPage( + this, + url("/issues/new"), + ".js-report-buttons" + ) + .findByCssSelector(".js-Button-wrapper") + .click() + .end() + .sleep(500) + .findAllByCssSelector(".form-message-error") + .getVisibleText() + .then(function(texts) { + var errorTexts = [ + "A valid URL is required.", + "Problem type required.", + "A problem summary is required." + ]; + errorTexts.forEach(function(expectedText) { + assert.include(texts, expectedText, "Error messages don't match"); + }); + }) + .end(); } } }); diff --git a/webcompat/static/css/src/form.css b/webcompat/static/css/src/form.css index 3959eb2e0..526308c0d 100644 --- a/webcompat/static/css/src/form.css +++ b/webcompat/static/css/src/form.css @@ -37,9 +37,24 @@ max-width: none; } -.form-button-multiple .button { +.form-button-multiple .button-wrapper { + cursor: pointer; + display: flex; flex: 1 1 auto; margin: 20px 10px 0; + position: relative; +} + +.form-button-multiple .button-wrapper .button { + flex: 1; +} + +.form-button-multiple .button-wrapper .button:disabled { + pointer-events: none; +} + +.form-button-multiple .button-wrapper:hover .button { + opacity: .85; } .form-field { diff --git a/webcompat/static/js/lib/bugform-validation.js b/webcompat/static/js/lib/bugform-validation.js new file mode 100644 index 000000000..cfbc481b1 --- /dev/null +++ b/webcompat/static/js/lib/bugform-validation.js @@ -0,0 +1,48 @@ +/* exported Validation */ +function Validation() { + var GITHUB_REGEXP = /^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}$/i; + var ALLOWED_IMG_FORMAT = ["jpg", "jpeg", "jpe", "png", "gif", "bmp"]; + + var isReportableURL = function(url) { + var ok = url && (_.startsWith(url, "http:") || _.startsWith(url, "https:")); + ok &= !(_.startsWith(url, "http:// ") || _.startsWith(url, "https:// ")); + return ok; + }; + + /** + Check a string is a valid GitHub username + - maximum 39 chars + - alphanumerical characters and hyphens + - no two consecutive hyphens + */ + var isValidGitHubUsername = function(contact) { + return GITHUB_REGEXP.test(contact); + }; + + return { + isDescriptionValid: function(descField) { + var val = descField.val(); + return $.trim(val) !== ""; + }, + isUrlValid: function(urlField) { + var val = urlField.val(); + return $.trim(val) !== "" && isReportableURL(val); + }, + isGithubUserNameValid: function(contactField) { + var contact = contactField.val(); + return isValidGitHubUsername(contact) || $.trim(contact) === ""; + }, + isProblemTypeValid: function(problemTypeField) { + return problemTypeField.filter(":checked").length; + }, + isImageTypeValid: function(uploadField) { + var splitImg = uploadField.val().split("."); + var ext = splitImg[splitImg.length - 1].toLowerCase(); + + return _.includes(ALLOWED_IMG_FORMAT, ext); + }, + isOptionalValid: function(input) { + return !!input.val(); + } + }; +} diff --git a/webcompat/static/js/lib/bugform.js b/webcompat/static/js/lib/bugform.js index 9ceb9feff..1ccee46be 100644 --- a/webcompat/static/js/lib/bugform.js +++ b/webcompat/static/js/lib/bugform.js @@ -33,10 +33,11 @@ BugForm.prototype.onDOMReadyInit = function() { this.reportButton = $("#js-ReportBug"); this.removeBanner = $(".js-remove-upload"); this.submitButtons = $("#js-ReportForm .js-Button"); + this.submitButtonWrappers = $("#js-ReportForm .js-Button-wrapper"); this.submitTypeInput = $("#submit_type:hidden"); this.uploadLabel = $(".js-label-upload"); this.urlParamRegExp = /url=([^&]+)/; - this.githubRegexp = /^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}$/i; + this.validation = new Validation(); this.UPLOAD_LIMIT = 1024 * 1024 * 4; @@ -44,17 +45,20 @@ BugForm.prototype.onDOMReadyInit = function() { url: { el: $("#url"), valid: null, - helpText: "A valid URL is required." + helpText: "A valid URL is required.", + errFunction: "requiredField" }, - problem_type: { + problem_category: { el: $("[name=problem_category]"), valid: null, - helpText: "Problem type required." + helpText: "Problem type required.", + errFunction: "requiredField" }, description: { el: $("#description"), valid: null, - helpText: "A problem summary is required." + helpText: "A problem summary is required.", + errFunction: "requiredField" }, steps_reproduce: { el: $("#steps_reproduce"), @@ -67,17 +71,19 @@ BugForm.prototype.onDOMReadyInit = function() { valid: true, helpText: "Image must be one of the following: jpe, jpg, jpeg, png, gif, or bmp.", - altHelpText: "Please choose a smaller image (< 4MB)" + errFunction: "imageField" }, browser: { el: $("#browser"), valid: true, - helpText: null + helpText: null, + errFunction: "optionalField" }, os: { el: $("#os"), valid: true, - helpText: null + helpText: null, + errFunction: "optionalField" }, browser_test_type: { el: $("[name=browser_test]"), @@ -88,13 +94,14 @@ BugForm.prototype.onDOMReadyInit = function() { el: $("#contact"), valid: true, helpText: - "GitHub nicknames are 39 characters max, alphanumeric and hyphens only." + "GitHub nicknames are 39 characters max, alphanumeric and hyphens only.", + errFunction: "requiredField" } }; this.browserField = this.inputs.browser.el; this.osField = this.inputs.os.el; - this.problemType = this.inputs.problem_type.el; + this.problemType = this.inputs.problem_category.el; this.uploadField = this.inputs.image.el; this.urlField = this.inputs.url.el; this.descField = this.inputs.description.el; @@ -113,8 +120,8 @@ BugForm.prototype.init = function() { } this.disableSubmits(); - this.urlField.on("blur input", this.checkURLValidity.bind(this)); - this.descField.on("blur input", this.checkDescriptionValidity.bind(this)); + this.urlField.on("blur input", this.checkUrl.bind(this)); + this.descField.on("blur input", this.checkDescription.bind(this)); this.problemType.on("change", this.checkProblemTypeValidity.bind(this)); this.uploadField.on("change", this.checkImageTypeValidity.bind(this)); this.osField.on("blur", this.checkOptionalNonEmpty.bind(this, this.osField)); @@ -124,6 +131,7 @@ BugForm.prototype.init = function() { ); this.contactField.on("blur input", this.checkGitHubUsername.bind(this)); this.submitButtons.on("click", this.storeClickedButton.bind(this)); + this.submitButtonWrappers.on("click", this.onSubmitAttempt.bind(this)); this.form.on("submit", this.onFormSubmit.bind(this)); // prevent submit by hitting enter key for single line input fields @@ -285,99 +293,106 @@ BugForm.prototype.enableSubmits = function() { this.submitButtons.removeClass("is-disabled"); }; +/* determines function based on whether validation returns true or false */ +BugForm.prototype.determineValidityFunction = function(func, field, silent) { + if (func(field)) return "makeValid"; + return silent ? "makeInvalidSilent" : "makeInvalid"; +}; + BugForm.prototype.checkProblemTypeValidity = function() { - if (!$("[name=problem_category]:checked").length) { - this.makeInvalid("problem_type"); - } else { - this.makeValid("problem_type"); - } + var func = this.determineValidityFunction( + this.validation.isProblemTypeValid, + this.problemType + ); + this[func]("problem_category"); }; BugForm.prototype.checkImageTypeValidity = function(event) { - var splitImg = this.uploadField.val().split("."); - var ext = splitImg[splitImg.length - 1].toLowerCase(); - var allowed = ["jpg", "jpeg", "jpe", "png", "gif", "bmp"]; // Bail if there's no image. if (!this.uploadField.val()) { return; } - if (!_.includes(allowed, ext)) { - this.makeInvalid("image"); - } else { - this.makeValid("image"); - if (event) { - // We can just grab the 0th one, because we only allow uploading - // a single image at a time (for now) - this.convertToDataURI( - event.target.files[0], - this.showUploadPreview.bind(this) - ); - } + var func = this.determineValidityFunction( + this.validation.isImageTypeValid, + this.uploadField + ); + this[func]("image"); + + if (func === "makeValid" && event) { + // We can just grab the 0th one, because we only allow uploading + // a single image at a time (for now) + this.convertToDataURI( + event.target.files[0], + this.showUploadPreview.bind(this) + ); } - // null out input.value so we get a consistent // change event across browsers - event.target.value = null; + if (event) event.target.value = null; }; -BugForm.prototype.isReportableURL = function(url) { - var ok = url && (_.startsWith(url, "http:") || _.startsWith(url, "https:")); - ok &= !(_.startsWith(url, "http:// ") || _.startsWith(url, "https:// ")); - return ok; +BugForm.prototype.checkUrl = function(event) { + var isSilent = event.type === "input" || !this.urlField.val(); + this.checkURLValidity(isSilent); +}; + +BugForm.prototype.checkDescription = function() { + var isSilent = !this.descField.val(); + this.checkDescriptionValidity(isSilent); }; /* Check to see that the URL input element is not empty, or if it's a non-webby scheme. */ -BugForm.prototype.checkURLValidity = function() { - var val = this.urlField.val(); - if ($.trim(val) === "" || !this.isReportableURL(val)) { - this.makeInvalid("url"); - } else { - this.makeValid("url"); - } +BugForm.prototype.checkURLValidity = function(silent) { + var func = this.determineValidityFunction( + this.validation.isUrlValid, + this.urlField, + silent + ); + this[func]("url"); }; /* Check to see that the description input element is not empty. */ -BugForm.prototype.checkDescriptionValidity = function() { - var val = this.descField.val(); - if ($.trim(val) === "") { - this.makeInvalid("description"); - } else { - this.makeValid("description"); - } +BugForm.prototype.checkDescriptionValidity = function(silent) { + var func = this.determineValidityFunction( + this.validation.isDescriptionValid, + this.descField, + silent + ); + this[func]("description"); }; /* Check if Browser and OS are empty or not, only - so we can set them to valid (there is no invalid state) */ -BugForm.prototype.checkOptionalNonEmpty = function(input) { - var inputId = input.prop("id"); + so we can set them to valid (there is no invalid state)*/ +BugForm.prototype.checkOptionalNonEmpty = function(field) { + var func = this.determineValidityFunction( + this.validation.isOptionalValid, + field + ); + var inputId = field.prop("id"); + this[func](inputId); +}; - if (input.val()) { - this.makeValid(inputId); - } else { - this.makeInvalid(inputId); - } +/* Check to see if the GitHub username has the right syntax.*/ +BugForm.prototype.checkGitHubUsername = function() { + var func = this.determineValidityFunction( + this.validation.isGithubUserNameValid, + this.contactField + ); + this[func]("contact"); }; -/* -Check a string is a valid GitHub username - - maximum 39 chars - - alphanumerical characters and hyphens - - no two consecutive hyphens -*/ -BugForm.prototype.isValidGitHubUsername = function(contact) { - return this.githubRegexp.test(contact); +BugForm.prototype.onSubmitAttempt = function() { + this.performChecks(); }; -/* Check to see if the GitHub username has the right syntax. */ -BugForm.prototype.checkGitHubUsername = function() { - var contact = this.contactField.val(); - if (this.isValidGitHubUsername(contact) || $.trim(contact) === "") { - this.makeValid("contact"); - } else { - this.makeInvalid("contact"); - } +BugForm.prototype.performChecks = function() { + this.checkURLValidity(); + this.checkDescriptionValidity(); + this.checkProblemTypeValidity(); + this.checkImageTypeValidity(); + this.checkGitHubUsername(); }; BugForm.prototype.checkForm = function() { @@ -391,11 +406,7 @@ BugForm.prototype.checkForm = function() { ]; if (_.some(inputs, Boolean)) { // then, check validity - this.checkURLValidity(); - this.checkDescriptionValidity(); - this.checkProblemTypeValidity(); - this.checkImageTypeValidity(); - this.checkGitHubUsername(); + this.performChecks(); // and open the form, if it's not already open if (!this.reportButton.hasClass("is-open")) { this.reportButton.click(); @@ -410,88 +421,105 @@ BugForm.prototype.checkForm = function() { } }; -/* makeInvalid can take an {altHelp: true} options argument to select - alternate helpText to display */ -BugForm.prototype.makeInvalid = function(id, opts) { - // Early return if inline help is already in place. - if (this.inputs[id].valid === false) { - return; - } +BugForm.prototype.requiredField = function(id, inlineHelp) { + inlineHelp.insertAfter("label[for=" + id + "]"); +}; + +BugForm.prototype.imageField = function(id, inlineHelp) { + $(".form-upload-error").remove(); + + inlineHelp + .removeClass("form-message-error") + .addClass("form-upload-error") + .appendTo(".js-error-upload"); + + $(".js-label-upload").addClass("is-hidden"); + $(".js-remove-upload").addClass("is-hidden"); + $(".js-error-upload").removeClass("is-hidden"); + + $(".form-message-error").hide(); + $(".form-input-validation .error").hide(); + // "reset" the form field, because the file would get rejected + // from the server anyways. + this.uploadField.val(this.uploadField.get(0).defaultValue); +}; + +BugForm.prototype.optionalField = function(id) { + this.inputs[id].el + .parents(".js-Form-group") + .removeClass("is-error js-form-error"); +}; + +/* shows an error based on the errFunction in the config above */ +BugForm.prototype.showError = function(id) { + if (!this.inputs[id].hasOwnProperty("errFunction")) return; var inlineHelp = $("", { class: "label-icon-message form-message-error", - text: - opts && opts.altHelp - ? this.inputs[id].altHelpText - : this.inputs[id].helpText + text: this.inputs[id].helpText }); - this.inputs[id].valid = false; this.inputs[id].el .parents(".js-Form-group") .removeClass("is-validated js-no-error") .addClass("is-error js-form-error"); - switch (id) { - case "os": - case "browser": - // remove error classes, because these inputs are optional - this.inputs[id].el - .parents(".js-Form-group") - .removeClass("is-error js-form-error"); - break; - case "url": - case "contact": - case "description": - case "problem_type": - inlineHelp.insertAfter("label[for=" + id + "]"); - break; - case "image": - // hide the error in case we already saw one - $(".form-upload-error").remove(); - - inlineHelp - .removeClass("form-message-error") - .addClass("form-upload-error") - .appendTo(".js-error-upload"); - - $(".js-label-upload").addClass("is-hidden"); - $(".js-remove-upload").addClass("is-hidden"); - $(".js-error-upload").removeClass("is-hidden"); - - $(".form-message-error").hide(); - $(".form-input-validation .error").hide(); - // "reset" the form field, because the file would get rejected - // from the server anyways. - this.uploadField.val(this.uploadField.get(0).defaultValue); - // return early because we just cleared out the input. - // someone might decide to just not select an image. - return; + var func = this.inputs[id].errFunction; + this[func](id, inlineHelp); +}; + +BugForm.prototype.makeInvalid = function(id) { + // Early return if inline help is already in place. + if (this.inputs[id].valid === false) { + return; } + this.inputs[id].valid = false; + this.showError(id); + // someone might decide to just not select an image after seeing the error, + // so buttons shouldn't be disabled + if (id !== "image") this.disableSubmits(); +}; + +BugForm.prototype.makeInvalidSilent = function(id) { + this.removeSuccessStyle(this.inputs[id].el); this.disableSubmits(); }; -BugForm.prototype.makeValid = function(id) { - this.inputs[id].valid = true; - this.inputs[id].el - .parents(".js-Form-group") +BugForm.prototype.checkAllRequiredValid = function() { + return ( + this.inputs["url"].valid && + this.inputs["problem_category"].valid && + this.inputs["image"].valid && + this.inputs["description"].valid && + this.inputs["contact"].valid + ); +}; + +BugForm.prototype.enableSubmitsIfFormValid = function() { + if (this.checkAllRequiredValid()) { + this.enableSubmits(); + } +}; + +BugForm.prototype.removeSuccessStyle = function(el) { + el.parents(".js-Form-group").removeClass("is-validated js-no-error"); +}; + +BugForm.prototype.showSuccess = function(el) { + el.parents(".js-Form-group") .removeClass("is-error js-form-error") .addClass("is-validated js-no-error"); - this.inputs[id].el - .parents(".js-Form-group") + el.parents(".js-Form-group") .find(".form-message-error") .remove(); +}; - if ( - this.inputs["url"].valid && - this.inputs["problem_type"].valid && - this.inputs["image"].valid && - this.inputs["description"].valid - ) { - this.enableSubmits(); - } +BugForm.prototype.makeValid = function(id) { + this.inputs[id].valid = true; + this.showSuccess(this.inputs[id].el); + this.enableSubmitsIfFormValid(); }; /* diff --git a/webcompat/templates/home-page/form.html b/webcompat/templates/home-page/form.html index 39fd3c499..db9d65574 100644 --- a/webcompat/templates/home-page/form.html +++ b/webcompat/templates/home-page/form.html @@ -12,7 +12,7 @@

Report Site Issue

- {{ form.url.label(class_='form-label form-required') }} + {{ form.url.label(class_='form-label') }} {% if form.url.errors %} {% for error in form.url.errors %} {{ error }} @@ -26,7 +26,7 @@

Report Site Issue

- + {% if form.problem_category.errors %} {% for error in form.problem_category.errors %} {{ error }} @@ -41,7 +41,7 @@

Report Site Issue

- {{ form.description.label(class_='form-label form-required') }} + {{ form.description.label(class_='form-label') }} {% if form.description.errors %} {% for error in form.description.errors %} {{ error }} @@ -128,22 +128,26 @@

Report Site Issue

{% endif %}
- - +
+ +
+
+ +
All information included in this report will be publicly visible. diff --git a/webcompat/templates/layout.html b/webcompat/templates/layout.html index d51e297bc..fc876fece 100644 --- a/webcompat/templates/layout.html +++ b/webcompat/templates/layout.html @@ -32,6 +32,7 @@ + {%- if config['LOCALHOST'] -%} @@ -45,4 +46,4 @@ {% endfor %} {% block extrascripts %}{% endblock %} - \ No newline at end of file + From 508269a59e10c38e899b48383a6655b03a5a57f6 Mon Sep 17 00:00:00 2001 From: ksenia Date: Fri, 31 May 2019 15:16:57 -0400 Subject: [PATCH 2/3] Issue #2725: code review changes --- grunt-tasks/concat.js | 1 + webcompat/form.py | 4 ++-- webcompat/static/js/lib/bugform.js | 12 +++++++++--- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/grunt-tasks/concat.js b/grunt-tasks/concat.js index 3db6a8db0..0efdda3a1 100644 --- a/grunt-tasks/concat.js +++ b/grunt-tasks/concat.js @@ -20,6 +20,7 @@ module.exports = function(grunt) { "<%= jsPath %>/lib/flash-message.js", "<%= jsPath %>/lib/homepage.js", "<%= jsPath %>/lib/autogrow-textfield.js", + "<%= jsPath %>/lib/bugform-validation.js", "<%= jsPath %>/lib/bugform.js", "<%= jsDistPath %>/templates.js" ], diff --git a/webcompat/form.py b/webcompat/form.py index dc679364e..e70fc859b 100644 --- a/webcompat/form.py +++ b/webcompat/form.py @@ -61,10 +61,10 @@ username_message = u'A valid username must be {0} characters long'.format( random.randrange(0, 99)) -desc_label = u'Please write a short problem summary' +desc_label = u'Please write a short problem summary (mandatory)' desc_message = u'A problem summary is required.' -url_label = u'Site URL' +url_label = u'Site URL (mandatory)' browser_test_label = u'Did you test in another browser?' textarea_label = u'Please describe what happened, including any steps you took before you saw the problem' # noqa diff --git a/webcompat/static/js/lib/bugform.js b/webcompat/static/js/lib/bugform.js index 1ccee46be..7de074f11 100644 --- a/webcompat/static/js/lib/bugform.js +++ b/webcompat/static/js/lib/bugform.js @@ -295,7 +295,9 @@ BugForm.prototype.enableSubmits = function() { /* determines function based on whether validation returns true or false */ BugForm.prototype.determineValidityFunction = function(func, field, silent) { - if (func(field)) return "makeValid"; + if (func(field)) { + return "makeValid"; + } return silent ? "makeInvalidSilent" : "makeInvalid"; }; @@ -329,7 +331,9 @@ BugForm.prototype.checkImageTypeValidity = function(event) { } // null out input.value so we get a consistent // change event across browsers - if (event) event.target.value = null; + if (event) { + event.target.value = null; + } }; BugForm.prototype.checkUrl = function(event) { @@ -478,7 +482,9 @@ BugForm.prototype.makeInvalid = function(id) { this.showError(id); // someone might decide to just not select an image after seeing the error, // so buttons shouldn't be disabled - if (id !== "image") this.disableSubmits(); + if (id !== "image") { + this.disableSubmits(); + } }; BugForm.prototype.makeInvalidSilent = function(id) { From 196b5c3a967ff855eb62252e261f961682f209fe Mon Sep 17 00:00:00 2001 From: ksenia Date: Fri, 31 May 2019 17:18:07 -0400 Subject: [PATCH 3/3] Issue #2725: Run validation in "silent" mode on page refresh or when coming from the report site issue extension --- webcompat/static/js/lib/bugform.js | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/webcompat/static/js/lib/bugform.js b/webcompat/static/js/lib/bugform.js index 7de074f11..c31f7ce5e 100644 --- a/webcompat/static/js/lib/bugform.js +++ b/webcompat/static/js/lib/bugform.js @@ -301,15 +301,16 @@ BugForm.prototype.determineValidityFunction = function(func, field, silent) { return silent ? "makeInvalidSilent" : "makeInvalid"; }; -BugForm.prototype.checkProblemTypeValidity = function() { +BugForm.prototype.checkProblemTypeValidity = function(silent) { var func = this.determineValidityFunction( this.validation.isProblemTypeValid, - this.problemType + this.problemType, + silent ); this[func]("problem_category"); }; -BugForm.prototype.checkImageTypeValidity = function(event) { +BugForm.prototype.checkImageTypeValidity = function(event, silent) { // Bail if there's no image. if (!this.uploadField.val()) { return; @@ -317,7 +318,8 @@ BugForm.prototype.checkImageTypeValidity = function(event) { var func = this.determineValidityFunction( this.validation.isImageTypeValid, - this.uploadField + this.uploadField, + silent ); this[func]("image"); @@ -379,10 +381,11 @@ BugForm.prototype.checkOptionalNonEmpty = function(field) { }; /* Check to see if the GitHub username has the right syntax.*/ -BugForm.prototype.checkGitHubUsername = function() { +BugForm.prototype.checkGitHubUsername = function(event, silent) { var func = this.determineValidityFunction( this.validation.isGithubUserNameValid, - this.contactField + this.contactField, + silent ); this[func]("contact"); }; @@ -391,12 +394,12 @@ BugForm.prototype.onSubmitAttempt = function() { this.performChecks(); }; -BugForm.prototype.performChecks = function() { - this.checkURLValidity(); - this.checkDescriptionValidity(); - this.checkProblemTypeValidity(); - this.checkImageTypeValidity(); - this.checkGitHubUsername(); +BugForm.prototype.performChecks = function(isSilent) { + this.checkURLValidity(isSilent); + this.checkDescriptionValidity(isSilent); + this.checkProblemTypeValidity(isSilent); + this.checkImageTypeValidity(null, isSilent); + this.checkGitHubUsername(null, isSilent); }; BugForm.prototype.checkForm = function() { @@ -410,7 +413,7 @@ BugForm.prototype.checkForm = function() { ]; if (_.some(inputs, Boolean)) { // then, check validity - this.performChecks(); + this.performChecks(true); // and open the form, if it's not already open if (!this.reportButton.hasClass("is-open")) { this.reportButton.click();