service-captcha-gui/exmplate/script.js
Leonid Nikitin 23b71a09c6
Added fallback for empty error messages.
In the case where the data.errors object does not have any explicit errors, the diff adds a fallback. The resulting error message displayed will then be the general data message. This prevents situations where the user receives an empty error message.
2023-11-23 01:10:04 +06:00

192 lines
8.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

(function (document) {
const captchaBlocks = document.querySelectorAll('div.captcha-service-kor-elf');
captchaBlocks.forEach(function (element) {
const shadow = element.attachShadow({ mode: 'closed' });
const button = document.createElement("button");
const style = document.createElement('link');
const domain = element.getAttribute('data-domain');
const token = element.getAttribute('data-token');
let windowCaptcha = null;
style.rel = 'stylesheet';
style.type = 'text/css';
style.href = 'style.css';
shadow.appendChild(style);
button.textContent = 'Я не робот!';
button.type = 'button';
button.classList.add('button-open-window-captcha');
shadow.appendChild(button);
button.addEventListener('click', function () {
if (windowCaptcha === null) {
windowCaptcha = createWindowCaptcha(shadow, domain, token);
}
windowCaptcha.style.display = 'block';
actionGetCaptcha(windowCaptcha, domain, token, shadow);
});
});
function createWindowCaptcha (shadow, domain, token) {
const windowCaptcha = document.createElement('div');
windowCaptcha.classList.add('window-captcha');
windowCaptcha.innerHTML = `<div class="window-captcha__content">
<div class="window-captcha__content__header">Я не робот! <button type="button" class="window-captcha__reload"></button><button type="button" class="window-captcha__close">X</button></div>
<div class="window-captcha__content__body"></div>
</div>`;
shadow.appendChild(windowCaptcha);
windowCaptcha.addEventListener('click', function (event) {
if (event.target !== windowCaptcha) {
return null;
}
actionClose(windowCaptcha);
});
windowCaptcha.querySelector('button.window-captcha__close').addEventListener('click', function () {
actionClose(windowCaptcha);
});
windowCaptcha.querySelector('button.window-captcha__reload').addEventListener('click', function () {
actionGetCaptcha(windowCaptcha, domain, token);
});
return windowCaptcha;
}
function actionClose(windowCaptcha)
{
windowCaptcha.style.display = 'none';
}
function actionGetCaptcha(windowCaptcha, domain, token, shadow)
{
let bodyBlock = windowCaptcha.querySelector('div.window-captcha__content__body');
if (bodyBlock.querySelectorAll('.loading').length > 0) {
return null;
}
bodyBlock.innerHTML = '<div class="loading"></div>';
fetch(domain + '/api/v1/captcha', {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'public-token': token
}
})
.then(response => response.json())
.then(function (data) {
let originalWidth = data.image_body.width;
let originalHeight = data.image_body.height;
bodyBlock.innerHTML = `
<form method="post">
<div class="window-captcha__content__body__head"><img src="${ data.image_head.base64 }" width="100%"></div>
<p>Выберите значение в том порядке, на котором на картинке выше:</p>
<div class="window-captcha__content__body__coordinator"><img src="${ data.image_body.base64 }" width="100%" /></div>
<input type="hidden" name="captcha_key" class="captcha_key" value="${ data.captcha_key }" />
<button type="button" class="window-captcha__content__body__button">Я не робот!</button>
</form>
`;
let blockCoordinator = bodyBlock.querySelector('div.window-captcha__content__body__coordinator');
let blockCoordinatorImg = blockCoordinator.querySelector('img');
blockCoordinatorImg.addEventListener('click', function (event) {
let pointer = document.createElement('div');
pointer.style.left = ( event.offsetX / blockCoordinatorImg.width * 100 ) + '%';
pointer.style.top = ( event.offsetY / blockCoordinatorImg.height * 100 ) + '%';
pointer.classList.add('pointer');
let coordinatorX = event.offsetX * (originalWidth / blockCoordinatorImg.width)
let coordinatorY = event.offsetY * (originalHeight / blockCoordinatorImg.height)
let pointerNumber = blockCoordinator.querySelectorAll('.pointer').length + 1
pointer.innerHTML = `
<span class="pounter__number">${ pointerNumber }</span>
<input type="hidden" class="x" name="pointer[][x]" value="${ Math.round(coordinatorX) }" />
<input type="hidden" class="y" name="pointer[][y]" value="${ Math.round(coordinatorY) }" />
`;
pointer.addEventListener('click', function () {
pointer.remove();
blockCoordinator.querySelectorAll('.pointer').forEach(function (elementPointer, pointIndex) {
elementPointer.querySelector('span.pounter__number').textContent = pointIndex + 1;
});
});
blockCoordinator.appendChild(pointer);
});
bodyBlock.querySelector('.window-captcha__content__body__button').addEventListener('click', function () {
checkingCaptcha(bodyBlock, domain, token, shadow);
});
})
.catch(error => {
bodyBlock.innerHTML = `<div class="window-captcha__content__body__error">Произошла ошибка, сервис с каптчей не ответил. Попробуйте ещё раз!</div>`;
});
}
function checkingCaptcha (bodyBlock, domain, token, shadow) {
let button = bodyBlock.querySelector('button.window-captcha__content__body__button');
if (button.querySelectorAll('.loading').length > 0) {
return null;
}
let loadingSpan = document.createElement('span');
loadingSpan.classList.add('loading');
button.appendChild(loadingSpan);
let data = {
captcha_key: bodyBlock.querySelector('.captcha_key').value,
verification: []
};
bodyBlock.querySelectorAll('.pointer').forEach(function (elementPointer) {
data["verification"].push({
x: elementPointer.querySelector('.x').value,
y: elementPointer.querySelector('.y').value
});
});
fetch(domain + '/api/v1/captcha', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'public-token': token
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(function (data) {
if (typeof data.errors !== 'undefined') {
let errorMessage = '';
for (let key in data.errors) {
errorMessage += data.errors[key] + '<br>';
}
if (errorMessage === '') {
errorMessage = data.message;
}
setError(errorMessage, button);
return
}
shadow.querySelector('button.button-open-window-captcha').remove();
let captchaVerified = document.createElement('div');
captchaVerified.innerHTML = `<span class="captcha-verified">Ура!!! Проверку прошли!</span><input type="hidden" name="captcha-verified" value="${ data.captcha_key }">`;
shadow.appendChild(captchaVerified);
shadow.querySelector('.window-captcha').remove();
})
.catch(error => {
setError('Произошла ошибка!', button)
}).finally(function () {
loadingSpan.remove();
});
}
function setError(message, button) {
let errorBlock = document.createElement('div');
errorBlock.classList.add("error-message");
errorBlock.innerHTML = message;
button.before(errorBlock);
setTimeout( function () {
errorBlock.remove();
}, 3000);
}
})(document);