UNPKG

doc-fui-ds

Version:

Doc

534 lines (461 loc) 21.2 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Random Spin Wheel</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script> <!-- Include SweetAlert2 from CDN --> <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script> <style> body { font-family: Arial, sans-serif; background: #f4f4f4; margin: 0; padding: 0; display: flex; justify-content: center; align-items: center; height: 100vh; } .container { display: flex; max-width: 800px; background: white; box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.1); border-radius: 10px; padding: 20px; } .left-section { width: 60%; text-align: center; } .right-section { width: 40%; padding-left: 20px; text-align: left; border-left: 2px solid #ddd; } h1 { font-size: 24px; color: #333; } textarea { width: 100%; height: 100px; border: 1px solid #ccc; padding: 10px; font-size: 16px; border-radius: 5px; direction: auto; } button { margin-top: 10px; padding: 10px 20px; font-size: 18px; border: none; background: #007bff; color: white; cursor: pointer; border-radius: 5px; } button:hover { background: #0056b3; } .wheel-container { position: relative; width: 300px; height: 300px; margin: 20px auto; } #wheel { width: 100%; height: 100%; border-radius: 50%; transition: transform 4s cubic-bezier(0.17, 0.67, 0.83, 0.67); } .arrow { position: absolute; top: -10px; left: 50%; transform: translateX(-50%); width: 0; height: 0; border-left: 15px solid transparent; border-right: 15px solid transparent; border-bottom: 30px solid red; } .winner-list { font-size: 18px; font-weight: bold; color: #28a745; } .winner-item { background: #f8f9fa; padding: 5px 10px; margin: 5px 0; border-radius: 5px; border-left: 5px solid #28a745; } </style> </head> <body> <div class="container"> <!-- Left Section: Wheel --> <div class="left-section"> <h1>🎡 Random User Draw Wheel 🎡</h1> <input type="file" id="fileInput" accept=".xls, .xlsx"> <br><br> <textarea id="nameInput" placeholder="Enter names (one per line)..."></textarea> <button id="drawButton">Spin the Wheel</button> <button id="resetButton" style="margin-top: 10px; padding: 10px 20px; font-size: 18px; border: none; background: #dc3545; color: white; cursor: pointer; border-radius: 5px;">Reset Game</button> <div class="wheel-container"> <div class="arrow"></div> <svg id="wheel" width="300" height="300" viewBox="0 0 300 300"></svg> </div> </div> <!-- Right Section: Winner List --> <div class="right-section"> <h2>🏆 Winners</h2> <div id="winnerList" class="winner-list"></div> <!-- Download Winner List Buttons --> <button id="downloadTxtButton" style="margin-top: 10px; padding: 10px 20px; font-size: 16px; background: #28a745; color: white; border: none; cursor: pointer; border-radius: 5px;">Download Winner List (.txt)</button> <button id="downloadExcelButton" style="margin-top: 10px; padding: 10px 20px; font-size: 16px; background: #007bff; color: white; border: none; cursor: pointer; border-radius: 5px;">Download Winner List (.xlsx)</button> </div> </div> <script> let namesArray = []; let rotation = 0; document.getElementById('fileInput').addEventListener('change', function (event) { const file = event.target.files[0]; if (!file) return; const fileType = file.name.split('.').pop().toLowerCase(); const reader = new FileReader(); if (fileType === 'txt') { // Handle .txt file reader.onload = function (e) { document.getElementById('nameInput').value = e.target.result; }; reader.readAsText(file); } else if (fileType === 'xls' || fileType === 'xlsx') { // Handle Excel file reader.onload = function (e) { const data = new Uint8Array(e.target.result); const workbook = XLSX.read(data, { type: 'array' }); // Extract data from the first sheet and first column const sheet = workbook.Sheets[workbook.SheetNames[0]]; const rows = XLSX.utils.sheet_to_json(sheet, { header: 1 }); // Extract names from the first column const names = rows.map(row => row[0]).filter(name => name); // Remove empty values // Insert names into textarea document.getElementById('nameInput').value = names.join('\n'); }; reader.readAsArrayBuffer(file); } else { // alert('Unsupported file type. Please upload a .txt, .xls, or .xlsx file.'); // ✅ Show SweetAlert2 warning when no names are available Swal.fire({ title: "Unsupported file type.😕", text: "lease upload a .txt, .xls, or .xlsx file.", icon: "warning", confirmButtonText: "OK", confirmButtonColor: "#007bff" }); return; } }); document.getElementById("drawButton").addEventListener("click", function () { if (namesArray.length === 0) { let namesText = document.getElementById("nameInput").value; namesArray = namesText.split("\n").map(name => name.trim()).filter(name => name !== ""); } if (namesArray.length === 0) { // ✅ Show SweetAlert2 warning when no names are available Swal.fire({ title: "Oops! No Names Found 😕", text: "Please enter names before spinning the wheel.", icon: "warning", confirmButtonText: "OK", confirmButtonColor: "#007bff" }); return; } generateWheel(); spinWheel(); }); // ✅ Reset Button Click Event document.getElementById("resetButton").addEventListener("click", function () { Swal.fire({ title: "Are you sure?", text: "This will clear the entire wheel, names, and winners.", icon: "warning", showCancelButton: true, confirmButtonColor: "#dc3545", cancelButtonColor: "#6c757d", confirmButtonText: "Yes, Reset" }).then((result) => { if (result.isConfirmed) { // ✅ Clear the text area & winners list document.getElementById("nameInput").value = ""; document.getElementById("winnerList").innerHTML = ""; // ✅ Reset the names array namesArray = []; // ✅ Clear the entire spin wheel let wheel = document.getElementById("wheel"); wheel.innerHTML = ""; // Clears all wheel segments // ✅ Reset the rotation to default wheel.style.transform = "rotate(0deg)"; rotation = 0; // ✅ Reset file input so users can re-upload Excel after reset let fileInput = document.getElementById("fileInput"); fileInput.value = ""; // Clears selected file Swal.fire({ title: "Game Reset!", text: "The spin wheel, names, and winners have been cleared. You can now re-import Excel data.", icon: "success", confirmButtonText: "OK", confirmButtonColor: "#007bff" }); } }); }); function generateWheel() { let wheel = document.getElementById("wheel"); wheel.innerHTML = ""; // Clear previous segments let totalSegments = namesArray.length; let sliceAngle = 360 / totalSegments; for (let i = 0; i < totalSegments; i++) { let angle = i * sliceAngle; let color = `hsl(${(i * 360) / totalSegments}, 80%, 60%)`; let path = document.createElementNS("http://www.w3.org/2000/svg", "path"); path.setAttribute("d", describeArc(150, 150, 150, angle, angle + sliceAngle)); path.setAttribute("fill", color); path.setAttribute("stroke", "#fff"); path.setAttribute("stroke-width", "2"); wheel.appendChild(path); // Text positioning let text = document.createElementNS("http://www.w3.org/2000/svg", "text"); let textAngle = angle + sliceAngle / 2; // Center of the slice let textX = 150 + Math.cos((textAngle - 90) * Math.PI / 180) * 100; // Adjusted for diagonal alignment let textY = 150 + Math.sin((textAngle - 90) * Math.PI / 180) * 100; text.setAttribute("x", textX); text.setAttribute("y", textY); text.setAttribute("transform", `rotate(${textAngle + 90}, ${textX}, ${textY})`); // Rotates text diagonally text.setAttribute("text-anchor", "middle"); text.setAttribute("font-size", "14px"); text.setAttribute("fill", "#fff"); text.setAttribute("dominant-baseline", "middle"); // Center align text vertically text.textContent = namesArray[i]; wheel.appendChild(text); } } function spinWheel() { let totalSegments = namesArray.length; let sliceAngle = 360 / totalSegments; let randomIndex = Math.floor(Math.random() * totalSegments); let finalRotation = 360 * 5 + (randomIndex * sliceAngle) + (sliceAngle / 2); let wheel = document.getElementById("wheel"); rotation += finalRotation; wheel.style.transform = `rotate(${rotation}deg)`; setTimeout(() => { let actualRotation = rotation % 360; let winningIndex = Math.floor((360 - actualRotation) / sliceAngle) % totalSegments; let winner = namesArray[winningIndex]; // ✅ Show SweetAlert2 pop-up with the winner Swal.fire({ title: "🎉 Winner Selected! 🎉", text: `${winner} is the lucky winner! 🏆`, icon: "success", confirmButtonText: "OK", confirmButtonColor: "#007bff" }); // ✅ Display the winner in the list let winnerList = document.getElementById("winnerList"); let winnerItem = document.createElement("div"); winnerItem.classList.add("winner-item"); winnerItem.textContent = `🏆 ${winner}`; winnerList.appendChild(winnerItem); // ✅ Remove the winner from the names list namesArray.splice(winningIndex, 1); if (namesArray.length === 0) { setTimeout(() => { Swal.fire({ title: "Game Over! 🎊", text: "All winners have been selected! Resetting the game.", icon: "info", confirmButtonText: "Restart" }).then(() => { document.getElementById("nameInput").value = ""; document.getElementById("winnerList").innerHTML = ""; }); }, 2000); } }, 5000); } function describeArc(x, y, radius, startAngle, endAngle) { let start = polarToCartesian(x, y, radius, endAngle); let end = polarToCartesian(x, y, radius, startAngle); let largeArcFlag = endAngle - startAngle <= 180 ? "0" : "1"; return [ "M", x, y, "L", start.x, start.y, "A", radius, radius, 0, largeArcFlag, 0, end.x, end.y, "Z" ].join(" "); } function polarToCartesian(centerX, centerY, radius, angleInDegrees) { let angleInRadians = (angleInDegrees - 90) * Math.PI / 180; return { x: centerX + (radius * Math.cos(angleInRadians)), y: centerY + (radius * Math.sin(angleInRadians)) }; } // ✅ Function to download winner list as a .txt file document.getElementById("downloadTxtButton").addEventListener("click", function () { let winnerList = document.getElementById("winnerList").children; if (winnerList.length === 0) { Swal.fire({ title: "No Winners Yet!", text: "There are no winners to download.", icon: "warning", confirmButtonText: "OK", confirmButtonColor: "#dc3545" }); return; } let winners = Array.from(winnerList).map(item => item.textContent).join("\n"); let blob = new Blob([winners], { type: "text/plain" }); let link = document.createElement("a"); link.href = URL.createObjectURL(blob); link.download = "WinnerList.txt"; link.click(); }); // ✅ Function to download winner list as an .xlsx (Excel) file document.getElementById("downloadExcelButton").addEventListener("click", function () { let winnerList = document.getElementById("winnerList").children; if (winnerList.length === 0) { Swal.fire({ title: "No Winners Yet!", text: "There are no winners to download.", icon: "warning", confirmButtonText: "OK", confirmButtonColor: "#dc3545" }); return; } let winners = Array.from(winnerList).map(item => [item.textContent]); let worksheet = XLSX.utils.aoa_to_sheet([["Winner List"], ...winners]); let workbook = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(workbook, worksheet, "Winners"); // ✅ Create and trigger download let excelBuffer = XLSX.write(workbook, { bookType: "xlsx", type: "array" }); let blob = new Blob([excelBuffer], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" }); let link = document.createElement("a"); link.href = URL.createObjectURL(blob); link.download = "WinnerList.xlsx"; link.click(); }); // ✅ Prevent Page Reload with Confirmation window.addEventListener("beforeunload", function (event) { event.preventDefault(); Swal.fire({ title: "Are you sure?", text: "Refreshing will reset the game and clear all data.", icon: "warning", showCancelButton: true, confirmButtonColor: "#dc3545", cancelButtonColor: "#6c757d", confirmButtonText: "Yes, Refresh" }).then((result) => { if (result.isConfirmed) { window.removeEventListener("beforeunload", () => {}); // Allow reload if confirmed location.reload(); } }); return ""; // Blocks default browser refresh alert }); // ✅ Block Page Refresh (F5, Ctrl+R, Cmd+R) document.addEventListener("keydown", function (event) { if (event.key === "F5" || (event.ctrlKey && event.key === "r") || (event.metaKey && event.key === "r")) { event.preventDefault(); Swal.fire({ title: "Action Blocked 🚫", text: "Page refresh is disabled!", icon: "error", confirmButtonText: "OK", confirmButtonColor: "#dc3545" }); } }); // ✅ Block Right Click Context Menu document.addEventListener("contextmenu", function (event) { event.preventDefault(); Swal.fire({ title: "Action Blocked 🚫", text: "Right Click is disabled!", icon: "error", confirmButtonText: "OK", confirmButtonColor: "#dc3545" }); }); // ✅ Block Inspect Element (F12, Ctrl+Shift+I, Cmd+Opt+I) document.addEventListener("keydown", function (event) { if (event.key === "F12" || (event.ctrlKey && event.shiftKey && event.key === "I") || (event.metaKey && event.altKey && event.key === "I")) { event.preventDefault(); Swal.fire({ title: "Action Blocked 🚫", text: "Inspect Element is disabled!", icon: "error", confirmButtonText: "OK", confirmButtonColor: "#dc3545" }); } }); // ✅ Block View Source (Ctrl+U, Cmd+U) document.addEventListener("keydown", function (event) { if ((event.ctrlKey && event.key === "u") || (event.metaKey && event.key === "u")) { event.preventDefault(); Swal.fire({ title: "Action Blocked 🚫", text: "View Source is disabled!", icon: "error", confirmButtonText: "OK", confirmButtonColor: "#dc3545" }); } }); // ✅ Detect Developer Tools (DevTools) and Block Access let devtoolsOpen = false; setInterval(function () { let widthThreshold = window.outerWidth - window.innerWidth > 160; let heightThreshold = window.outerHeight - window.innerHeight > 160; if (widthThreshold || heightThreshold) { if (!devtoolsOpen) { devtoolsOpen = true; document.body.innerHTML = ""; // Clear the page content alert("Developer Tools Detected! Access Denied. 🔒"); } } else { devtoolsOpen = false; } }, 1000); // ✅ Block Back/Forward Button Navigation history.pushState(null, null, location.href); window.addEventListener("popstate", function () { history.pushState(null, null, location.href); Swal.fire({ title: "Navigation Blocked 🚫", text: "Back and forward navigation is disabled!", icon: "error", confirmButtonText: "OK", confirmButtonColor: "#dc3545" }); }); </script> </body> </html>