Leonid Nikitin
4bac5c10a0
Adjusted the path to style.css to be dynamically set using 'data-static-path' attribute. This change allows stylesheets to be fetched from the correct path based on the consumed API.
204 lines
9.1 KiB
JavaScript
204 lines
9.1 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');
|
||
const staticPath = element.getAttribute('data-static-path');
|
||
|
||
let windowCaptcha = null;
|
||
|
||
style.rel = 'stylesheet';
|
||
style.type = 'text/css';
|
||
style.href = staticPath + '/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, shadow);
|
||
});
|
||
|
||
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 => {
|
||
if (response.status === 429) {
|
||
setError('Вы превысили количество попыток. Обновите каптчу.', button);
|
||
return
|
||
}
|
||
return 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);
|