doc-fui-ds
Version:
Doc
641 lines (527 loc) • 27.5 kB
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>