Leonid Nikitin
876fcc9e6b
A conditional block of code was added to handle the case when 'captcha_key' is not defined. This is to manage the scenario when captcha verification fails, providing an error message to the user and thus improving user experience.
197 lines
8.5 KiB
JavaScript
197 lines
8.5 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
|
||
}
|
||
if (typeof data.captcha_key === 'undefined') {
|
||
setError('Произошла ошибка!', 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); |