Leonid Nikitin
23b71a09c6
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.
192 lines
8.4 KiB
JavaScript
192 lines
8.4 KiB
JavaScript
(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); |