Show sourcecode
The following files exists in this folder. Click to view.
webbserverprogrammering/submissions/projekt-matkort-handler/public/js/
roulette.js
178 lines UTF-8 Windows (CRLF)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
$(document).ready(function () {
let rouletteItems = [];
const colors = [
"#f44336",
"#2196f3",
"#4caf50",
"#ff9800",
"#9c27b0",
"#00bcd4",
"#e91e63",
];
// Map `restaurants` var (comes from index.php script tag) to searchable list
const autocompleteList = restaurants.map((r) => ({
id: r.id,
name: r.name,
address: r.address,
}));
// Toggle Sidebar
$("#toggle-roulette-btn").click(function () {
$("#roulette-sidebar").addClass("active");
$(this).fadeOut(200); // Hide the toggle button when roulette opens
});
$("#close-roulette-btn").click(function () {
$("#roulette-sidebar").removeClass("active");
$("#toggle-roulette-btn").fadeIn(200); // Show the toggle button again when it closes
});
function updateRouletteUI() {
const listEl = $("#roulette-items-list");
listEl.empty();
if (rouletteItems.length === 0) {
$("#roulette-wheel").html(
'<div class="wheel-placeholder">Välj matställen...</div>',
);
$("#roulette-wheel").css("background", "var(--bg-color)"); // Use theme var instead of white/gray #1
$("#spin-btn").prop("disabled", true);
return;
}
$("#spin-btn").prop("disabled", false);
// Populate list
rouletteItems.forEach((item, index) => {
listEl.append(`
<li style="padding: 6px 8px; border-bottom: 1px solid #eee; display: flex; justify-content: space-between; align-items: center;">
<span style="font-size: 0.9rem;">${item.name}</span>
<button class="remove-item" data-id="${item.id}" type="button" style="border: none; background: none; color: var(--secondary); font-weight: bold; cursor: pointer; font-size: 1.2rem; line-height: 1;">×</button>
</li>
`);
});
// Draw Wheel (CSS Conic Gradient)
let gradientStops = [];
const slicePercent = 100 / rouletteItems.length;
rouletteItems.forEach((item, index) => {
const color = colors[index % colors.length];
const startStr = `${slicePercent * index}%`;
const endStr = `${slicePercent * (index + 1)}%`;
gradientStops.push(`${color} ${startStr} ${endStr}`);
});
$("#roulette-wheel").empty();
$("#roulette-wheel").css(
"background",
`conic-gradient(${gradientStops.join(", ")})`,
);
}
function addRestaurant(restObj) {
if (!rouletteItems.find((r) => r.id === restObj.id)) {
rouletteItems.push(restObj);
updateRouletteUI();
}
}
// --- Events ---
// Autocomplete Search
$("#roulette-search").on("keyup input", function () {
const val = $(this).val().toLowerCase();
const resBox = $("#roulette-search-result");
resBox.empty();
if (val.length > 0) {
const matches = autocompleteList
.filter((r) => r.name.toLowerCase().includes(val))
.slice(0, 5);
matches.forEach((m) => {
resBox.append(
`<p data-id="${m.id}" data-name="${m.name}">${m.name}</p>`,
);
});
}
});
$(document).on("click", "#roulette-search-result p", function () {
const id = $(this).data("id");
const name = $(this).data("name");
addRestaurant({ id, name });
$("#roulette-search").val("");
$("#roulette-search-result").empty();
});
// Remove item
$(document).on("click", ".remove-item", function () {
const id = $(this).data("id");
rouletteItems = rouletteItems.filter((r) => r.id !== id);
updateRouletteUI();
});
// Clear all
$("#clear-roulette-btn").click(function () {
rouletteItems = [];
$("#roulette-winner").hide();
updateRouletteUI();
});
// Apply all
$("#apply-all-btn").click(function () {
autocompleteList.forEach((r) => addRestaurant(r));
});
// Add favorites (Ajax)
$("#add-favourites-btn").click(function () {
$.get("api/restaurant_ajax.php?action=get_favorites", function (data) {
if (data && data.length > 0) {
data.forEach((fav) => addRestaurant({ id: fav.id, name: fav.name }));
} else {
alert("Du har inga sparade favoriter ännu!");
}
});
});
// Spin!
let currentRotation = 0;
$("#spin-btn").click(function () {
if (rouletteItems.length === 0) return;
$("#roulette-winner").hide();
$("#spin-btn").prop("disabled", true);
// Calculate random slice
const sliceDegrees = 360 / rouletteItems.length;
const randomItemIndex = Math.floor(Math.random() * rouletteItems.length);
// Target angle (where the pointer hits the middle of the selected slice)
const targetSliceAngle = randomItemIndex * sliceDegrees + sliceDegrees / 2;
// Number of full spins
const spins = 5 * 360;
// Calculate how much we need to rotate to land on the target from the CURRENT rotation
const currentRotMod = currentRotation % 360;
const desiredRotMod = 360 - targetSliceAngle;
let offset = desiredRotMod - currentRotMod;
if (offset < 0) {
offset += 360;
}
currentRotation += spins + offset;
$("#roulette-wheel").css("transform", `rotate(${currentRotation}deg)`);
setTimeout(() => {
const winner = rouletteItems[randomItemIndex];
$("#winner-name").text(winner.name);
$("#roulette-winner").fadeIn();
$("#spin-btn").prop("disabled", false);
}, 3000); // Matches CSS transition duration
});
});