document.addEventListener("DOMContentLoaded", () => { let lastUploadedImage = null; const dropzone = document.getElementById("dropzone"); const featureSelect = document.getElementById("feature-select"); const thinkingText = document.getElementById("thinking-text"); function handleImageUpload(file) { const predictedImagesContainer = document.getElementById("predicted-images"); predictedImagesContainer.innerHTML = ""; const predictionContainer = document.getElementById("prediction-container"); const imageElement = document.createElement("img"); imageElement.src = "static/loading.gif"; imageElement.style.height = "100px"; imageElement.style.width = "100px"; imageElement.style.margin = 'auto'; predictionContainer.appendChild(imageElement); const selectedFeature = featureSelect.value; const formData = new FormData(); thinkingText.innerText = ""; formData.append("uploaded-image", file); formData.append("feature", selectedFeature); lastUploadedImage = file; fetch("/guess", { method: "POST", body: formData, }) .then((response) => response.json()) .then((data) => { console.log(data); displayResults(data); }) .catch((error) => { console.error("Error uploading image:", error); }); const reader = new FileReader(); reader.onloadend = () => { const uploadedImage = new Image(); uploadedImage.src = reader.result; uploadedImage.classList.add("uploaded-image"); uploadedImage.onload = async () => { const imageWidth = uploadedImage.width; const imageHeight = uploadedImage.height; // Create a canvas to draw cropped image const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); canvas.width = 400; canvas.height = 400; let sourceX, sourceY, sourceWidth, sourceHeight; if (imageWidth > imageHeight) { // Image is wider than it is tall sourceHeight = imageHeight; sourceWidth = imageHeight; sourceX = (imageWidth - sourceWidth) / 2; sourceY = 0; } else { // Image is taller than it is wide or square sourceWidth = imageWidth; sourceHeight = imageWidth; sourceY = (imageHeight - sourceHeight) / 2; sourceX = 0; } ctx.drawImage(uploadedImage, sourceX, sourceY, sourceWidth, sourceHeight, 0, 0, 225, 225); const croppedImage = new Image(); croppedImage.src = canvas.toDataURL(); croppedImage.classList.add("uploaded-image"); dropzone.innerHTML = ""; dropzone.appendChild(croppedImage); }; }; if (file) { reader.readAsDataURL(file); } } dropzone.addEventListener("click", () => { const fileInput = document.createElement("input"); fileInput.type = "file"; fileInput.accept = "image/*"; fileInput.onchange = (e) => { const file = e.target.files[0]; handleImageUpload(file); }; fileInput.click(); }); dropzone.addEventListener("dragover", (e) => { e.preventDefault(); dropzone.classList.add("highlight"); }); dropzone.addEventListener("dragleave", () => { dropzone.classList.remove("highlight"); }); dropzone.addEventListener("drop", (e) => { e.preventDefault(); dropzone.classList.remove("highlight"); const file = e.dataTransfer.files[0]; handleImageUpload(file); }); featureSelect.addEventListener("change", () => { if (lastUploadedImage) { handleImageUpload(lastUploadedImage); } }); function displayResults(data) { thinkingText.innerText = ""; const predictionContainer = document.getElementById("prediction-container"); const loadingImage = predictionContainer.querySelector('img[src="static/loading.gif"]'); if (loadingImage) { predictionContainer.removeChild(loadingImage); } const predictedImagesContainer = document.getElementById("predicted-images"); predictedImagesContainer.innerHTML = ""; // Clear previous images for (let i = 0; i < data.images.length; i++) { const imageUrl = data.images[i]; const predictionUrl = data.predictions[i]; const name = data.names[i]; const species = data.species[i]; // Create a container div for each image and its anchor const imageContainer = document.createElement("div"); // Create the anchor element const anchorElement = document.createElement("a"); anchorElement.href = predictionUrl; anchorElement.target = "_blank"; // Open the link in a new tab // Create the caption element const captionElement = document.createElement("div"); captionElement.classList.add("image-caption"); captionElement.textContent = name; // Use the name from the 'names' list as the caption text // Create the caption element const speciesElement = document.createElement("div"); speciesElement.classList.add("image-species"); speciesElement.textContent = species; // Use the name from the 'names' list as the caption text // Create the image element const imageElement = document.createElement("img"); // Add cache-busting parameter to the image URL const cacheBustUrl = imageUrl + `?cache=${Date.now()}`; // Set the lazy loading attribute imageElement.loading = "lazy"; // Set the data-src attribute with the cache-busted URL imageElement.src = cacheBustUrl; const tooltip = document.createElement("div"); tooltip.classList.add("image-tooltip"); tooltip.textContent = species; // Use the name from the 'names' list as the tooltip text // Append the image to the anchor and the anchor to the container anchorElement.appendChild(imageElement); anchorElement.appendChild(captionElement); imageContainer.appendChild(tooltip); imageContainer.appendChild(anchorElement); captionElement.style.opacity = "0"; captionElement.style.opacity = "1"; // Append the container to the predictedImagesContainer predictedImagesContainer.appendChild(imageContainer); // Add the tooltip element to the document body document.body.appendChild(tooltip); // Add event listeners to handle tooltip visibility imageContainer.addEventListener("mouseover", () => { tooltip.style.opacity = "1"; }); imageContainer.addEventListener("mouseout", () => { tooltip.style.opacity = "0"; }); // Position the tooltip dynamically based on cursor movement imageContainer.addEventListener("mousemove", (event) => { tooltip.style.left = event.pageX + "px"; tooltip.style.top = event.pageY + "px"; }); } } });