redefine project

This commit is contained in:
p-wojt 2021-12-31 21:42:08 +01:00
parent 656e157f14
commit 9649216920
12 changed files with 359 additions and 154 deletions

35
app.css
View File

@ -1,18 +1,6 @@
html { html {
font-family: 'Courier New', Courier, monospace; font-family: 'Courier New', Courier, monospace;
} }
canvas {
margin: 0;
position: absolute;
width: 500px;
height: 500px;
top: 50%;
left: 50%;
margin-right: -50%;
transform: translate(-50%, -50%);
}
input { input {
height: 1.5rem; height: 1.5rem;
width: 15rem; width: 15rem;
@ -28,7 +16,12 @@ li {
padding: 0.75rem; padding: 0.75rem;
} }
.openCloseMenu { .open-close-menu{
display: flex;
justify-content: right;
}
.open-close-arrow {
width: 1rem; width: 1rem;
height: 1rem; height: 1rem;
} }
@ -39,12 +32,22 @@ li {
float: right; float: right;
} }
#menu { .decreasing {
width: 0.1rem;
transition-duration: 3s;
}
.normal {
width: 20rem;
transition-duration: 3s;
}
.menu {
height: 100vh; height: 100vh;
width: 20rem; width: 20rem;
} }
#newItemButton { .new-item-button {
height: 2rem; height: 2rem;
width: 10rem; width: 10rem;
margin-top: 0.5rem; margin-top: 0.5rem;
@ -54,7 +57,7 @@ li {
text-align: center; text-align: center;
} }
#counter { .counter {
font-size: 24px; font-size: 24px;
text-align: center; text-align: center;
} }

View File

@ -1,25 +1,25 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Roulette wheel</title> <title>Roulette wheel</title>
<script type="module" src="dist/bundle.js"></script> <script type="module" src="dist/bundle.js"></script>
<link rel="stylesheet" href="app.css"> <link rel="stylesheet" href="app.css" />
</head> </head>
<body> <body>
<div id="menu"> <div class="menu">
<img src="static/right-arrow.png" alt="open-close-arrow" class="openCloseMenu"> <div class="open-close-menu">
<p id="counter">0/16</p> </div>
<div id="newItem"> <div class="counter">
<label for="newItem">Item name</label> </div>
<input name="newItem" minlength="1" maxlength="32"> <div class="item-menu">
<button id="newItemButton">Add</button> <label for="new-item">Item name</label>
<button id="removeAllItemsButton">Remove all</button> <input name="new-item" minlength="1" maxlength="32">
</div> <button class="new-item-button">Add</button>
<button class="remove-all-items-button">Remove all</button>
</div>
</div> </div>
<canvas></canvas> </body>
<footer><div>Icons made by <a href="https://www.flaticon.com/authors/roundicons" title="Roundicons">Roundicons</a> from <a href="https://www.flaticon.com/" title="Flaticon">www.flaticon.com</a></div></footer>
</body>
</html> </html>

View File

@ -1,99 +1,202 @@
import { ItemEl } from "./components/menu-item"; // import { MenuItem } from "./components/menu-item";
import { ItemElList } from "./components/menu-item-list"; import { CounterItem } from "./components/counter-item";
import { MenuItem } from "./components/menu-item";
import { MenuItemList } from "./components/menu-item-list";
import { OpenCloseArrow } from "./components/open-close-arrow";
import { Counter } from "./model/counter";
import { Item } from "./model/item";
import { avaliableIds, initializeIdsPool } from "./utils/item-id-pool";
import { avaliableRGBs } from "./utils/utils";
// import { OpenCloseArrow } from "./components/open-close-arrow";
const canvas = document.querySelector("canvas")! as HTMLCanvasElement; const counterEl = document.getElementsByClassName(
const ctx = canvas.getContext("2d")!; "counter"
const centreX = canvas.width / 2; )[0]! as HTMLDivElement;
const centreY = canvas.height / 2; const itemMenuEl = document.getElementsByClassName(
"item-menu"
)[0]! as HTMLDivElement;
const openCloseMenuEl = document.getElementsByClassName(
"open-close-menu"
)[0]! as HTMLDivElement;
const inputEl = document.querySelector("input")! as HTMLInputElement;
const addButtonEl = document.getElementsByClassName(
"new-item-button"
)[0]! as HTMLButtonElement;
const removeAllItemsButtonEl = document.getElementsByClassName(
"remove-all-items-button"
)[0]! as HTMLButtonElement;
HTMLUL
ctx.beginPath(); const MIN_ITEMS = 0;
ctx.moveTo(centreX, centreY); const MAX_ITEMS = 16;
ctx.stroke();
console.log("Works!"); const openCloseItem = new OpenCloseArrow();
openCloseMenuEl.appendChild(openCloseItem.el);
const maxItems = 16; const counterItem = new CounterItem(MIN_ITEMS, MAX_ITEMS);
const items: ItemElList = new ItemElList(); counterEl.appendChild(counterItem.el);
const menuEl = document.getElementById("menu")! as HTMLDivElement; const counter = counterItem.getCounter;
const counterEl = document.getElementById("counter")!;
const itemNameInput = document.querySelector("input")! as HTMLInputElement;
const newItemButtonEl = document.getElementById(
"newItemButton"
)! as HTMLButtonElement;
const removeAllItemsButtonEl = document.getElementById(
"removeAllItemsButton"
)! as HTMLButtonElement;
menuEl.appendChild(items.el); const items: MenuItemList = new MenuItemList();
itemMenuEl.appendChild(items.el);
const avaliableRGBs = ["255, 0, 0", "0, 255, 0", "0, 0, 255"];
const bgOpacity = 0.5;
let nextColor = avaliableRGBs[0];
let counter = 0;
const idsPool: number[] = []; configure();
initalizeIdsPool();
function addNewItem() { function configure() {
if (itemNameInput.value.length > 0 && itemNameInput.value.length <= 32) { initializeIdsPool(MAX_ITEMS);
if (counter < maxItems && idsPool.length > 0) { }
const item = new ItemEl(
idsPool.pop()!,
itemNameInput.value,
`rgba(${nextColor}, ${bgOpacity})`
);
item.deleteItem.el.addEventListener("click", () => { addButtonEl.addEventListener("click", () => {
const itemElId = calculateItemElId(item); const id = avaliableIds.pop();
idsPool.push(itemElId); const name = inputEl.value;
setNextColor(); if (id) {
items.removeItem(item); if (name) {
counter--; if (counter.increment()) {
updateCounter(); const item = new MenuItem(id, name, avaliableRGBs[MAX_ITEMS % Counter.value]);
}); console.log(item.deleteItem);
item.deleteItem.el.addEventListener('click', () => {
items.addItem(item); if(counter.decrement()){
counter++; avaliableIds.push(item.el.id)
updateCounter(); items.removeItem(item);
setNextColor(); counterItem.updateContent();
}
})
items.addItem(item);
counterItem.updateContent();
}
} else { } else {
alert("Maximum number of items!"); alert("Item name cannot be empty!");
} }
}
}
function removeAllItems() {
if (items.itemsLength > 0) {
items.clear();
counter = 0;
initalizeIdsPool();
nextColor = avaliableRGBs[0];
updateCounter();
} else { } else {
alert("Nothing to clear!"); alert("Maxium number of elements!");
} }
} });
function updateCounter() { removeAllItemsButtonEl.addEventListener("click", () => {
counterEl.textContent = `${counter}/${maxItems}`; initializeIdsPool(MAX_ITEMS);
} items.clear();
counter.clear();
counterItem.updateContent();
});
function setNextColor() { // const openCloseMenuEl = document.getElementsByClassName(
nextColor = avaliableRGBs[counter % avaliableRGBs.length]; // "open-close-menu"
} // )[0]! as HTMLDivElement;
function calculateItemElId(item: ItemEl) { // const itemNameInput = document.querySelector("input")! as HTMLInputElement;
return +item.el.id.slice(0, item.el.id.indexOf("-"));
}
function initalizeIdsPool() { // const newItemButtonEl = document.getElementById(
idsPool.length = 0; // "newItemButton"
for (let i = 0; i < maxItems; i++) { // )! as HTMLButtonElement;
idsPool.push(i);
}
}
newItemButtonEl.addEventListener("click", addNewItem); // const removeAllItemsButtonEl = document.getElementById(
removeAllItemsButtonEl.addEventListener("click", removeAllItems); // "removeAllItemsButton"
// )! as HTMLButtonElement;
// // const newItemMenu = document.getElementById('new-item-menu')! as HTMLDivElement;
// menuEl.appendChild(items.el);
// openCloseMenuEl.appendChild(new OpenCloseArrow().el);
// const avaliableRGBs = ["255, 0, 0", "0, 255, 0", "0, 0, 255"];
// const bgOpacity = 0.5;
// let nextColor = avaliableRGBs[0];
// const idsPool: number[] = [];
// initalizeIdsPool();
// function addNewItem() {
// if (itemNameInput.value.length > 0 && itemNameInput.value.length <= 32) {
// if (counter < maxItems && idsPool.length > 0) {
// const item = new MenuItem(
// idsPool.pop()!,
// itemNameInput.value,
// `rgba(${nextColor}, ${bgOpacity})`
// );
// item.deleteItem.el.addEventListener("click", () => {
// const itemElId = calculateItemElId(item);
// idsPool.push(itemElId);
// setNextColor();
// items.removeItem(item);
// counter--;
// updateCounter();
// });
// items.addItem(item);
// counter++;
// updateCounter();
// setNextColor();
// } else {
// alert("Maximum number of items!");
// }
// }
// }
// function removeAllItems() {
// if (items.itemsLength > 0) {
// items.clear();
// counter = 0;
// initalizeIdsPool();
// nextColor = avaliableRGBs[0];
// updateCounter();
// } else {
// alert("Nothing to clear!");
// }
// }
// function updateCounter() {
// counterEl.textContent = `${counter}/${maxItems}`;
// counterEl.animate([
// { transform: 'scale(1.25)'},
// { transform: 'scale(1.00)'}
// ],
// {
// duration: 500
// }
// );
// }
// function setNextColor() {
// nextColor = avaliableRGBs[counter % avaliableRGBs.length];
// }
// function calculateItemElId(item: MenuItem) {
// return +item.el.id.slice(0, item.el.id.indexOf("-"));
// }
// const openCloseArrow = document.getElementById("open-close-arrow")!;
// let open = true;
// function rotateOpenCloseArrow() {
// openCloseArrow.animate([
// { transform: 'rotate(180deg)' }
// ],
// {
// duration: 500,
// }
// );
// if(open){
// menuEl.className = 'decreasing';
// open = false;
// }else{
// menuEl.className = 'normal';
// open = true;
// }
// }
// function initalizeIdsPool() {
// idsPool.length = 0;
// for (let i = 0; i < maxItems; i++) {
// idsPool.push(i);
// }
// }
// newItemButtonEl.addEventListener("click", addNewItem);
// removeAllItemsButtonEl.addEventListener("click", removeAllItems);
// openCloseArrow.addEventListener("click", rotateOpenCloseArrow);

View File

@ -0,0 +1,35 @@
import { Counter } from "../model/counter";
import { Component } from "./base-component";
export class CounterItem extends Component<HTMLElement>{
private counter: Counter;
constructor(min: number, max: number){
const counterEl = document.createElement('p');
counterEl.textContent = `${min}/${max}`;
counterEl.className = 'counter-item';
super(counterEl);
this.counter = new Counter(min, max);
}
get getCounter(){
return this.counter;
}
updateContent(){
this.el.textContent = `${Counter.value}/${this.counter.max}`
this.animate();
}
private animate(): void{
this.el.animate(
[
{ transform: 'scale(1.25)'},
{ transform: 'scale(1.00)'}
],
{
duration: 500
}
);
}
}

View File

@ -1,13 +1,13 @@
import { Component } from "./base-component"; import { Component } from "./base-component";
export class DeleteItemEl extends Component<HTMLImageElement>{ export class ItemRemoval extends Component<HTMLImageElement>{
constructor(id: number){ constructor(id: number){
const el = document.createElement('img'); const el = document.createElement('img');
el.src = 'static/close.png'; el.src = 'static/close.png';
el.alt = 'delete'; el.alt = 'delete';
el.className = 'item-delete' el.className = `item-delete`;
el.id = `${id}-delete`; el.id = `${id}-delete`
super(el); super(el);
} }

View File

@ -1,40 +1,33 @@
import { Component } from "./base-component"; import { Component } from "./base-component";
import { ItemEl } from "./menu-item"; import { MenuItem } from "./menu-item";
export class ItemElList extends Component<HTMLUListElement> { export class MenuItemList extends Component<HTMLUListElement> {
private items: ItemEl[]; private items: MenuItem[];
constructor(){ constructor() {
const UList = document.createElement('ul'); const UList = document.createElement("ul");
UList.className = 'item-list'; UList.className = "item-list";
super(UList); super(UList);
this.items = []; this.items = [];
} }
get itemsLength() { get itemsLength() {
return this.items.length; return this.items.length;
} }
addItem(item: ItemEl){ addItem(item: MenuItem) {
this.items.push(item); this.items.push(item);
this.el.appendChild(item.el); this.el.appendChild(item.el);
} }
clear(){ clear() {
this.removeChildren(); this.removeChildren();
this.items = []; this.items = [];
} }
removeItem(item: ItemEl){ removeItem(item: MenuItem) {
item.el.remove(); item.el.remove();
const indexToRemove = this.items.indexOf(item); const indexToRemove = this.items.indexOf(item);
this.items.splice(indexToRemove, 1); this.items.splice(indexToRemove, 1);
} }
findLastItem(){
if(this.items.length > 0){
return this.items[this.items.length - 1];
}
return null;
}
} }

View File

@ -1,12 +1,12 @@
import { Component } from "./base-component"; import { Component } from "./base-component";
import { DeleteItemEl } from "./menu-delete-item"; import { ItemRemoval } from "./item-removal";
export class ItemEl extends Component<HTMLLIElement> { export class MenuItem extends Component<HTMLLIElement> {
deleteItem: DeleteItemEl; deleteItem: ItemRemoval;
constructor(id: number, value: string, color: string){ constructor(id: number, value: string, color: string){
const deleteItem = new DeleteItemEl(id); const deleteItem = new ItemRemoval(id);
const el = document.createElement('li'); const el = document.createElement('li');
el.className = 'menu-item'; el.className = 'menu-item';
el.id = `${id}-item`; el.id = `${id}-item`;

View File

@ -0,0 +1,12 @@
import { Component } from "./base-component";
export class OpenCloseArrow extends Component<HTMLImageElement> {
constructor() {
const arrow = document.createElement('img');
arrow.src = 'static/right-arrow.png';
arrow.alt = 'open-close-arrow';
arrow.className = 'open-close-arrow';
super(arrow);
}
}

39
src/model/counter.ts Normal file
View File

@ -0,0 +1,39 @@
export class Counter {
static value: number;
min: number;
max: number;
constructor(min: number, max: number){
Counter.value = min;
this.min = min;
this.max = max;
}
increment(){
if(!this.isMax()){
Counter.value++;
return true;
}
return false;
}
decrement(){
if(!this.isMin()){
Counter.value--;
return true;
}
return false;
}
clear(){
Counter.value = 0;
}
private isMax(){
return this.max === Counter.value;
}
private isMin(){
return this.min === Counter.value;
}
}

11
src/model/item.ts Normal file
View File

@ -0,0 +1,11 @@
export class Item {
id: number;
name: string;
color: string;
constructor(id: number, name: string, color: string){
this.id = id;
this.name = name;
this.color = color;
}
}

View File

@ -0,0 +1,7 @@
export const avaliableIds: number[] = [];
export function initializeIdsPool(numberOfElements: number){
for(let i = 1; i <= numberOfElements; i++){
avaliableIds[i] = i;
}
}

2
src/utils/utils.ts Normal file
View File

@ -0,0 +1,2 @@
export const avaliableRGBs = ["255, 0, 0", "0, 255, 0", "0, 0, 255"];