summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/pages/sessions/new/username_validator.js
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/pages/sessions/new/username_validator.js')
-rw-r--r--app/assets/javascripts/pages/sessions/new/username_validator.js148
1 files changed, 47 insertions, 101 deletions
diff --git a/app/assets/javascripts/pages/sessions/new/username_validator.js b/app/assets/javascripts/pages/sessions/new/username_validator.js
index 7a41805bada..36d1e773134 100644
--- a/app/assets/javascripts/pages/sessions/new/username_validator.js
+++ b/app/assets/javascripts/pages/sessions/new/username_validator.js
@@ -1,133 +1,79 @@
-/* eslint-disable consistent-return, class-methods-use-this */
+import InputValidator from '~/validators/input_validator';
-import $ from 'jquery';
import _ from 'underscore';
import axios from '~/lib/utils/axios_utils';
import flash from '~/flash';
import { __ } from '~/locale';
const debounceTimeoutDuration = 1000;
+const rootUrl = gon.relative_url_root;
const invalidInputClass = 'gl-field-error-outline';
const successInputClass = 'gl-field-success-outline';
-const unavailableMessageSelector = '.username .validation-error';
-const successMessageSelector = '.username .validation-success';
-const pendingMessageSelector = '.username .validation-pending';
-const invalidMessageSelector = '.username .gl-field-error';
+const successMessageSelector = '.validation-success';
+const pendingMessageSelector = '.validation-pending';
+const unavailableMessageSelector = '.validation-error';
-export default class UsernameValidator {
- constructor() {
- this.inputElement = $('#new_user_username');
- this.inputDomElement = this.inputElement.get(0);
- this.state = {
- available: false,
- valid: false,
- pending: false,
- empty: true,
- };
+export default class UsernameValidator extends InputValidator {
+ constructor(opts = {}) {
+ super();
- const debounceTimeout = _.debounce(username => {
- this.validateUsername(username);
- }, debounceTimeoutDuration);
-
- this.inputElement.on('keyup.username_check', () => {
- const username = this.inputElement.val();
-
- this.state.valid = this.inputDomElement.validity.valid;
- this.state.empty = !username.length;
+ const container = opts.container || '';
+ const validateLengthElements = document.querySelectorAll(`${container} .js-validate-username`);
- if (this.state.valid) {
- return debounceTimeout(username);
- }
-
- this.renderState();
- });
+ this.debounceValidateInput = _.debounce(inputDomElement => {
+ UsernameValidator.validateUsernameInput(inputDomElement);
+ }, debounceTimeoutDuration);
- // Override generic field validation
- this.inputElement.on('invalid', this.interceptInvalid.bind(this));
+ validateLengthElements.forEach(element =>
+ element.addEventListener('input', this.eventHandler.bind(this)),
+ );
}
- renderState() {
- // Clear all state
- this.clearFieldValidationState();
-
- if (this.state.valid && this.state.available) {
- return this.setSuccessState();
- }
-
- if (this.state.empty) {
- return this.clearFieldValidationState();
- }
-
- if (this.state.pending) {
- return this.setPendingState();
- }
+ eventHandler(event) {
+ const inputDomElement = event.target;
- if (!this.state.valid) {
- return this.setInvalidState();
- }
-
- if (!this.state.available) {
- return this.setUnavailableState();
- }
- }
-
- interceptInvalid(event) {
- event.preventDefault();
- event.stopPropagation();
+ UsernameValidator.resetInputState(inputDomElement);
+ this.debounceValidateInput(inputDomElement);
}
- validateUsername(username) {
- if (this.state.valid) {
- this.state.pending = true;
- this.state.available = false;
- this.renderState();
- axios
- .get(`${gon.relative_url_root}/users/${username}/exists`)
- .then(({ data }) => this.setAvailabilityState(data.exists))
+ static validateUsernameInput(inputDomElement) {
+ const username = inputDomElement.value;
+
+ if (inputDomElement.checkValidity() && username.length > 0) {
+ UsernameValidator.setMessageVisibility(inputDomElement, pendingMessageSelector);
+ UsernameValidator.fetchUsernameAvailability(username)
+ .then(usernameTaken => {
+ UsernameValidator.setInputState(inputDomElement, !usernameTaken);
+ UsernameValidator.setMessageVisibility(inputDomElement, pendingMessageSelector, false);
+ UsernameValidator.setMessageVisibility(
+ inputDomElement,
+ usernameTaken ? unavailableMessageSelector : successMessageSelector,
+ );
+ })
.catch(() => flash(__('An error occurred while validating username')));
}
}
- setAvailabilityState(usernameTaken) {
- if (usernameTaken) {
- this.state.available = false;
- } else {
- this.state.available = true;
- }
- this.state.pending = false;
- this.renderState();
+ static fetchUsernameAvailability(username) {
+ return axios.get(`${rootUrl}/users/${username}/exists`).then(({ data }) => data.exists);
}
- clearFieldValidationState() {
- this.inputElement.siblings('p').hide();
-
- this.inputElement.removeClass(invalidInputClass).removeClass(successInputClass);
+ static setMessageVisibility(inputDomElement, messageSelector, isVisible = true) {
+ const messageElement = inputDomElement.parentElement.querySelector(messageSelector);
+ messageElement.classList.toggle('hide', !isVisible);
}
- setUnavailableState() {
- const $usernameUnavailableMessage = this.inputElement.siblings(unavailableMessageSelector);
- this.inputElement.addClass(invalidInputClass).removeClass(successInputClass);
- $usernameUnavailableMessage.show();
+ static setInputState(inputDomElement, success = true) {
+ inputDomElement.classList.toggle(successInputClass, success);
+ inputDomElement.classList.toggle(invalidInputClass, !success);
}
- setSuccessState() {
- const $usernameSuccessMessage = this.inputElement.siblings(successMessageSelector);
- this.inputElement.addClass(successInputClass).removeClass(invalidInputClass);
- $usernameSuccessMessage.show();
- }
+ static resetInputState(inputDomElement) {
+ UsernameValidator.setMessageVisibility(inputDomElement, successMessageSelector, false);
+ UsernameValidator.setMessageVisibility(inputDomElement, unavailableMessageSelector, false);
- setPendingState() {
- const $usernamePendingMessage = $(pendingMessageSelector);
- if (this.state.pending) {
- $usernamePendingMessage.show();
- } else {
- $usernamePendingMessage.hide();
+ if (inputDomElement.checkValidity()) {
+ inputDomElement.classList.remove(successInputClass, invalidInputClass);
}
}
-
- setInvalidState() {
- const $inputErrorMessage = $(invalidMessageSelector);
- this.inputElement.addClass(invalidInputClass).removeClass(successInputClass);
- $inputErrorMessage.show();
- }
}