1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
import { debounce } from 'lodash';
import InputValidator from '~/validators/input_validator';
import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as 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 successMessageSelector = '.validation-success';
const pendingMessageSelector = '.validation-pending';
const unavailableMessageSelector = '.validation-error';
export default class UsernameValidator extends InputValidator {
constructor(opts = {}) {
super();
const container = opts.container || '';
const validateLengthElements = document.querySelectorAll(`${container} .js-validate-username`);
this.debounceValidateInput = debounce((inputDomElement) => {
UsernameValidator.validateUsernameInput(inputDomElement);
}, debounceTimeoutDuration);
validateLengthElements.forEach((element) =>
element.addEventListener('input', this.eventHandler.bind(this)),
);
}
eventHandler(event) {
const inputDomElement = event.target;
UsernameValidator.resetInputState(inputDomElement);
this.debounceValidateInput(inputDomElement);
}
static validateUsernameInput(inputDomElement) {
const username = inputDomElement.value;
if (inputDomElement.checkValidity() && username.length > 1) {
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')));
}
}
static fetchUsernameAvailability(username) {
return axios.get(`${rootUrl}/users/${username}/exists`).then(({ data }) => data.exists);
}
static setMessageVisibility(inputDomElement, messageSelector, isVisible = true) {
const messageElement = inputDomElement.parentElement.querySelector(messageSelector);
messageElement.classList.toggle('hide', !isVisible);
}
static setInputState(inputDomElement, success = true) {
inputDomElement.classList.toggle(successInputClass, success);
inputDomElement.classList.toggle(invalidInputClass, !success);
}
static resetInputState(inputDomElement) {
UsernameValidator.setMessageVisibility(inputDomElement, successMessageSelector, false);
UsernameValidator.setMessageVisibility(inputDomElement, unavailableMessageSelector, false);
if (inputDomElement.checkValidity()) {
inputDomElement.classList.remove(successInputClass, invalidInputClass);
}
}
}
|