329 lines
13 KiB
JavaScript
329 lines
13 KiB
JavaScript
|
||
let urlCreator = window.URL || window.webkitURL;
|
||
|
||
let currentAttachmentID = 0;
|
||
let currentBeerdName = [];
|
||
const deviceID = "web";
|
||
|
||
async function SavePhoto(self) {
|
||
document.getElementById("result").innerHTML = "";
|
||
let photo = document.getElementById("file-input").files[0];
|
||
let formData = new FormData();
|
||
formData.append("f", photo);
|
||
formData.append('device_id', deviceID);
|
||
let response = await fetch(self.action, { method: "POST", body: formData });
|
||
|
||
if (response.ok) {
|
||
let json = await response.json();
|
||
currentAttachmentID = json.uploaded_attach_id;
|
||
let shareID = json.share_id;
|
||
let style = "";
|
||
if (!shareID) {
|
||
style = "style='display:none'"
|
||
}
|
||
let text = `
|
||
<div class = "title-block">
|
||
<h3 class='image-results'>Результаты</h3>
|
||
<div id = "share-icon" onclick="ym(93420354,'reachGoal','share-icon'); return true;" data-link = "https://порода-по-фото.рф/beerds/dogs/share/${shareID}" ${style}>
|
||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||
<path d="M6.58900253,18.0753965 C6.5573092,17.8852365 6.54138127,17.692783 6.54138127,17.5 C6.54138127,15.5670034 8.10838464,14 10.0413813,14 L12.5,14 C12.7761424,14 13,14.2238576 13,14.5 L13,17.7267988 C13,17.8027316 13.0270017,17.8761901 13.0761794,17.9340463 C13.190639,18.0687047 13.3925891,18.085079 13.5272475,17.9706194 L20.5626572,11.9905211 C20.6161112,11.9450852 20.6657995,11.8953969 20.7112354,11.8419429 C21.1762277,11.2948932 21.1097069,10.4744711 20.5626572,10.0094789 L13.5272475,4.02938061 C13.4693913,3.98020285 13.3959328,3.95320119 13.32,3.95320119 C13.1432689,3.95320119 13,4.09647007 13,4.27320119 L13,7.5 C13,7.77614237 12.7761424,8 12.5,8 L9.5,8 C5.91014913,8 3,10.9101491 3,14.5 C3,17.3494045 4.26637093,19.0973664 6.88288761,19.8387069 L6.58900253,18.0753965 Z M10.0413813,15 C8.66066939,15 7.54138127,16.1192881 7.54138127,17.5 C7.54138127,17.6377022 7.55275836,17.7751689 7.57539646,17.9109975 L7.99319696,20.4178005 C8.0506764,20.7626772 7.74549866,21.0585465 7.40256734,20.990415 C3.83673227,20.2819767 2,18.0778979 2,14.5 C2,10.3578644 5.35786438,7 9.5,7 L12,7 L12,4.27320119 C12,3.54418532 12.5909841,2.95320119 13.32,2.95320119 C13.6332228,2.95320119 13.9362392,3.06458305 14.1748959,3.26744129 L21.2103057,9.24753957 C22.1781628,10.0702182 22.2958533,11.5217342 21.4731747,12.4895914 C21.3927882,12.5841638 21.3048781,12.6720739 21.2103057,12.7524604 L14.1748959,18.7325587 C13.6194301,19.2047047 12.7863861,19.1371606 12.3142401,18.5816947 C12.1113819,18.343038 12,18.0400216 12,17.7267988 L12,15 L10.0413813,15 Z"/>
|
||
</svg>
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
let uniqChecker = {};
|
||
|
||
// Функция для создания HTML галереи
|
||
const createGalleryHTML = (urls) => {
|
||
if (urls.length === 0) return '';
|
||
|
||
let mainImage = `<img src="${urls[0]}" class="main-image" data-urls='${JSON.stringify(urls)}' />`;
|
||
let otherImages = urls.slice(1)
|
||
.map(url => `<img src="${url}" class="thumbnail" />`)
|
||
.join('');
|
||
|
||
return `
|
||
<div class="gallery-container">
|
||
<div class="main-image-container">${mainImage}</div>
|
||
<div class="thumbnails" style="display:none;">${otherImages}</div>
|
||
</div>
|
||
`;
|
||
};
|
||
|
||
// Обработка основных результатов
|
||
for (let key in json.results) {
|
||
currentBeerdName.push(json.results[key]);
|
||
if (json.description != undefined) {
|
||
text += `<div class='image-block'><div class='image-text'>${json.results[key]} (вероятность: ${Math.round(parseFloat(key) * 100)}%) <br/><a href="${json.description[json.results[key]]}" target='_blank'>Описание и фото</a></div>`;
|
||
} else {
|
||
text += `<div class='image-block'><div class='image-text'>${json.results[key]} (вероятность: ${Math.round(parseFloat(key) * 100)}%)</div>`;
|
||
}
|
||
|
||
|
||
// Поиск всех изображений для текущего результата
|
||
let allUrls = [];
|
||
for (let imgKey in json.images) {
|
||
if (json.images[imgKey].name === json.results[key]) {
|
||
allUrls.push(...json.images[imgKey].url);
|
||
}
|
||
}
|
||
|
||
text += createGalleryHTML(allUrls);
|
||
text += "</div>";
|
||
uniqChecker[json.results[key]] = key;
|
||
}
|
||
// Обработка дополнительных результатов
|
||
for (let key in json.results_net) {
|
||
if (uniqChecker[json.results_net[key]] !== undefined) continue;
|
||
|
||
text += `<div class='image-block'><div class='image-text'>${json.results_net[key]}</div>`;
|
||
|
||
let allUrls = [];
|
||
for (let imgKey in json.images) {
|
||
if (json.images[imgKey].name === json.results_net[key]) {
|
||
allUrls.push(...json.images[imgKey].url);
|
||
}
|
||
}
|
||
|
||
text += createGalleryHTML(allUrls);
|
||
text += "</div>";
|
||
}
|
||
|
||
document.getElementById("result").innerHTML = text;
|
||
document.querySelector(".star-rating").style.display = "block";
|
||
document.getElementById("rate-stars").style.display = "block";
|
||
document.getElementById("feedback").textContent = "";
|
||
setTimeout(function(){
|
||
window.scrollBy({
|
||
top: 300,
|
||
behavior: 'smooth'
|
||
});
|
||
}, 100);
|
||
// Внутри функции SavePhoto после вставки HTML:
|
||
document.querySelectorAll('.main-image').forEach(img => {
|
||
img.addEventListener('click', function (e) {
|
||
const urls = JSON.parse(this.dataset.urls);
|
||
showModal(urls);
|
||
e.stopPropagation();
|
||
});
|
||
});
|
||
|
||
// Функции для работы модального окна
|
||
function showModal(urls) {
|
||
const modal = document.createElement('div');
|
||
modal.className = 'modal-overlay';
|
||
modal.innerHTML = `
|
||
<div class="modal-content">
|
||
<div class="thumbnails-grid">
|
||
${urls.map(url => `<img src="${url}" class="thumbnail" />`).join('')}
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
modal.addEventListener('click', (e) => {
|
||
if (e.target === modal) hideModal();
|
||
});
|
||
|
||
document.body.appendChild(modal);
|
||
modal.style.display = 'flex';
|
||
document.body.style.overflow = 'hidden';
|
||
}
|
||
|
||
function hideModal() {
|
||
const modal = document.querySelector('.modal-overlay');
|
||
if (modal) {
|
||
document.body.removeChild(modal);
|
||
document.body.style.overflow = 'auto';
|
||
}
|
||
}
|
||
let isTouchDevice = 'ontouchstart' in window;
|
||
let startX = 0;
|
||
let scrollLeft = 0;
|
||
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
const grid = document.querySelector('.thumbnails-grid');
|
||
|
||
if (isTouchDevice && grid) {
|
||
grid.addEventListener('touchstart', (e) => {
|
||
startX = e.touches[0].pageX - grid.offsetLeft;
|
||
scrollLeft = grid.scrollLeft;
|
||
});
|
||
|
||
grid.addEventListener('touchmove', (e) => {
|
||
e.preventDefault();
|
||
const x = e.touches[0].pageX - grid.offsetLeft;
|
||
const walk = (x - startX) * 2;
|
||
grid.scrollLeft = scrollLeft - walk;
|
||
});
|
||
}
|
||
});
|
||
|
||
} else {
|
||
alert("Ошибка HTTP: " + response.status);
|
||
}
|
||
}
|
||
const fileInput = document.getElementById("file-input");
|
||
if (fileInput) {
|
||
fileInput.addEventListener("change", function () {
|
||
let photo = document.getElementById("file-input").files[0];
|
||
let imageUrl = urlCreator.createObjectURL(photo);
|
||
document.getElementById("image").src = imageUrl;
|
||
document.getElementById("upload-image-text").innerHTML = "Ваше изображение:";
|
||
});
|
||
}
|
||
|
||
|
||
// Добавляем обработчик клика для бургера
|
||
document.addEventListener('DOMContentLoaded', function () {
|
||
const burger = document.querySelector('.burger');
|
||
const menu = document.querySelector('#menu ul');
|
||
|
||
burger.addEventListener('click', function () {
|
||
this.classList.toggle('active');
|
||
menu.classList.toggle('active');
|
||
});
|
||
|
||
|
||
// Закрываем меню при ресайзе окна
|
||
window.addEventListener('resize', function () {
|
||
if (window.innerWidth > 768) {
|
||
burger.classList.remove('active');
|
||
menu.classList.remove('active');
|
||
}
|
||
});
|
||
});
|
||
|
||
// описание породы
|
||
function openModal(imgElement) {
|
||
const modal = document.getElementById('modal');
|
||
const modalImg = document.getElementById('modal-img');
|
||
const caption = document.getElementById('caption');
|
||
modal.style.display = "block";
|
||
modalImg.src = imgElement.src;
|
||
caption.innerHTML = imgElement.alt;
|
||
}
|
||
function closeModal() {
|
||
document.getElementById('modal').style.display = "none";
|
||
}
|
||
|
||
|
||
/* ────────────────────────────────────────────────────── */
|
||
/* 3️⃣ Скрипт: выбор звезды, отправка POST‑запроса */
|
||
/* ────────────────────────────────────────────────────── */
|
||
(() => {
|
||
const ratingContainer = document.querySelector('.star-rating');
|
||
let stars = []
|
||
if (ratingContainer) {
|
||
stars = Array.from(ratingContainer.querySelectorAll('.star'));
|
||
}
|
||
const feedback = document.getElementById('feedback');
|
||
|
||
let currentRating = 0; // 0 = пока не выбрано
|
||
|
||
// Установить визуальное состояние (цвет, aria‑checked)
|
||
function setRating(value) {
|
||
currentRating = value;
|
||
stars.forEach(star => {
|
||
const starValue = Number(star.dataset.value);
|
||
const isSelected = starValue <= value;
|
||
star.classList.toggle('selected', isSelected);
|
||
star.setAttribute('aria-checked', isSelected);
|
||
});
|
||
}
|
||
|
||
// Отправка POST /vote
|
||
async function sendVote(value) {
|
||
// Подготовьте объект‑payload. Добавьте id‑токены, если нужны.
|
||
const payload = {
|
||
rate: value,
|
||
attachment_id: currentAttachmentID,
|
||
beerd_name: currentBeerdName[0],
|
||
};
|
||
|
||
try {
|
||
const resp = await fetch('/votes/do', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify(payload),
|
||
credentials: 'include' // если ваш API использует cookies
|
||
});
|
||
|
||
if (!resp.ok) {
|
||
throw new Error(`Ошибка ${resp.status}`);
|
||
}
|
||
|
||
feedback.textContent = 'Спасибо за оценку!';
|
||
feedback.style.color = '#080';
|
||
document.getElementById("rate-stars").style.display = "none";
|
||
} catch (err) {
|
||
console.error(err);
|
||
feedback.textContent = 'Произошла ошибка, попробуйте позже.';
|
||
feedback.style.color = '#a00';
|
||
}
|
||
}
|
||
|
||
// Обработчики клика и клавиатуры
|
||
stars.forEach(star => {
|
||
// Клик мышкой
|
||
star.addEventListener('click', () => {
|
||
const value = Number(star.dataset.value);
|
||
setRating(value);
|
||
sendVote(value);
|
||
});
|
||
|
||
// Навигация клавиатурой: пробел/Enter выбирает звезду
|
||
star.addEventListener('keydown', e => {
|
||
if (e.key === ' ' || e.key === 'Enter') {
|
||
e.preventDefault();
|
||
const value = Number(star.dataset.value);
|
||
setRating(value);
|
||
sendVote(value);
|
||
}
|
||
});
|
||
|
||
// При наведении меняем состояние всех звёзд до текущего
|
||
star.addEventListener('mouseover', () => {
|
||
setRating(Number(star.dataset.value));
|
||
});
|
||
|
||
star.addEventListener('mouseout', () => {
|
||
setRating(currentRating); // вернём к сохранённому
|
||
});
|
||
});
|
||
|
||
// По умолчанию не показываем выбранную оценку
|
||
setRating(0);
|
||
})();
|
||
|
||
|
||
document.addEventListener('click', function (event) {
|
||
const shareBtn = event.target.closest('#share-icon');
|
||
|
||
if (shareBtn) {
|
||
const link = shareBtn.getAttribute('data-link');
|
||
|
||
if (link) {
|
||
navigator.clipboard.writeText(link).then(() => {
|
||
showTooltip(shareBtn, 'Скопировано!');
|
||
});
|
||
}
|
||
}
|
||
});
|
||
|
||
function showTooltip(parent, text) {
|
||
// Проверяем, не висит ли уже тултип
|
||
if (parent.querySelector('.tooltip')) return;
|
||
|
||
const tooltip = document.createElement('span');
|
||
tooltip.className = 'tooltip';
|
||
tooltip.textContent = text;
|
||
|
||
parent.appendChild(tooltip);
|
||
|
||
// Удаляем тултип через 2 секунды
|
||
setTimeout(() => {
|
||
tooltip.classList.add('fade-out');
|
||
setTimeout(() => tooltip.remove(), 300);
|
||
}, 2000);
|
||
} |