summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBryce Johnson <bryce@gitlab.com>2016-10-21 13:49:09 +0200
committerBryce Johnson <bryce@gitlab.com>2016-11-01 16:48:37 +0100
commit93bd3dd8a8f587dc860c72653364d853c27bc6fd (patch)
treeb45644f71d9e21dec030480570d56848eda8ae12
parentaba94f65f039908d14643f3854e3c2901ff843aa (diff)
downloadgitlab-ce-93bd3dd8a8f587dc860c72653364d853c27bc6fd.tar.gz
Upgrade gl_field_errors to support more use cases.
-rw-r--r--app/assets/javascripts/gl_field_errors.js.es654
-rw-r--r--app/assets/javascripts/username_validator.js.es61
-rw-r--r--app/assets/stylesheets/framework/forms.scss32
-rw-r--r--app/assets/stylesheets/pages/login.scss30
-rw-r--r--app/views/devise/shared/_signup_box.html.haml2
-rw-r--r--spec/javascripts/fixtures/gl_field_errors.html.haml2
-rw-r--r--spec/javascripts/gl_field_errors_spec.js.es62
7 files changed, 84 insertions, 39 deletions
diff --git a/app/assets/javascripts/gl_field_errors.js.es6 b/app/assets/javascripts/gl_field_errors.js.es6
index be6c3ec274f..fa3e131c43b 100644
--- a/app/assets/javascripts/gl_field_errors.js.es6
+++ b/app/assets/javascripts/gl_field_errors.js.es6
@@ -4,18 +4,56 @@
* This class overrides the browser's validation error bubbles, displaying custom
* error messages for invalid fields instead. To begin validating any form, add the
* class `show-gl-field-errors` to the form element, and ensure error messages are
- * declared in each inputs' title attribute.
+ * declared in each inputs' `title` attribute. If no title is declared for an invalid
+ * field the user attempts to submit, "This field is required." will be shown by default.
*
- * Example:
+ * Opt not to validate certain fields by adding the class `gl-field-error-ignore` to the input.
+ *
+ * Set a custom error anchor for error message to be injected after with the class `gl-field-error-anchor`
+ *
+ * Examples:
+ *
+ * Basic:
*
* <form class='show-gl-field-errors'>
* <input type='text' name='username' title='Username is required.'/>
- *</form>
+ * </form>
+ *
+ * Ignore specific inputs (e.g. UsernameValidator):
+ *
+ * <form class='show-gl-field-errors'>
+ * <div class="form-group>
+ * <input type='text' class='gl-field-errors-ignore' pattern='[a-zA-Z0-9-_]+'/>
+ * </div>
+ * <div class="form-group">
+ * <input type='text' name='username' title='Username is required.'/>
+ * </div>
+ * </form>
+ *
+ * Custom Error Anchor (allows error message to be injected after specified element):
*
+ * <form class='show-gl-field-errors'>
+ * <div class="form-group gl-field-error-anchor">
+ * <input type='text' name='username' title='Username is required.'/>
+ * // Error message typically injected here
+ * </div>
+ * // Error message now injected here
+ * </form>
+ *
+ * */
+
+ /*
+ * Regex Patterns in use:
+ *
+ * Only alphanumeric: : "[a-zA-Z0-9]+"
+ * No special characters : "[a-zA-Z0-9-_]+",
+ *
* */
const errorMessageClass = 'gl-field-error';
const inputErrorClass = 'gl-field-error-outline';
+ const errorAnchorSelector = '.gl-field-error-anchor';
+ const ignoreInputSelector = '.gl-field-error-ignore';
class GlFieldError {
constructor({ input, formErrors }) {
@@ -34,16 +72,18 @@
}
initFieldValidation() {
+ const customErrorAnchor = this.inputElement.parents(errorAnchorSelector);
+ const errorAnchor = customErrorAnchor.length ? customErrorAnchor : this.inputElement;
+
// hidden when injected into DOM
- this.inputElement.after(this.fieldErrorElement);
+ errorAnchor.after(this.fieldErrorElement);
this.inputElement.off('invalid').on('invalid', this.handleInvalidSubmit.bind(this));
this.scopedSiblings = this.safelySelectSiblings();
}
safelySelectSiblings() {
// Apply `ignoreSelector` in markup to siblings whose visibility should not be toggled with input validity
- const ignoreSelector = '.validation-ignore';
- const unignoredSiblings = this.inputElement.siblings(`p:not(${ignoreSelector})`);
+ const unignoredSiblings = this.inputElement.siblings(`p:not(${ignoreInputSelector})`);
const parentContainer = this.inputElement.parent('.form-group');
// Only select siblings when they're scoped within a form-group with one input
@@ -125,7 +165,7 @@
}
}
- const customValidationFlag = 'no-gl-field-errors';
+ const customValidationFlag = 'gl-field-error-ignore';
class GlFieldErrors {
constructor(form) {
diff --git a/app/assets/javascripts/username_validator.js.es6 b/app/assets/javascripts/username_validator.js.es6
index c4dde575c6e..023ec0838dc 100644
--- a/app/assets/javascripts/username_validator.js.es6
+++ b/app/assets/javascripts/username_validator.js.es6
@@ -25,7 +25,6 @@
this.inputElement.on('keyup.username_check', () => {
const username = this.inputElement.val();
-
this.state.valid = this.inputDomElement.validity.valid;
this.state.empty = !username.length;
diff --git a/app/assets/stylesheets/framework/forms.scss b/app/assets/stylesheets/framework/forms.scss
index 761c07384f4..514d0868ba1 100644
--- a/app/assets/stylesheets/framework/forms.scss
+++ b/app/assets/stylesheets/framework/forms.scss
@@ -136,3 +136,35 @@ label {
color: $red-normal;
}
+.show-gl-field-errors {
+ .gl-field-success-outline {
+ border: 1px solid $green-normal;
+
+ &:focus {
+ box-shadow: 0 0 0 1px $green-normal inset, 0 1px 1px rgba(0, 0, 0, 0.075) inset, 0 0 4px 0 $green-normal;
+ border: 0 none;
+ }
+ }
+
+ .gl-field-error-outline {
+ border: 1px solid $red-normal;
+
+ &:focus {
+ box-shadow: 0 0 0 1px $red-normal inset, 0 1px 1px rgba(0, 0, 0, 0.075) inset, 0 0 4px 0 rgba(210, 40, 82, 0.6);
+ border: 0 none;
+ }
+ }
+
+ .gl-field-success-message {
+ color: $green-normal;
+ }
+
+ .gl-field-error-message {
+ color: $red-normal;
+ }
+
+ .gl-field-hint {
+ color: $gl-text-color;
+ }
+}
+
diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss
index a2f5c6c6bd3..10f67b47998 100644
--- a/app/assets/stylesheets/pages/login.scss
+++ b/app/assets/stylesheets/pages/login.scss
@@ -75,43 +75,17 @@
.login-body {
font-size: 13px;
-
input + p {
margin-top: 5px;
}
- .gl-field-success-outline {
- border: 1px solid $green-normal;
-
- &:focus {
- box-shadow: 0 0 0 1px $green-normal inset, 0 1px 1px rgba(0, 0, 0, 0.075) inset, 0 0 4px 0 $green-normal;
- border: 0 none;
- }
- }
-
- .gl-field-error-outline {
- border: 1px solid $red-normal;
-
- &:focus {
- box-shadow: 0 0 0 1px $red-normal inset, 0 1px 1px rgba(0, 0, 0, 0.075) inset, 0 0 4px 0 rgba(210, 40, 82, 0.6);
- border: 0 none;
- }
- }
-
- .username .validation-success,
- .gl-field-success-message {
+ .username .validation-success {
color: $green-normal;
}
- .username .validation-error,
- .gl-field-error-message {
+ .username .validation-error {
color: $red-normal;
}
-
- .gl-field-hint {
- color: $gl-text-color;
- }
-
}
}
diff --git a/app/views/devise/shared/_signup_box.html.haml b/app/views/devise/shared/_signup_box.html.haml
index d0bbcf3115e..99cde88fb08 100644
--- a/app/views/devise/shared/_signup_box.html.haml
+++ b/app/views/devise/shared/_signup_box.html.haml
@@ -8,7 +8,7 @@
= f.text_field :name, class: "form-control top", required: true, title: "This field is required."
%div.username.form-group
= f.label :username
- = f.text_field :username, class: "form-control middle no-gl-field-error", pattern: "[a-zA-Z0-9]+", required: true, title: 'Please create a username with only alphanumeric characters.'
+ = f.text_field :username, class: "form-control middle", pattern: "[a-zA-Z0-9]+", required: true, title: 'Please create a username with only alphanumeric characters.'
%p.validation-error.hide Username is already taken.
%p.validation-success.hide Username is available.
%p.validation-pending.hide Checking username availability...
diff --git a/spec/javascripts/fixtures/gl_field_errors.html.haml b/spec/javascripts/fixtures/gl_field_errors.html.haml
index 2526e5e33a5..3026af8856d 100644
--- a/spec/javascripts/fixtures/gl_field_errors.html.haml
+++ b/spec/javascripts/fixtures/gl_field_errors.html.haml
@@ -10,6 +10,6 @@
.form-group
%input.hidden{ type:'hidden' }
.form-group
- %input.custom.no-gl-field-errors{ type:'text' } Custom, do not validate
+ %input.custom.gl-field-error-ignore{ type:'text' } Custom, do not validate
.form-group
%input.submit{type: 'submit'} Submit
diff --git a/spec/javascripts/gl_field_errors_spec.js.es6 b/spec/javascripts/gl_field_errors_spec.js.es6
index 4bdd72800ea..220e8c32447 100644
--- a/spec/javascripts/gl_field_errors_spec.js.es6
+++ b/spec/javascripts/gl_field_errors_spec.js.es6
@@ -21,7 +21,7 @@
});
it('should ignore elements with custom error handling', function() {
- const customErrorFlag = 'no-gl-field-errors';
+ const customErrorFlag = 'gl-field-error-ignore';
const customErrorElem = $(`.${customErrorFlag}`);
expect(customErrorElem.length).toBe(1);