From 656e157f140df1e822d2e19232844678c1c3cea5 Mon Sep 17 00:00:00 2001 From: p-wojt Date: Thu, 30 Dec 2021 18:19:00 +0100 Subject: [PATCH] Add/remove/clear items --- app.css | 62 ++++++++++++++++++ index.html | 15 ++++- src/app.ts | 99 +++++++++++++++++++++++++++++ src/components/base-component.ts | 15 +++++ src/components/menu-delete-item.ts | 17 +++++ src/components/menu-item-list.ts | 40 ++++++++++++ src/components/menu-item.ts | 19 ++++++ static/close.png | Bin 0 -> 6536 bytes static/right-arrow.png | Bin 0 -> 2601 bytes webpack.config.js | 10 +-- webpack.config.prod.js | 2 +- 11 files changed, 272 insertions(+), 7 deletions(-) create mode 100644 app.css create mode 100644 src/components/base-component.ts create mode 100644 src/components/menu-delete-item.ts create mode 100644 src/components/menu-item-list.ts create mode 100644 src/components/menu-item.ts create mode 100644 static/close.png create mode 100644 static/right-arrow.png diff --git a/app.css b/app.css new file mode 100644 index 0000000..1cbcd7e --- /dev/null +++ b/app.css @@ -0,0 +1,62 @@ +html { + 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 { + height: 1.5rem; + width: 15rem; +} + +ul { + list-style-type: none; + padding: 0; + text-align: center; +} + +li { + padding: 0.75rem; +} + +.openCloseMenu { + width: 1rem; + height: 1rem; +} + +.item-delete { + width: 1rem; + height: 1rem; + float: right; +} + +#menu { + height: 100vh; + width: 20rem; +} + +#newItemButton { + height: 2rem; + width: 10rem; + margin-top: 0.5rem; +} + +#menu-item { + text-align: center; +} + +#counter { + font-size: 24px; + text-align: center; +} + + diff --git a/index.html b/index.html index 85b43a0..f19797d 100644 --- a/index.html +++ b/index.html @@ -5,8 +5,21 @@ Roulette wheel + + - Test! + + + \ No newline at end of file diff --git a/src/app.ts b/src/app.ts index e69de29..ac6fa6b 100644 --- a/src/app.ts +++ b/src/app.ts @@ -0,0 +1,99 @@ +import { ItemEl } from "./components/menu-item"; +import { ItemElList } from "./components/menu-item-list"; + +const canvas = document.querySelector("canvas")! as HTMLCanvasElement; +const ctx = canvas.getContext("2d")!; +const centreX = canvas.width / 2; +const centreY = canvas.height / 2; + +ctx.beginPath(); +ctx.moveTo(centreX, centreY); +ctx.stroke(); + +console.log("Works!"); + +const maxItems = 16; +const items: ItemElList = new ItemElList(); + +const menuEl = document.getElementById("menu")! as HTMLDivElement; +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 avaliableRGBs = ["255, 0, 0", "0, 255, 0", "0, 0, 255"]; +const bgOpacity = 0.5; +let nextColor = avaliableRGBs[0]; + +let counter = 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 ItemEl( + 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}`; +} + +function setNextColor() { + nextColor = avaliableRGBs[counter % avaliableRGBs.length]; +} + +function calculateItemElId(item: ItemEl) { + return +item.el.id.slice(0, item.el.id.indexOf("-")); +} + +function initalizeIdsPool() { + idsPool.length = 0; + for (let i = 0; i < maxItems; i++) { + idsPool.push(i); + } +} + +newItemButtonEl.addEventListener("click", addNewItem); +removeAllItemsButtonEl.addEventListener("click", removeAllItems); diff --git a/src/components/base-component.ts b/src/components/base-component.ts new file mode 100644 index 0000000..921615f --- /dev/null +++ b/src/components/base-component.ts @@ -0,0 +1,15 @@ +export abstract class Component { + el: T; + + constructor(el: T){ + this.el = el; + } + + 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/menu-delete-item.ts b/src/components/menu-delete-item.ts new file mode 100644 index 0000000..ef0601c --- /dev/null +++ b/src/components/menu-delete-item.ts @@ -0,0 +1,17 @@ +import { Component } from "./base-component"; + +export class DeleteItemEl 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); + } + + configure(){ + // TODO: make icon rotation after mouse over event + } +} \ No newline at end of file diff --git a/src/components/menu-item-list.ts b/src/components/menu-item-list.ts new file mode 100644 index 0000000..0fcbcfe --- /dev/null +++ b/src/components/menu-item-list.ts @@ -0,0 +1,40 @@ +import { Component } from "./base-component"; +import { ItemEl } from "./menu-item"; + +export class ItemElList extends Component { + private items: ItemEl[]; + + constructor(){ + const UList = document.createElement('ul'); + UList.className = 'item-list'; + super(UList); + this.items = []; + } + + get itemsLength() { + return this.items.length; + } + + addItem(item: ItemEl){ + this.items.push(item); + this.el.appendChild(item.el); + } + + clear(){ + this.removeChildren(); + this.items = []; + } + + removeItem(item: ItemEl){ + item.el.remove(); + const indexToRemove = this.items.indexOf(item); + this.items.splice(indexToRemove, 1); + } + + findLastItem(){ + if(this.items.length > 0){ + return this.items[this.items.length - 1]; + } + return null; + } +} diff --git a/src/components/menu-item.ts b/src/components/menu-item.ts new file mode 100644 index 0000000..0c031d0 --- /dev/null +++ b/src/components/menu-item.ts @@ -0,0 +1,19 @@ +import { Component } from "./base-component"; +import { DeleteItemEl } from "./menu-delete-item"; + +export class ItemEl extends Component { + + deleteItem: DeleteItemEl; + + constructor(id: number, value: string, color: string){ + const deleteItem = new DeleteItemEl(id); + const el = document.createElement('li'); + el.className = 'menu-item'; + el.id = `${id}-item`; + el.textContent = value; + el.style.backgroundColor = color; + el.appendChild(deleteItem.el); + super(el); + this.deleteItem = deleteItem; + } +} \ No newline at end of file diff --git a/static/close.png b/static/close.png new file mode 100644 index 0000000000000000000000000000000000000000..45e82a40c041d1f617d873e625a9a724f982b396 GIT binary patch literal 6536 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 literal 0 HcmV?d00001 diff --git a/static/right-arrow.png b/static/right-arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..f224f62ea8f78f76e3ec92b7bf56775ccbf7a4fa GIT binary patch literal 2601 zcmeHJSx{3~7{0kgWsy}u1*<7qqb$m3C6+ZZL_jG)Q2|2)q!9KXOA(^IDOzv^$F-OV z0U}aBiWNb&01irVVHY8QQ50ezF`z(#iOKEZp{>sJL9K7?ow@(_pa1**?L3`h-d=9H z+NRnN1nGLXyY7G>7`QN`sR5wr%E}f18VN2QJ2f>m2ZqQ`!BH#D-9G_>^k}m`ChJ(* zeh^%eNb*bcp@$_V2gip($;ruUBVwZxLW1K$*V5x@EUAMj1Yu^pJ$I5&6b1VKzyI0| zFzWKW!On$=JG^`#46K2jJ5N(fTW7wWzJa09LSvIfOH9p{EysPi@+9u{=ZeKrtN&qz|I5dnF9u*xEOOH=xAk4JG=@~~)W@eo| zf8pm#EH)>%;Fsc(tEFYvu9sI--mI#wsjcJHH#9ai-@E^ywWG7E`{ASBKK{Uyp=ZyB zM}#j#qhn&pOX>K;>&dBUnSADrLitvuJ{KQ_K+xO?57*5*5A?qrd~>mN&eG;rOI(9H zazah>Na7<43tU-Sw|my!+p)!L#UAf91*fbc&Ya6mZ*Sn2CAHZkc;RV6WnGT*(Bu#7 zgm#{sLEm=2rT++n!%#gwl%dQ#RIh4Hy5GOYD#G`w#EFUqpl$d<`)&7x(e{+XlC$>g zRl(f^y-N+nV>~l<;V5gWE87lji>YZoX3EPBeDssN`=DFogj7+T-p|qh#wSGXhvpGrej#I`oj$^;0Q-H+nI8#JTxx|!!-kmIkC5F$a)I2J<%>{gf;c4Crt(Lt}1Pq^b zgTs`xI=B#JcA7XQ1b>_f7lkb#LKv*UpC%j5H2Ty3JNkJ%ZW7_IJ|9}K)j00t$1a6q zGQ(o^-dXBHn|+YZCUwqI{CgK|M7a3zBfguV9? ztuU(6Ot$sY_?vAeHoZmVa}HPp4QtPg?1K*U<++VX#kGr}Wr-q@x@WYjQ&rMb#8vvT zC~k7Jsg$ei#r&Qr4P00AeIi;jP|a0xrp!7;>Iyy&Q0wPqNs$gqBA}k!;VKc~{#-z{ z+~q18#)msq4eT-DT@_hjzNrS~--*o`d=jW}L>?#>Dp=|(4Wsl=gt7*;Li`!bCl4?? z_-C0wt*EX3H#b3lZwjQ%WNbN4OdjLZt(iAX7W6Gsaph_1PL^XXGF3C3B`8(U##gAg zy+w#@Z;vy>8K_y)?Seh3@|$E-!tQcTT>y?&s`BIvHJ?(9$aaf3ygMLi6$qVI^UXHo zA~L;E4)0qK!>Gy$)q$vF8fbPYX!NaRYCdBNDxs$Op%O=s+8COjVB`Tl)lL|9{_kF8ia8KrChSqSkZFppbP+Hrur6KDF)C9 zJ1q`FH^%lnIK>Fv^rro4Tv4<1RUSe(IBZLcoUkL$??lEcG9QXs`%?4X7WR_k@~_a< z(#a82Tv5Wt2kXe^UqFHqYP&B-KN`zIRe|vhG5$`i{`s~sDZR~K1TG!7zaeMqMlGT~ c!=ZBZ-0++*Pf@r_$?OxwgXHD