UNPKG

doc-fui-ds

Version:

Doc

641 lines (527 loc) 27.5 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> <!-- Bootstrap CSS --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"> <!-- SweetAlert2 --> <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script> <!-- XLSX for Excel Handling --> <script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script> <style> .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-item { background: #f8f9fa; padding: 5px 10px; margin: 5px 0; border-radius: 5px; border-left: 5px solid #28a745; } </style> </head> <body class="bg-light"> <div class="container mt-4"> <div class="row"> <!-- Left Section: Wheel --> <div class="col-md-7 text-center"> <h1 class="mb-3 text-primary">🎡 Random Spin Wheel 🎡</h1> <input type="file" id="fileInput" accept=".xls, .xlsx" class="form-control mb-3"> <textarea id="nameInput" class="form-control mb-3" placeholder="Enter names (one per line)..." rows="4"></textarea> <button id="drawButton" class="btn btn-primary me-2">Spin the Wheel</button> <button id="resetButton" class="btn btn-danger">Reset Game</button> <div class=""> <button id="downloadInputTxtButton" class="btn btn-secondary mt-3">Download Input Data (.txt)</button> <button id="downloadInputExcelButton" class="btn btn-secondary mt-3">Download Input Data (.xlsx)</button> <button id="downloadInputCsvButton" class="btn btn-secondary mt-3">Download Input Data (.csv)</button> </div> <div class=""> <button id="shuffleButton" class="btn btn-primary mt-3">Shuffle Data</button> <button id="sortButton" class="btn btn-secondary mt-3">Sort Data</button> </div> <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="col-md-5"> <h2 class="text-success">🏆 Winners</h2> <div id="winnerList" class="border rounded p-3 bg-white"></div> <button id="downloadTxtButton" class="btn btn-success mt-3">Download Winners (.txt)</button> <button id="downloadExcelButton" class="btn btn-info mt-3">Download Winners (.xlsx)</button> <button id="downloadCsvButton" class="btn btn-warning mt-3">Download Winners (.csv)</button> </div> </div> </div> <!-- Modal Structure --> <div class="modal fade" id="adsModal" tabindex="-1" aria-labelledby="adsModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="adsModalLabel">Sponsored Ad</h5> </div> <div class="modal-body" id="adContent"> <p>Loading Ad...</p> </div> </div> </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 addWinner(name) { let winnerList = document.getElementById("winnerList"); let winnerItem = document.createElement("div"); winnerItem.classList.add("winner-item", "d-flex", "justify-content-between", "align-items-center", "p-2", "border", "rounded", "mb-2", "bg-light"); let winnerText = document.createElement("span"); winnerText.textContent = name; let deleteBtn = document.createElement("button"); deleteBtn.textContent = "❌"; deleteBtn.classList.add("btn", "btn-sm", "btn-danger", "ms-2"); deleteBtn.onclick = function () { deleteWinner(winnerItem, name); }; winnerItem.appendChild(winnerText); winnerItem.appendChild(deleteBtn); winnerList.appendChild(winnerItem); } function deleteWinner(winnerItem, name) { winnerItem.remove(); // Add the winner back to the namesArray so they can be drawn again if (!namesArray.includes(name)) { namesArray.push(name); } } 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]; Swal.fire({ title: "🎉 Winner Selected! 🎉", text: `${winner} is the lucky winner! 🏆`, icon: "success", confirmButtonText: "OK", confirmButtonColor: "#007bff" }); let winnerList = document.getElementById("winnerList"); let winnerItem = document.createElement("div"); winnerItem.classList.add("winner-item", "d-flex", "justify-content-between", "align-items-center", "p-2", "border", "rounded", "mb-2", "bg-light"); let winnerText = document.createElement("span"); winnerText.textContent = `🏆 ${winner}`; let deleteBtn = document.createElement("button"); deleteBtn.textContent = "❌"; deleteBtn.classList.add("btn", "btn-sm", "btn-danger", "ms-2"); deleteBtn.onclick = function () { deleteWinner(winnerItem, winner); }; winnerItem.appendChild(winnerText); winnerItem.appendChild(deleteBtn); winnerList.appendChild(winnerItem); 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)) }; } // ✅ Ads image list const adsArray = [ "<img src='https://via.placeholder.com/300x250?text=Ad+1' alt='Ad 1'>", "<img src='https://via.placeholder.com/300x250?text=Ad+2' alt='Ad 2'>", "<img src='https://via.placeholder.com/300x250?text=Ad+3' alt='Ad 3'>" ]; // ✅ Ads modal after clicking on download button function showAdModal(callback) { let randomAd = adsArray[Math.floor(Math.random() * adsArray.length)]; document.getElementById("adContent").innerHTML = `<span id='countdown'>5</span><br>` + randomAd; let modal = new bootstrap.Modal(document.getElementById("adsModal")); modal.show(); let countdown = 5; const countdownElem = document.getElementById("countdown"); const interval = setInterval(() => { countdown--; countdownElem.textContent = countdown; if (countdown <= 0) clearInterval(interval); }, 1000); setTimeout(() => { modal.hide(); callback(); }, 5000); } // ✅ 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; } showAdModal(() => { 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; } showAdModal(() => { 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"); 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(); }); }); // ✅ Function to download winner list as an .csv (CSV) file document.getElementById("downloadCsvButton").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; } showAdModal(() => { let winners = Array.from(winnerList).map(item => item.textContent).join("\n"); let csvContent = "data:text/csv;charset=utf-8," + "Winner List\n" + winners; let encodedUri = encodeURI(csvContent); let link = document.createElement("a"); link.href = encodedUri; link.download = "WinnerList.csv"; link.click(); }); }); // Function to download input data in all formats function downloadInputData(format) { let inputData = document.getElementById("nameInput").value.trim(); if (!inputData) { Swal.fire({ title: "No Input Data!", text: "Please enter or upload names before downloading.", icon: "warning", confirmButtonText: "OK", confirmButtonColor: "#dc3545" }); return; } showAdModal(() => { if (format === "txt") { let blob = new Blob([inputData], { type: "text/plain" }); let link = document.createElement("a"); link.href = URL.createObjectURL(blob); link.download = "InputData.txt"; link.click(); } else if (format === "xlsx") { let names = inputData.split("\n").map(name => [name]); let worksheet = XLSX.utils.aoa_to_sheet([["Input Data"], ...names]); let workbook = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(workbook, worksheet, "Input Data"); 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 = "InputData.xlsx"; link.click(); } else if (format === "csv") { let csvContent = "data:text/csv;charset=utf-8," + "Input Data\n" + inputData.replace(/\n/g, "\n"); let encodedUri = encodeURI(csvContent); let link = document.createElement("a"); link.href = encodedUri; link.download = "InputData.csv"; link.click(); } }); } document.getElementById("downloadInputTxtButton").addEventListener("click", () => downloadInputData("txt")); document.getElementById("downloadInputExcelButton").addEventListener("click", () => downloadInputData("xlsx")); document.getElementById("downloadInputCsvButton").addEventListener("click", () => downloadInputData("csv")); // Function to shuffle input data document.getElementById("shuffleButton").addEventListener("click", function () { let inputData = document.getElementById("nameInput").value.trim().split("\n"); if (inputData.length === 0 || (inputData.length === 1 && inputData[0] === "")) { Swal.fire({ title: "No Input Data!", text: "Please enter or upload names before shuffling.", icon: "warning", confirmButtonText: "OK", confirmButtonColor: "#dc3545" }); return; } inputData = inputData.sort(() => Math.random() - 0.5); document.getElementById("nameInput").value = inputData.join("\n"); }); // Function to sort input data document.getElementById("sortButton").addEventListener("click", function () { let inputData = document.getElementById("nameInput").value.trim().split("\n"); if (inputData.length === 0 || (inputData.length === 1 && inputData[0] === "")) { Swal.fire({ title: "No Input Data!", text: "Please enter or upload names before sorting.", icon: "warning", confirmButtonText: "OK", confirmButtonColor: "#dc3545" }); return; } inputData = inputData.sort(); document.getElementById("nameInput").value = inputData.join("\n"); }); </script> <!-- Bootstrap JS --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> </body> </html>