// DOM Elements const uploadArea = document.getElementById("uploadArea"); const imageInput = document.getElementById("imageInput"); const imagePreview = document.getElementById("imagePreview"); const submitButton = document.getElementById("submitButton"); const errorMessage = document.getElementById("errorMessage"); const resultSection = document.getElementById("result"); const resultStatus = document.getElementById("resultStatus"); const resultDescription = document.getElementById("resultDescription"); const probabilityValue = document.getElementById("probabilityValue"); const probabilityFill = document.getElementById("probabilityFill"); const likelyInfo = document.getElementById("likelyInfo"); const resultImage = document.getElementById("resultImage"); const actionButtons = document.getElementById("actionButtons"); const navButtons = document.querySelectorAll(".nav-button"); const pages = document.querySelectorAll(".page"); const resourceCategories = document.querySelectorAll(".resource-category"); const optInCheckbox = document.getElementById("optInCheckbox"); const contactInfoInput = document.getElementById("contactInfo"); const contactOptin = document.querySelector(".contact-optin"); // State let selectedImage = null; // Custom dropdown logic const dropdownToggle = document.getElementById("dropdownToggle"); const dropdownMenu = document.getElementById("dropdownMenu"); const dropdownOptions = dropdownMenu ? dropdownMenu.querySelectorAll(".dropdown-option") : []; const selectedModelSpan = document.getElementById("selectedModel"); let selectedModelValue = "CompVis/stable-diffusion-v1-4"; const customDropdown = document.getElementById("modelDropdown"); // Loading animation const loadingContainer = document.createElement("div"); loadingContainer.id = "loadingAnimation"; loadingContainer.style.display = "none"; loadingContainer.style.justifyContent = "center"; loadingContainer.style.alignItems = "center"; loadingContainer.style.flexDirection = "column"; loadingContainer.style.textAlign = "center"; loadingContainer.style.position = "absolute"; loadingContainer.style.top = "0"; loadingContainer.style.left = "0"; loadingContainer.style.width = "100%"; loadingContainer.style.height = "100%"; loadingContainer.style.zIndex = "2"; const loadingImg = document.createElement("img"); loadingImg.alt = "Loading..."; loadingImg.style.width = "64px"; loadingImg.style.height = "64px"; const loadingMsg = document.createElement("div"); loadingMsg.className = "loading-message"; loadingMsg.textContent = "Processing"; loadingContainer.appendChild(loadingImg); loadingContainer.appendChild(loadingMsg); resultSection.appendChild(loadingContainer); let loadingFrame = 1; let loadingInterval = null; const resultContent = resultSection.querySelector(".result-content"); // About overlay logic const aboutOverlay = document.getElementById("aboutOverlay"); const aboutCloseBtn = document.getElementById("aboutCloseBtn"); function showLoading() { resultSection.hidden = false; resultSection.style.display = ""; if (resultContent) resultContent.style.display = "none"; loadingContainer.style.display = "flex"; loadingFrame = 1; updateLoadingFrame(); loadingInterval = setInterval(() => { loadingFrame = (loadingFrame % 16) + 1; updateLoadingFrame(); }, 60); } function hideLoading() { loadingContainer.style.display = "none"; if (resultContent) resultContent.style.display = ""; if (loadingInterval) clearInterval(loadingInterval); } function updateLoadingFrame() { loadingImg.src = `static/assets/Infer_LoadingAnimation/Property 1=Variant${loadingFrame}.svg`; } function hideResultSection() { resultSection.hidden = true; resultSection.style.display = "none"; if (likelyInfo) likelyInfo.hidden = true; if (resultImage) resultImage.hidden = true; if (resultContent) resultContent.style.display = ""; loadingContainer.style.display = "none"; } function showResultSection() { resultSection.hidden = false; resultSection.style.display = ""; } // Event Listeners uploadArea.addEventListener("click", () => imageInput.click()); imageInput.addEventListener("change", handleImageUpload); submitButton.addEventListener("click", handleSubmit); navButtons.forEach((button) => { button.addEventListener("click", () => { const targetPage = button.dataset.page; navigateToPage(targetPage); }); }); // Hide result section initially hideResultSection(); // Add drag and drop support uploadArea.addEventListener("dragover", (e) => { e.preventDefault(); e.stopPropagation(); uploadArea.classList.add("dragover"); }); uploadArea.addEventListener("dragleave", (e) => { e.preventDefault(); e.stopPropagation(); uploadArea.classList.remove("dragover"); }); uploadArea.addEventListener("drop", (e) => { e.preventDefault(); e.stopPropagation(); uploadArea.classList.remove("dragover"); const file = e.dataTransfer.files[0]; if (file && file.type.startsWith("image/")) { handleImageUpload({ target: { files: [file] } }); } }); // Resource category selection resourceCategories.forEach((category) => { category.addEventListener("click", () => { resourceCategories.forEach((c) => c.classList.remove("active")); category.classList.add("active"); }); }); // Functions function handleImageUpload(event) { const file = event.target.files[0]; if (!file) return; if (!file.type.startsWith("image/")) { showError("Please select an image file"); return; } selectedImage = file; errorMessage.textContent = ""; submitButton.disabled = false; // Hide result section when a new image is selected hideResultSection(); // Hide contact opt-in on new upload if (contactOptin) contactOptin.style.display = "none"; const reader = new FileReader(); reader.onload = (e) => { imagePreview.src = e.target.result; imagePreview.hidden = false; document.querySelector(".upload-placeholder").style.display = "none"; }; reader.readAsDataURL(file); } async function handleSubmit() { if (!selectedImage) { showError("Please select an image first"); return; } submitButton.disabled = true; errorMessage.textContent = ""; hideResultSection(); showLoading(); if (contactOptin) contactOptin.style.display = "none"; try { const formData = new FormData(); formData.append("image", selectedImage); formData.append("model", selectedModelValue); // Only send opt-in if visible and checked if ( contactOptin && contactOptin.style.display !== "none" && optInCheckbox && optInCheckbox.checked && contactInfoInput && contactInfoInput.value ) { formData.append("opt_in", "true"); formData.append("contact_info", contactInfoInput.value); } else { formData.append("opt_in", "false"); } const response = await fetch( "https://s-ahal-infer.hf.space/api/check-membership", { method: "POST", body: formData, } ); if (!response.ok) { throw new Error(`Server responded with ${response.status}`); } const data = await response.json(); displayResult(data); } catch (error) { showError(`Error: ${error.message}`); console.error("Error:", error); hideLoading(); } finally { submitButton.disabled = false; } } function displayResult(data) { const probability = data.probability * 100; const isLikely = data.probability > 0.5; resultStatus.textContent = isLikely ? "Likely" : "Unlikely"; const modelName = selectedModelSpan.textContent; const desc = `This image ${ isLikely ? "probably is" : "is probably not" } in the training data for the ${modelName} model.`; resultDescription.innerHTML = desc; probabilityValue.innerHTML = `${probability.toFixed( 1 )}%`; probabilityFill.style.width = "0%"; setTimeout(() => { probabilityFill.style.width = `${probability}%`; }, 30); if (imagePreview && resultImage) { resultImage.src = imagePreview.src; resultImage.hidden = false; } if (isLikely) { likelyInfo.hidden = false; let usersText = ""; if (typeof data.likely_count === "number" && data.likely_count > 1) { usersText = `There are ${ data.likely_count - 1 } other user-tested artworks that were found to likely be included in this model's training data.`; } likelyInfo.querySelector(".likely-users").innerHTML = usersText; // Show contact opt-in below results if (contactOptin) contactOptin.style.display = ""; } else { likelyInfo.hidden = true; if (contactOptin) contactOptin.style.display = "none"; } hideLoading(); showResultSection(); } function showError(message) { errorMessage.textContent = message; } function navigateToPage(pageId) { // Update active page pages.forEach((page) => { page.classList.remove("active"); if (page.id === pageId) { page.classList.add("active"); } }); // Update active nav button navButtons.forEach((button) => { button.classList.toggle("active", button.dataset.page === pageId); }); // Scroll to top when changing pages window.scrollTo(0, 0); } // Initialize navigateToPage("model-select"); function closeDropdown() { dropdownMenu.hidden = true; dropdownToggle.setAttribute("aria-expanded", "false"); if (customDropdown) customDropdown.classList.remove("open"); } function openDropdown() { dropdownMenu.hidden = false; dropdownToggle.setAttribute("aria-expanded", "true"); if (customDropdown) customDropdown.classList.add("open"); // Focus the selected option const selected = dropdownMenu.querySelector(".dropdown-option.selected"); if (selected) selected.focus(); } dropdownToggle.addEventListener("click", (e) => { e.stopPropagation(); if (dropdownMenu.hidden) { openDropdown(); } else { closeDropdown(); } }); dropdownOptions.forEach((option) => { option.setAttribute("tabindex", "0"); option.addEventListener("click", (e) => { dropdownOptions.forEach((opt) => opt.classList.remove("selected")); option.classList.add("selected"); selectedModelSpan.textContent = option.textContent; selectedModelValue = option.getAttribute("data-value"); closeDropdown(); }); option.addEventListener("keydown", (e) => { if (e.key === "Enter" || e.key === " ") { option.click(); } else if (e.key === "ArrowDown") { e.preventDefault(); let next = option.nextElementSibling; if (!next) next = dropdownMenu.firstElementChild; next.focus(); } else if (e.key === "ArrowUp") { e.preventDefault(); let prev = option.previousElementSibling; if (!prev) prev = dropdownMenu.lastElementChild; prev.focus(); } else if (e.key === "Escape") { closeDropdown(); dropdownToggle.focus(); } }); }); document.addEventListener("click", (e) => { if (!dropdownMenu.hidden) { closeDropdown(); } }); dropdownToggle.addEventListener("keydown", (e) => { if (e.key === "ArrowDown" || e.key === "Enter" || e.key === " ") { openDropdown(); e.preventDefault(); } }); document.addEventListener("keydown", (e) => { if (e.key === "Escape") { closeDropdown(); } }); // Ensure About overlay logic runs after DOM is loaded window.addEventListener("DOMContentLoaded", function () { const aboutOverlay = document.getElementById("aboutOverlay"); const aboutCloseBtn = document.getElementById("aboutCloseBtn"); const aboutLink = Array.from(document.querySelectorAll(".nav-link")).find( (link) => link.textContent.trim().toLowerCase() === "about" ); if (aboutLink) { aboutLink.addEventListener("click", function (e) { e.preventDefault(); if (aboutOverlay) aboutOverlay.style.display = "flex"; }); } if (aboutCloseBtn) { aboutCloseBtn.addEventListener("click", function () { if (aboutOverlay) aboutOverlay.style.display = "none"; }); } if (aboutOverlay) { aboutOverlay.addEventListener("click", function (e) { if (e.target === aboutOverlay) { aboutOverlay.style.display = "none"; } }); } }); // Resource card logic for resources page (function () { const resourceData = { "do-not-train": { title: "Do Not Train", html: `What It Is: A simple metadata tag artists can add to their images to declare they don't consent to their work being used for training AI.
How To Use: Add a do-not-train tag to your website's HTML or use platforms that support the tag.
Note: It's not enforceable yet, but signals intent for future protections.
Learn more`, }, nightshade: { title: "Nightshade", html: `What It Is: A tool that poisons your artwork's pixels—imperceptibly to humans, but disruptive to training algorithms.
Why It Works: It corrupts how AI models interpret your work, deterring them from using it.
Try it out`, }, glaze: { title: "Glaze", html: `What It Is: A style cloak that protects your artistic fingerprint.
What It Does: Applies a subtle, AI-visible filter that makes your work harder to mimic.
Best For: Artists with a strong visual signature.
Try it out`, }, copyright: { title: "Copyright Resources", html: `Understand Your Rights:
In many countries, your work is protected the moment it's created—but enforcing that is another story.

Includes:`, }, licensing: { title: "Licensing Tools", html: `Put Terms in Writing:
Use free or paid licenses to explicitly control how your work can be used.

Options to Explore:`, }, }; const categories = document.querySelectorAll(".resource-category"); const info = document.getElementById("resource-info"); if (categories.length && info) { function showResource(key) { categories.forEach((btn) => btn.classList.toggle("active", btn.dataset.resource === key) ); info.innerHTML = `

${resourceData[key].title}

${resourceData[key].html}

`; } categories.forEach((btn) => { btn.addEventListener("click", () => showResource(btn.dataset.resource)); }); // Show default showResource("do-not-train"); } })();