diff --git a/app.css b/app.css
index 37d54e6..b1ed244 100644
--- a/app.css
+++ b/app.css
@@ -1,14 +1,14 @@
body {
background-color: #121212;
- color: #FAF9F6;
+ color: #faf9f6;
transition-duration: 3s;
}
-button{
+button {
cursor: pointer;
}
-canvas{
+canvas {
height: 50rem;
cursor: pointer;
}
@@ -45,25 +45,24 @@ ul {
text-align: center;
}
-
.add-item-button {
height: 2rem;
width: 15.5rem;
margin-top: 0.5rem;
- background-color: #6495ED;
+ background-color: #6495ed;
border: 0.05rem solid black;
- box-shadow: 0 0.7rem 0 -0.1rem #6082B6, 0 0.75rem 0 -0.05rem black;
+ box-shadow: 0 0.7rem 0 -0.1rem #6082b6, 0 0.75rem 0 -0.05rem black;
border-radius: 0.5rem;
}
.add-item-button:hover {
transform: translate(0, 0.25rem);
- box-shadow: 0 0.5rem 0 -0.1rem #6082B6, 0 0.55rem 0 -0.05rem black;
+ box-shadow: 0 0.5rem 0 -0.1rem #6082b6, 0 0.55rem 0 -0.05rem black;
}
.add-item-button:active {
transform: translate(0, 0.5rem);
- box-shadow: 0 0.1rem 0 -0.1rem #6082B6, 0 0.15rem 0 -0.05rem black;
+ box-shadow: 0 0.1rem 0 -0.1rem #6082b6, 0 0.15rem 0 -0.05rem black;
}
.counter {
@@ -87,7 +86,7 @@ ul {
}
.menu-item-list {
- text-align: center;
+ text-align: center;
}
.moon-sun {
@@ -98,20 +97,20 @@ ul {
.remove-all-items-button {
width: 5.4rem;
height: 2rem;
- background-color: #6495ED;
+ background-color: #6495ed;
border: 0.05rem solid black;
- box-shadow: 0 0.7rem 0 -0.1rem #6082B6, 0 0.75rem 0 -0.05rem black;
+ box-shadow: 0 0.7rem 0 -0.1rem #6082b6, 0 0.75rem 0 -0.05rem black;
border-radius: 0.5rem;
}
.remove-all-items-button:hover {
transform: translate(0, 0.25rem);
- box-shadow: 0 0.5rem 0 -0.1rem #6082B6, 0 0.55rem 0 -0.05rem black;
+ box-shadow: 0 0.5rem 0 -0.1rem #6082b6, 0 0.55rem 0 -0.05rem black;
}
.remove-all-items-button:active {
transform: translate(0, 0.5rem);
- box-shadow: 0 0.1rem 0 -0.1rem #6082B6, 0 0.15rem 0 -0.05rem black;
+ box-shadow: 0 0.1rem 0 -0.1rem #6082b6, 0 0.15rem 0 -0.05rem black;
}
.roulette-wheel {
@@ -129,19 +128,19 @@ ul {
}
.winner {
- font-size: 32;
+ font-size: 32px;
margin-bottom: 1rem;
height: 28px;
}
@media screen and (max-width: 940px) {
- canvas{
+ canvas {
margin-top: 5rem;
height: 20rem;
margin: auto;
}
- .menu{
+ .menu {
width: 23.5rem;
}
@@ -157,4 +156,4 @@ ul {
footer {
position: relative;
}
-}
\ No newline at end of file
+}
diff --git a/index.html b/index.html
index 69c26bd..eef467a 100644
--- a/index.html
+++ b/index.html
@@ -10,7 +10,7 @@
-
+
diff --git a/src/app.ts b/src/app.ts
index c9ad9a3..c199ceb 100644
--- a/src/app.ts
+++ b/src/app.ts
@@ -22,15 +22,20 @@ const lightDarkModeEl = document.getElementsByClassName(
"light-dark-mode"
)[0]! as HTMLDivElement;
const canvasEl = document.querySelector("canvas")! as HTMLCanvasElement;
-const ctx = canvasEl.getContext("2d")!;
const bodyEl = document.querySelector("body")! as HTMLBodyElement;
const modeEl = lightDarkModeEl.querySelector("img")! as HTMLImageElement;
-const canvasWrapper = document.getElementsByClassName(
- "roulette-wheel"
-)[0]! as HTMLDivElement;
const winnerEl = document.getElementsByClassName(
"winner"
)[0]! as HTMLDivElement;
+const footerEl = document.querySelector("footer")!;
+const authorsEl = document.getElementsByClassName(
+ "icons-authors"
+)[0]! as HTMLDivElement;
+const canvasWrapper = document.getElementsByClassName(
+ "roulette-wheel"
+)[0]! as HTMLDivElement;
+
+const ctx = canvasEl.getContext("2d")!;
canvasEl.width = canvasWrapper.offsetWidth;
canvasEl.height = canvasWrapper.offsetHeight;
@@ -47,12 +52,12 @@ const itemsList = new ItemList(MAXIMUM_SIZE);
const items: MenuItem[] = [];
let rotate_by = 50;
+let totalTime = 0;
configure();
function configure() {
counterEl.textContent = `0/${MAXIMUM_SIZE}`;
- winnerEl.style.fontSize = "32px";
LightDarkMode.currentMode = "dark";
IdPool.initializeIdsPool(MAXIMUM_SIZE);
@@ -63,37 +68,47 @@ function configure() {
drawRouletteWheel(0);
canvasEl.addEventListener("click", startRoulette);
+ footerEl.addEventListener("click", () => {
+ authorsEl.hidden = !authorsEl.hidden;
+ });
}
+
function addRemoveItem() {
addButtonEl.addEventListener("click", () => {
- const name = inputEl.value;
- if (name) {
- const id = IdPool.getAnId();
- if (id) {
- const color = avaliableRGBs[id % avaliableRGBs.length];
- const item = new Item(id, name, color);
- const menuItem = new MenuItem(id, name, color);
+ if (!animationId) {
+ clearWinner();
+ const name = inputEl.value;
+ if (name) {
+ const id = IdPool.getAnId();
+ if (id) {
+ const color = avaliableRGBs[id % avaliableRGBs.length];
+ const item = new Item(id, name, color);
+ const menuItem = new MenuItem(id, name, color);
- menuItem.deleteItem.el.addEventListener("click", () => {
- menuItem.el.remove();
- items.splice(items.indexOf(menuItem), 1);
- itemsList.remove(item);
- IdPool.addId(item.id);
+ menuItem.deleteItem.el.addEventListener("click", () => {
+ if (!animationId) {
+ clearWinner();
+ menuItem.el.remove();
+ items.splice(items.indexOf(menuItem), 1);
+ itemsList.remove(item);
+ IdPool.addId(item.id);
+ updateCounter();
+ drawRouletteWheel(0);
+ }
+ });
+
+ registerChangeColorByClick(item, menuItem);
+
+ itemsList.add(item);
+ items.push(menuItem);
+ itemListEl.appendChild(menuItem.el);
updateCounter();
+ guessItemIndex = Math.floor(Math.random() * items.length);
+ segmentAngle = 360 / items.length;
+ maxAngle = 360 * ROTATIONS + segmentAngle * guessItemIndex;
drawRouletteWheel(0);
- });
-
- registerChangeColorByClick(item, menuItem);
-
- itemsList.add(item);
- items.push(menuItem);
- itemListEl.appendChild(menuItem.el);
- updateCounter();
- guessItemIndex = Math.floor(Math.random() * items.length);
- segmentAngle = 360 / items.length;
- maxAngle = 360 * ROTATIONS + segmentAngle * guessItemIndex;
- drawRouletteWheel(0);
+ }
}
}
});
@@ -108,32 +123,59 @@ function addItemByEnter() {
function registerChangeColorByClick(item: Item, menuItem: MenuItem) {
menuItem.el.addEventListener("click", () => {
- const actualColorIndex = avaliableRGBs.indexOf(
- menuItem.el.style.backgroundColor
- );
- if (actualColorIndex !== -1) {
- const color =
- avaliableRGBs[(actualColorIndex + 1) % avaliableRGBs.length];
- menuItem.el.style.backgroundColor = color;
- item.color = color;
- if (!animationId) drawRouletteWheel(0);
+ if (!animationId) {
+ const actualColorIndex = avaliableRGBs.indexOf(
+ menuItem.el.style.backgroundColor
+ );
+ if (actualColorIndex !== -1) {
+ const color =
+ avaliableRGBs[(actualColorIndex + 1) % avaliableRGBs.length];
+ menuItem.el.style.backgroundColor = color;
+ item.color = color;
+ drawRouletteWheel(0);
+ }
}
});
}
function removeAllItems() {
removeAllItemsButtonEl.addEventListener("click", () => {
- if (items.length > 0) {
- items.forEach((menuItem) => menuItem.el.remove());
- items.length = 0;
- itemsList.clear();
- IdPool.initializeIdsPool(MAXIMUM_SIZE);
- updateCounter();
- drawRouletteWheel(0);
+ if (!animationId) {
+ clearWinner();
+ if (items.length > 0) {
+ items.forEach((menuItem) => menuItem.el.remove());
+ items.length = 0;
+ itemsList.clear();
+ IdPool.initializeIdsPool(MAXIMUM_SIZE);
+ updateCounter();
+ drawRouletteWheel(0);
+ }
}
});
}
+
+function lightDarkMode() {
+ lightDarkModeEl.addEventListener("click", () => {
+ modeEl.animate([{ transform: "rotate(360deg)" }], {
+ duration: 500,
+ });
+
+ if (LightDarkMode.currentMode == "dark") {
+ modeEl.src = "static/sun.png";
+ bodyEl.style.backgroundColor = "#FAF9F6";
+ bodyEl.style.color = "black";
+ LightDarkMode.currentMode = "light";
+ } else {
+ modeEl.src = "static/moon.png";
+ bodyEl.style.backgroundColor = "#121212";
+ bodyEl.style.color = "white";
+ LightDarkMode.currentMode = "dark";
+ }
+ });
+}
+
+
function updateCounter() {
counterEl.textContent = `${itemsList.items.length}/${MAXIMUM_SIZE}`;
animateCounter();
@@ -141,11 +183,7 @@ function updateCounter() {
function animateCounter() {
counterEl.animate(
- [
- { transform: "scale(1.5)" },
- { transform: "scale(1.00)" },
- { transform: "" },
- ],
+ [{ transform: "scale(1.5)" }, { transform: "scale(1.00)" }],
{
duration: 500,
}
@@ -162,25 +200,6 @@ function animateWinner() {
);
}
-function lightDarkMode() {
- lightDarkModeEl.addEventListener("click", () => {
- modeEl.animate([{ transform: "rotate(360deg)" }], {
- duration: 500,
- });
-
- if (LightDarkMode.currentMode == "dark") {
- modeEl.src = "static/sun.png";
- bodyEl.style.backgroundColor = "#FAF9F6";
- bodyEl.style.color = "black";
- } else {
- modeEl.src = "static/moon.png";
- bodyEl.style.backgroundColor = "#121212";
- bodyEl.style.color = "white";
- }
- LightDarkMode.changeMode();
- });
-}
-
function drawRouletteWheel(angle: number) {
const segmentWidth = 360 / items.length;
let startAngle = angle;
@@ -242,24 +261,14 @@ let animationId: number | null;
let winner: string;
let endTime: number;
-function easeOut(
- time: number,
- beginningVal: number,
- toChange: number,
- duration: number
-) {
- return time == duration
- ? beginningVal + toChange
- : toChange * (-Math.pow(2, (-10 * time) / duration) + 1) + beginningVal;
-}
-
function startRoulette() {
if (!animationId) {
- if (winner) {
- winner = "";
- winnerEl.textContent = "";
+ const winnerCleared = clearWinner();
+ if (winnerCleared) {
drawRouletteWheel(0);
} else {
+ addButtonEl.style.background = "#C0C0C0";
+ removeAllItemsButtonEl.style.background = "#C0C0C0";
guessItemIndex = Math.floor(Math.random() * items.length);
winner = itemsList.items[guessItemIndex].name;
segmentAngle = 360 / items.length;
@@ -274,8 +283,15 @@ function startRoulette() {
}
}
+function clearWinner() {
+ if (winner) {
+ winner = "";
+ winnerEl.textContent = "";
+ return true;
+ }
+ return false;
+}
-let totalTime = 0;
function beginAnimateRoulette() {
const angle = easeOut(totalTime, 0, maxAngle, endTime);
if (totalTime < endTime || maxAngle - angle > 0.1) {
@@ -288,12 +304,20 @@ function beginAnimateRoulette() {
window.cancelAnimationFrame(animationId!);
animationId = null;
winnerEl.textContent = `Winner: ${winner}`;
+ addButtonEl.style.background = "#6082B6";
+ removeAllItemsButtonEl.style.background = "#6082B6";
animateWinner();
}
}
-const footerEl = document.querySelector('footer')!;
-const authorsEl = document.getElementsByClassName('icons-authors')[0]! as HTMLDivElement;
-footerEl.addEventListener('click', () => {
- authorsEl.hidden = !authorsEl.hidden;
-});
+
+function easeOut(
+ time: number,
+ beginningVal: number,
+ toChange: number,
+ duration: number
+) {
+ return time == duration
+ ? beginningVal + toChange
+ : toChange * (-Math.pow(2, (-10 * time) / duration) + 1) + beginningVal;
+}
diff --git a/src/components/base-component.ts b/src/components/base-component.ts
index 921615f..a7e4ef3 100644
--- a/src/components/base-component.ts
+++ b/src/components/base-component.ts
@@ -1,15 +1,15 @@
export abstract class Component {
- el: T;
+ el: T;
- constructor(el: T){
- this.el = el;
- }
+ constructor(el: T) {
+ this.el = el;
+ }
- removeChildren() {
- if(this.el.childNodes.length > 0){
- while(this.el.firstChild){
- this.el.removeChild(this.el.firstChild);
- }
- }
+ removeChildren() {
+ if (this.el.childNodes.length > 0) {
+ while (this.el.firstChild) {
+ this.el.removeChild(this.el.firstChild);
+ }
}
-}
\ No newline at end of file
+ }
+}
diff --git a/src/components/item-removal.ts b/src/components/item-removal.ts
index 5033091..4ab327b 100644
--- a/src/components/item-removal.ts
+++ b/src/components/item-removal.ts
@@ -1,13 +1,12 @@
import { Component } from "./base-component";
-export class ItemRemoval extends Component{
-
- constructor(id: number){
- const el = document.createElement('img');
- el.src = 'static/close.png';
- el.alt = 'delete';
- el.className = `item-delete`;
- el.id = `${id}-delete`
- super(el);
- }
-}
\ No newline at end of file
+export class ItemRemoval extends Component {
+ constructor(id: number) {
+ const el = document.createElement("img");
+ el.src = "static/close.png";
+ el.alt = "delete";
+ el.className = `item-delete`;
+ el.id = `${id}-delete`;
+ super(el);
+ }
+}
diff --git a/src/components/menu-item.ts b/src/components/menu-item.ts
index c32d969..dd7aec3 100644
--- a/src/components/menu-item.ts
+++ b/src/components/menu-item.ts
@@ -2,28 +2,27 @@ import { Component } from "./base-component";
import { ItemRemoval } from "./item-removal";
export class MenuItem extends Component {
+ deleteItem: ItemRemoval;
- deleteItem: ItemRemoval;
+ constructor(id: number, name: string, color: string) {
+ const deleteItem = new ItemRemoval(id);
+ const el = document.createElement("li");
+ el.className = "menu-item";
+ el.id = `${id}-item`;
+ el.textContent = name;
+ el.style.backgroundColor = color;
+ el.appendChild(deleteItem.el);
+ super(el);
+ this.deleteItem = deleteItem;
+ this.appearAnimation();
+ }
- constructor(id: number, name: string, color: string){
- const deleteItem = new ItemRemoval(id);
- const el = document.createElement('li');
- el.className = 'menu-item';
- el.id = `${id}-item`;
- el.textContent = name;
- el.style.backgroundColor = color;
- el.appendChild(deleteItem.el);
- super(el);
- this.deleteItem = deleteItem;
- this.appearAnimation();
- }
-
- appearAnimation(){
- this.el.animate(
- [{ transform: "scale(1.25)" }, { transform: "scale(1.00)" }],
- {
- duration: 500,
- }
- );
- }
-}
\ No newline at end of file
+ appearAnimation() {
+ this.el.animate(
+ [{ transform: "scale(1.25)" }, { transform: "scale(1.00)" }],
+ {
+ duration: 500,
+ }
+ );
+ }
+}
diff --git a/src/model/item-list.ts b/src/model/item-list.ts
index 2e21338..e384287 100644
--- a/src/model/item-list.ts
+++ b/src/model/item-list.ts
@@ -2,31 +2,30 @@ import { Item } from "./item";
import { List } from "./list";
export class ItemList implements List- {
- items: Item[];
- maximumSize: number;
+ items: Item[];
+ maximumSize: number;
- constructor(maxSize: number){
- this.items = [];
- this.maximumSize = maxSize;
- }
+ constructor(maxSize: number) {
+ this.items = [];
+ this.maximumSize = maxSize;
+ }
- add(item: Item){
- if(this.items.length < this.maximumSize)
- this.items.push(item);
- }
+ add(item: Item) {
+ if (this.items.length < this.maximumSize) this.items.push(item);
+ }
- removeById(id: number){
- const toRemove = this.items.find(e => e.id === id);
- if(toRemove){
- this.remove(toRemove);
- }
+ removeById(id: number) {
+ const toRemove = this.items.find((e) => e.id === id);
+ if (toRemove) {
+ this.remove(toRemove);
}
+ }
- remove(item: Item){
- this.items.splice(this.items.indexOf(item), 1);
- }
+ remove(item: Item) {
+ this.items.splice(this.items.indexOf(item), 1);
+ }
- clear(){
- this.items = [];
- }
-}
\ No newline at end of file
+ clear() {
+ this.items = [];
+ }
+}
diff --git a/src/model/list.ts b/src/model/list.ts
index c74bdc9..706ea9a 100644
--- a/src/model/list.ts
+++ b/src/model/list.ts
@@ -1,5 +1,5 @@
export interface List {
- items: T[];
-
- add(item: T): void;
-}
\ No newline at end of file
+ items: T[];
+
+ add(item: T): void;
+}
diff --git a/src/utils/item-id-pool.ts b/src/utils/item-id-pool.ts
index 7de4747..04815a5 100644
--- a/src/utils/item-id-pool.ts
+++ b/src/utils/item-id-pool.ts
@@ -16,7 +16,7 @@ export abstract class IdPool {
return id;
}
- static addId(id: number){
+ static addId(id: number) {
this.avaliableIds.push(id);
}
}
diff --git a/src/utils/light-dark-mode.ts b/src/utils/light-dark-mode.ts
index 5fe5db2..eda73bb 100644
--- a/src/utils/light-dark-mode.ts
+++ b/src/utils/light-dark-mode.ts
@@ -1,13 +1,5 @@
-type mode = 'dark' | 'light';
+type mode = "dark" | "light";
-export abstract class LightDarkMode{
- static currentMode: mode;
-
- static changeMode(){
- if(this.currentMode == 'light'){
- this.currentMode = 'dark';
- }else{
- this.currentMode = 'light';
- }
- }
+export abstract class LightDarkMode {
+ static currentMode: mode;
}