beerds/server/static/scripts.js

280 lines
9.9 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.

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 text = "<h3 class='image-results'>Результаты</h3>";
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');
const stars = Array.from(ratingContainer.querySelectorAll('.star'));
const feedback = document.getElementById('feedback');
let currentRating = 0; // 0 = пока не выбрано
// Установить визуальное состояние (цвет, ariachecked)
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);
})();