From 420805ca728035c4bfbd3a7ee41e865c4ac20294 Mon Sep 17 00:00:00 2001 From: CelesteNaude <286celeste@gmail.com> Date: Thu, 17 Feb 2022 15:35:46 +0200 Subject: [PATCH 01/19] finished Getting Started settings --- app.ts | 1 + index.html | 2 +- package-lock.json | 29 +++++++++++++++++++++++++++++ package.json | 23 +++++++++++++++++++++++ 4 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 app.ts create mode 100644 package-lock.json create mode 100644 package.json diff --git a/app.ts b/app.ts new file mode 100644 index 00000000..60fa19e1 --- /dev/null +++ b/app.ts @@ -0,0 +1 @@ +window.onload = () => { $("body").text("Hello world"); } diff --git a/index.html b/index.html index add5e736..6f6fc23a 100644 --- a/index.html +++ b/index.html @@ -3,6 +3,7 @@ JS Onboard Project + @@ -10,4 +11,3 @@ - diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..9adaa2d7 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,29 @@ +{ + "name": "onboard-javascript", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/jquery": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.13.tgz", + "integrity": "sha512-ZxJrup8nz/ZxcU0vantG+TPdboMhB24jad2uSap50zE7Q9rUeYlCF25kFMSmHR33qoeOgqcdHEp3roaookC0Sg==", + "requires": { + "@types/sizzle": "*" + } + }, + "@types/jquery.browser": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@types/jquery.browser/-/jquery.browser-0.1.1.tgz", + "integrity": "sha512-1y/iQmNaVkQfVhCc39q3KYOqS/oZscurcbiOcYasiSoX8v8XMjkAfiBmgXMgMLRFzDDoNT6Jmr1Krqh3XDMDWQ==", + "requires": { + "@types/jquery": "*" + } + }, + "@types/sizzle": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", + "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 00000000..24487ab9 --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "onboard-javascript", + "version": "1.0.0", + "description": "onboard", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build": "tsc --build" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/CelesteNaude/onboard-javascript.git" + }, + "author": "celeste", + "license": "ISC", + "bugs": { + "url": "https://github.com/CelesteNaude/onboard-javascript/issues" + }, + "homepage": "https://github.com/CelesteNaude/onboard-javascript#readme", + "dependencies": { + "@types/jquery.browser": "^0.1.1" + } +} From d5ce530df92583042a271e07addbdeee4a4ebc70 Mon Sep 17 00:00:00 2001 From: CelesteNaude <286celeste@gmail.com> Date: Wed, 23 Feb 2022 20:46:46 +0200 Subject: [PATCH 02/19] added table & pagination --- app.ts | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++- index.html | 11 ++++- style.css | 77 ++++++++++++++++++++++++++++++++++ 3 files changed, 205 insertions(+), 2 deletions(-) create mode 100644 style.css diff --git a/app.ts b/app.ts index 60fa19e1..35beea25 100644 --- a/app.ts +++ b/app.ts @@ -1 +1,118 @@ -window.onload = () => { $("body").text("Hello world"); } + + +const state = { + 'page': 1, + 'rows': 15, + + 'window': 10 +} + +async function pagination(tableData: any, numRecords: number, page: number, rows: number) { + let trimStart = (page - 1) * rows + let trimEnd = trimStart + rows + + let trimmedData = tableData.slice(trimStart, trimEnd) + let pages = Math.ceil(numRecords / rows) + + return { + 'data': trimmedData, + 'pages': pages + } +} + +function pageButtons(pages: number) { + let pageNum = document.getElementById('page-number') + pageNum!.innerHTML = `

Page ${state.page}

` + let wrapper = document.getElementById('pagination-wrapper') + wrapper!.innerHTML = "" + + let maxLeft = (state.page - Math.floor(state.window / 2)) + let maxRight = (state.page + Math.floor(state.window / 2)) + + // Button numbers must not go below 1 + if (maxLeft < 1) { + maxLeft = 1 + maxRight = state.window + } + + // Button numbers cannot exceed number of pages + if (maxRight > pages) { + maxLeft = pages - (state.window - 1) + maxRight = pages + + if (maxLeft < 1) { + maxLeft = 1 + } + } + + for (let page = maxLeft; page <= maxRight; page++) { + wrapper!.innerHTML += `` + } + + // If the current page is not 1 -> add '<< First' button + if (state.page != 1) { + wrapper!.innerHTML = `` + wrapper!.innerHTML + } + + // If the current page is not the last page -> add 'Last >>' button + if (state.page != pages) { + wrapper!.innerHTML += `` + } + + $('.page').on('click', function () { + + state.page = Number($(this).val()) + + loadIntoTable(document.querySelector("table")) + + }) +} + + +async function loadIntoTable(table: any) { + // Select elements to populate + let tableHead = table.querySelector("thead") + let tableBody = table.querySelector("tbody") + + let numRecords = await (await fetch('/recordCount')).json() + let cnumRecords = numRecords - 1 + let recordsLink = "/records?from=0&to=" + cnumRecords + let tableData = await (await fetch(recordsLink)).json() + + let rows = pagination(tableData, cnumRecords, state.page, state.rows) + console.log('Data:', rows) + + // API call for column headers + let hearders = await (await fetch('/columns')).json() + + // Clear the table + tableHead.innerHTML = "" + tableBody.innerHTML = "" + + // Populate the headers + for (let headerText of hearders) { + let headerElement = document.createElement("th") + + headerElement.textContent = headerText; + tableHead.querySelector("tr").appendChild(headerElement) + } + + // Populate the rows + for (let row of (await rows).data) { + let rowElement = document.createElement("tr") + + for (let cellText of row) { + let cellElement = document.createElement("td") + + cellElement.textContent = cellText + rowElement.appendChild(cellElement); + } + + tableBody.appendChild(rowElement) + } + pageButtons((await rows).pages) +} + +window.onload = () => { + loadIntoTable(document.querySelector("table")) +} diff --git a/index.html b/index.html index 6f6fc23a..3528b590 100644 --- a/index.html +++ b/index.html @@ -2,12 +2,21 @@ JS Onboard Project + -

Hello

+

Onboarding Project

+ + + +
+

Page

+
+
+
diff --git a/style.css b/style.css new file mode 100644 index 00000000..674b1020 --- /dev/null +++ b/style.css @@ -0,0 +1,77 @@ +body { + overflow: hidden; /* Hide scrollbars */ + } + +.table { + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + border-collapse: collapse; + /* overflow: hidden; */ + font-weight: bold; + text-align: center; + width: 100%; + table-layout:fixed; +} + +.table thead th { + background: #009578; + color: #ffff; +} + +.table td, +.table th { + padding: 10px 20px; + overflow: hidden; + text-overflow: ellipsis; + word-wrap: break-word; +} + +.table tbody tr:nth-of-type(even) { + background: #eeeeee; +} + +.table tbody tr:last-of-type { + border-bottom: #009578; +} + +.page-num { + font-weight: bold; + text-align: center; +} + +.center { + display: flex; + justify-content: center; + align-items: center; +} + +.container { + padding: 1rem; + margin: 3rem auto; + display: flex; + justify-content: center; + align-items: center; +} + +.controls-item { + display: inline-block; +} + +.btn { + color: black; + float: left; + padding: 8px 16px; + text-decoration: none; + border-collapse: collapse; +} + +.button:active{ + color: #fdfdfd; + background-color: #1d1f20; + border: solid 1px #1d1f20; +} + +.btn:hover:not(.selected) { + color: #fdfdfd; + background-color: #009578; + border: solid 1px #009578; +} From b398c118243a574109b0e6d80172eeec6ed67e6c Mon Sep 17 00:00:00 2001 From: CelesteNaude <286celeste@gmail.com> Date: Thu, 24 Feb 2022 18:07:26 +0200 Subject: [PATCH 03/19] 'search' & 'display n amount of records' function --- app.ts | 47 ++++++++++++++++++++++++++++++++++++++--------- index.html | 27 +++++++++++++++++++-------- style.css | 12 ++++-------- 3 files changed, 61 insertions(+), 25 deletions(-) diff --git a/app.ts b/app.ts index 35beea25..10938ce4 100644 --- a/app.ts +++ b/app.ts @@ -1,18 +1,42 @@ - -const state = { +let state = { 'page': 1, - 'rows': 15, + 'records': 15, 'window': 10 } -async function pagination(tableData: any, numRecords: number, page: number, rows: number) { - let trimStart = (page - 1) * rows - let trimEnd = trimStart + rows +function searchFunction() { + // Get entered ID and calculate what page it is on + let id = Number($('#id-search').val()) + let pageNum = Math.ceil((id + 1) / state.records) + console.log("Go to page ", pageNum) + // Set page to the one that the searched ID is on + state.page = pageNum + loadIntoTable(document.querySelector("table")) +} + + +function dropFunction() { + let num = Number($('#show-by').val()) + state.records = num + console.log("Show records of ", state.records) + loadIntoTable(document.querySelector("table")) +} + + +async function pagination(tableData: any, numRecords: number, page: number, records: number) { + console.log("In pag: ", numRecords, " and ", page, " and ", records) + let trimStart = (page - 1) * records + let trimEnd = trimStart + records + console.log("In pag: trimStart", trimStart, " and trimEnd", trimEnd, " records? ", records) let trimmedData = tableData.slice(trimStart, trimEnd) - let pages = Math.ceil(numRecords / rows) + let pages = Math.ceil(numRecords / records) + + // User info: Display number of records and pages on window + let pageDet = document.getElementById('page-details') + pageDet!.innerHTML = `

There are ${numRecords + 1} records and ${pages} pages

` return { 'data': trimmedData, @@ -21,8 +45,11 @@ async function pagination(tableData: any, numRecords: number, page: number, rows } function pageButtons(pages: number) { + // User info: Display current page number let pageNum = document.getElementById('page-number') pageNum!.innerHTML = `

Page ${state.page}

` + + // Select element to create pagination buttons in let wrapper = document.getElementById('pagination-wrapper') wrapper!.innerHTML = "" @@ -70,7 +97,7 @@ function pageButtons(pages: number) { async function loadIntoTable(table: any) { - // Select elements to populate + // Select table elements to populate let tableHead = table.querySelector("thead") let tableBody = table.querySelector("tbody") @@ -79,7 +106,9 @@ async function loadIntoTable(table: any) { let recordsLink = "/records?from=0&to=" + cnumRecords let tableData = await (await fetch(recordsLink)).json() - let rows = pagination(tableData, cnumRecords, state.page, state.rows) + console.log('Records:', state.records) + + let rows = pagination(tableData, cnumRecords, state.page, state.records) console.log('Data:', rows) // API call for column headers diff --git a/index.html b/index.html index 3528b590..20ff6713 100644 --- a/index.html +++ b/index.html @@ -9,14 +9,25 @@

Onboarding Project

- - - -
-

Page

-
-
-
+

+ + + + + + + + +
+

Page

+
+
+
diff --git a/style.css b/style.css index 674b1020..5988ab4b 100644 --- a/style.css +++ b/style.css @@ -1,5 +1,5 @@ body { - overflow: hidden; /* Hide scrollbars */ + /* overflow: hidden; Hide scrollbars */ } .table { @@ -34,19 +34,15 @@ body { } .page-num { + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + background: #009578; font-weight: bold; text-align: center; } -.center { - display: flex; - justify-content: center; - align-items: center; -} - .container { padding: 1rem; - margin: 3rem auto; + margin: 1rem auto; display: flex; justify-content: center; align-items: center; From 0fada8668f95a82963de49704b212be194c953fa Mon Sep 17 00:00:00 2001 From: CelesteNaude <286celeste@gmail.com> Date: Sun, 27 Feb 2022 10:58:09 +0200 Subject: [PATCH 04/19] edited user interface --- app.ts | 38 +++++++++++++----- index.html | 49 ++++++++++++++--------- style.css | 115 ++++++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 158 insertions(+), 44 deletions(-) diff --git a/app.ts b/app.ts index 10938ce4..7a7788e2 100644 --- a/app.ts +++ b/app.ts @@ -2,39 +2,39 @@ let state = { 'page': 1, 'records': 15, - 'window': 10 } +// Search ID function function searchFunction() { // Get entered ID and calculate what page it is on let id = Number($('#id-search').val()) let pageNum = Math.ceil((id + 1) / state.records) - console.log("Go to page ", pageNum) + // Set page to the one that the searched ID is on state.page = pageNum loadIntoTable(document.querySelector("table")) } - +// Select num records to display from drop down function function dropFunction() { + // Get value selected in drop down and reload table let num = Number($('#show-by').val()) state.records = num - console.log("Show records of ", state.records) loadIntoTable(document.querySelector("table")) } - +// Records to display in table function async function pagination(tableData: any, numRecords: number, page: number, records: number) { - console.log("In pag: ", numRecords, " and ", page, " and ", records) + // Calculate where records to display should start and end let trimStart = (page - 1) * records let trimEnd = trimStart + records - console.log("In pag: trimStart", trimStart, " and trimEnd", trimEnd, " records? ", records) let trimmedData = tableData.slice(trimStart, trimEnd) let pages = Math.ceil(numRecords / records) // User info: Display number of records and pages on window + // TODO: create a global get element function let pageDet = document.getElementById('page-details') pageDet!.innerHTML = `

There are ${numRecords + 1} records and ${pages} pages

` @@ -44,10 +44,17 @@ async function pagination(tableData: any, numRecords: number, page: number, reco } } +// Create paging buttons functions function pageButtons(pages: number) { // User info: Display current page number let pageNum = document.getElementById('page-number') - pageNum!.innerHTML = `

Page ${state.page}

` + if (state.page) { + pageNum!.innerHTML = `

Page ${state.page}

` + } + else { + pageNum!.innerHTML = `

No records to display

` + } + // Select element to create pagination buttons in let wrapper = document.getElementById('pagination-wrapper') @@ -62,7 +69,7 @@ function pageButtons(pages: number) { maxRight = state.window } - // Button numbers cannot exceed number of pages + // Button numbers cannot exceed max number of pages if (maxRight > pages) { maxLeft = pages - (state.window - 1) maxRight = pages @@ -72,6 +79,7 @@ function pageButtons(pages: number) { } } + // Create buttons for (let page = maxLeft; page <= maxRight; page++) { wrapper!.innerHTML += `` } @@ -95,12 +103,17 @@ function pageButtons(pages: number) { }) } - +// Load json data into table function async function loadIntoTable(table: any) { + // Display loader + $(".content").fadeOut(500); + $(".loader").fadeIn(500); + // Select table elements to populate let tableHead = table.querySelector("thead") let tableBody = table.querySelector("tbody") + // API calls for record amount and data let numRecords = await (await fetch('/recordCount')).json() let cnumRecords = numRecords - 1 let recordsLink = "/records?from=0&to=" + cnumRecords @@ -140,6 +153,11 @@ async function loadIntoTable(table: any) { tableBody.appendChild(rowElement) } pageButtons((await rows).pages) + + // Display content + console.log("page is finally fully loaded"); + $(".loader").fadeOut(500); + $(".content").fadeIn(500); } window.onload = () => { diff --git a/index.html b/index.html index 20ff6713..c2317918 100644 --- a/index.html +++ b/index.html @@ -8,25 +8,36 @@ -

Onboarding Project

-

- - - - - - - - -
-

Page

-
-
+
+
+
+
+

IMQS Onboarding Project

+

+
+
+ + +
+ +
+ + + +
+

Page

+
+
+
diff --git a/style.css b/style.css index 5988ab4b..f1cf47cf 100644 --- a/style.css +++ b/style.css @@ -1,9 +1,55 @@ +html { + font-size: 62.5%; + } + body { - /* overflow: hidden; Hide scrollbars */ - } + font-size: 16px; + font-size: 1.6rem; + min-height: 100%; + overflow: hidden; /* Hide scrollbars */ + background-color: #16191e; + color: #fdfdfd; +} +h1 { + font-size: 36px; + font-size: 3.6rem; +} + +/* Search ID and Show n records */ +.controls { + display: flex; + justify-content: center; +} + +.search-div { + margin: 1rem auto; + +} + +.drop-down { + margin: 1rem auto; + padding: 0.5rem; + text-align: center; +} + +.search-btn { + color: #fdfdfd; + padding: 0.5rem; + text-decoration: none; + border: solid 1px #45474b; + background-color: #45474b; +} + +.search-btn:hover:not(.selected) { + color: #1d1f20; + background-color: #cae00d; + border: solid 1px #cae00d; +} + +/* Table */ .table { - box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + box-shadow: 0 0 10px rgba(94, 102, 80, 0.918); border-collapse: collapse; /* overflow: hidden; */ font-weight: bold; @@ -13,8 +59,9 @@ body { } .table thead th { - background: #009578; - color: #ffff; + background: #cae00d; + color: #16191e; + opacity: 0.9; } .table td, @@ -26,20 +73,22 @@ body { } .table tbody tr:nth-of-type(even) { - background: #eeeeee; + background: #45474b; } .table tbody tr:last-of-type { - border-bottom: #009578; + border-bottom: #cae00d; } +/* Page n underneath table */ .page-num { - box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); - background: #009578; + color: #cae00d; font-weight: bold; + font-size: 2.4rem; text-align: center; } +/* Pagination buttons */ .container { padding: 1rem; margin: 1rem auto; @@ -53,11 +102,12 @@ body { } .btn { - color: black; + color: #fdfdfd; float: left; - padding: 8px 16px; + padding: 1rem; text-decoration: none; - border-collapse: collapse; + border: solid 1px #45474b; + background-color: #45474b; } .button:active{ @@ -67,7 +117,42 @@ body { } .btn:hover:not(.selected) { - color: #fdfdfd; - background-color: #009578; - border: solid 1px #009578; + color: #1d1f20; + background-color: #cae00d; + border: solid 1px #cae00d; +} + +/* Loader */ +.content { + display: none; +} + +.loader { + height: 100vh; + width: 100vw; + overflow: hidden; + background-color: #16191e; + position: absolute; + align-items: center; +} + +.loader>div{ + height: 6rem; + width: 6rem; + border: 15px solid #45474b; + border-top-color: #cae00d; + position: absolute; + margin: auto; + top: 0; + bottom: 0; + left: 0; + right: 0; + border-radius: 50%; + animation: spin 1.5s infinite linear; +} + +@keyframes spin { + 100%{ + transform: rotate(360deg); + } } From b128b1937dda6400ab728669ba40021d6c79c5f6 Mon Sep 17 00:00:00 2001 From: CelesteNaude <286celeste@gmail.com> Date: Sun, 27 Feb 2022 13:05:58 +0200 Subject: [PATCH 05/19] enhance performance (number records to fetch) --- app.ts | 86 +++++++++++++++++++++++++++++++++--------------------- index.html | 2 +- style.css | 2 +- 3 files changed, 55 insertions(+), 35 deletions(-) diff --git a/app.ts b/app.ts index 7a7788e2..b3fb3f63 100644 --- a/app.ts +++ b/app.ts @@ -1,19 +1,43 @@ -let state = { +const state = { 'page': 1, 'records': 15, 'window': 10 } +async function getData() { + // API calls for record count and headers + let numRecords = await (await fetch('/recordCount')).json() + let headers = await (await fetch('/columns')).json() + + return { + 'recordCount': numRecords, + 'headers': headers + } +} + // Search ID function -function searchFunction() { - // Get entered ID and calculate what page it is on +async function searchFunction() { let id = Number($('#id-search').val()) - let pageNum = Math.ceil((id + 1) / state.records) - // Set page to the one that the searched ID is on - state.page = pageNum - loadIntoTable(document.querySelector("table")) + // API calls for record amount + let dataInfo = getData() + let numRecords = (await dataInfo).recordCount - 1 + + if (id < 0 || id > numRecords || Number.isNaN(id)) { + // User info: Display error message + let pageInfo = document.getElementById('page-number') + pageInfo!.innerHTML = `

No records to display

` + } + else { + // Use entered ID to calculate what page it is on + let pageNum = Math.ceil((id + 1) / state.records) + + // Set page to the one that the searched ID is on + state.page = pageNum + + loadIntoTable(document.querySelector("table")) + } } // Select num records to display from drop down function @@ -25,21 +49,31 @@ function dropFunction() { } // Records to display in table function -async function pagination(tableData: any, numRecords: number, page: number, records: number) { +async function pagination(recordCount: number, page: number, records: number) { + let pages = Math.ceil(recordCount / records) + // Calculate where records to display should start and end let trimStart = (page - 1) * records - let trimEnd = trimStart + records + let trimEnd: number + if (page != pages) { + trimEnd = trimStart + records - 1 + } + else { + trimEnd = recordCount + } + + // Fetch only records that must be displayed on table + let recordsLink = "/records?from=" + trimStart + "&to=" + trimEnd + let tableData = await (await fetch(recordsLink)).json() - let trimmedData = tableData.slice(trimStart, trimEnd) - let pages = Math.ceil(numRecords / records) // User info: Display number of records and pages on window // TODO: create a global get element function let pageDet = document.getElementById('page-details') - pageDet!.innerHTML = `

There are ${numRecords + 1} records and ${pages} pages

` + pageDet!.innerHTML = `

There are ${recordCount + 1} records and ${pages} pages

` return { - 'data': trimmedData, + 'data': tableData, 'pages': pages } } @@ -48,13 +82,7 @@ async function pagination(tableData: any, numRecords: number, page: number, reco function pageButtons(pages: number) { // User info: Display current page number let pageNum = document.getElementById('page-number') - if (state.page) { - pageNum!.innerHTML = `

Page ${state.page}

` - } - else { - pageNum!.innerHTML = `

No records to display

` - } - + pageNum!.innerHTML = `

Page ${state.page}

` // Select element to create pagination buttons in let wrapper = document.getElementById('pagination-wrapper') @@ -113,19 +141,12 @@ async function loadIntoTable(table: any) { let tableHead = table.querySelector("thead") let tableBody = table.querySelector("tbody") - // API calls for record amount and data - let numRecords = await (await fetch('/recordCount')).json() - let cnumRecords = numRecords - 1 - let recordsLink = "/records?from=0&to=" + cnumRecords - let tableData = await (await fetch(recordsLink)).json() - - console.log('Records:', state.records) - - let rows = pagination(tableData, cnumRecords, state.page, state.records) - console.log('Data:', rows) + // API calls for record amount + let dataInfo = getData() + let cnumRecords = (await dataInfo).recordCount - 1 + let hearders = (await dataInfo).headers - // API call for column headers - let hearders = await (await fetch('/columns')).json() + let rows = pagination(cnumRecords, state.page, state.records) // Clear the table tableHead.innerHTML = "" @@ -155,7 +176,6 @@ async function loadIntoTable(table: any) { pageButtons((await rows).pages) // Display content - console.log("page is finally fully loaded"); $(".loader").fadeOut(500); $(".content").fadeIn(500); } diff --git a/index.html b/index.html index c2317918..24eb32aa 100644 --- a/index.html +++ b/index.html @@ -17,7 +17,7 @@

IMQS Onboarding Project

- +
-

IMQS Onboarding Project

-

+

IMQS Onboarding Project

+

-
- +
diff --git a/style.css b/style.css index 0dcc9b42..062bed29 100644 --- a/style.css +++ b/style.css @@ -1,3 +1,9 @@ +@media print { + body { + width: 100%; + } + } + html { font-size: 62.5%; } @@ -21,15 +27,12 @@ h1 { justify-content: center; } -.search-div { +.page-det { margin: 1rem auto; - } -.drop-down { +.search-div { margin: 1rem auto; - padding: 0.5rem; - text-align: center; } .search-btn { @@ -68,8 +71,8 @@ h1 { .table th { padding: 10px 20px; overflow: hidden; - text-overflow: ellipsis; - word-wrap: break-word; + text-overflow: clip; + white-space: nowrap; } .table tbody tr:nth-of-type(even) { From b4d2b64bd45d5a8e39a464d8b593fda82c79d99d Mon Sep 17 00:00:00 2001 From: CelesteNaude <286celeste@gmail.com> Date: Tue, 1 Mar 2022 20:33:49 +0200 Subject: [PATCH 07/19] add/delete rows when resizing window --- app.ts | 123 ++++++++++++++++++++++++++++++++++++++++------------- index.html | 2 +- style.css | 12 +++++- 3 files changed, 106 insertions(+), 31 deletions(-) diff --git a/app.ts b/app.ts index 925ad8c4..16796a0e 100644 --- a/app.ts +++ b/app.ts @@ -1,12 +1,15 @@ const state = { 'page': 1, - 'records': Math.ceil(window.innerHeight / 60), - 'window': 10 + 'records': Math.floor((window.innerHeight - 200) / 40), + 'window': 10, + 'trimStart': 0, + 'trimEnd': 10 } let RECORDCOUNT = 350 let HEADERS = ["ID", "City", "Population"] +let timeOutFunctionId: any function el(element: string) { return document.getElementById(element) @@ -16,18 +19,94 @@ async function getData() { // API calls for record count and headers RECORDCOUNT = await (await fetch('/recordCount')).json() HEADERS = await (await fetch('/columns')).json() - console.log("Changed to ", RECORDCOUNT, " and ", HEADERS) loadIntoTable(document.querySelector("table")) + console.log("The height of the window is: ", self.innerHeight) } // Bind to the resize event of the window object -window.addEventListener('resize', function (event) { - var newHeight = window.innerHeight; - state.records = Math.ceil(1000000 / newHeight) - console.log(state.records) +window.addEventListener('resize', function () { + let newHeight = Math.floor((window.innerHeight - 200) / 40); + let diff = Math.ceil(newHeight - state.records) + + console.log("Must be: ", newHeight) + console.log("Currently is: ", state.records) + + let table = document.querySelector("table") + let tableBody = table?.querySelector("tbody") + + // state.records = newHeight + let pages = Math.ceil(RECORDCOUNT / state.records) + pageButtons(pages) + + if (diff < 0) { + // Delete rows + console.log("Delete ", diff, " rows") + + console.log("Current record start: ", state.trimStart, " and end: ", state.trimEnd) + + deleteRows(state.records, diff) + + state.trimEnd = state.trimEnd + diff + console.log("After delete record start: ", state.trimStart, " and end: ", state.trimEnd) + state.records = newHeight + } + else if (diff > 0) { + // Add rows + console.log("Add ", diff, " rows") + + state.records = newHeight + + console.log("Current record start: ", state.trimStart, " and end: ", state.trimEnd) + let start = state.trimEnd + 1 + let end = state.trimEnd + diff + console.log("After record start: ", state.trimStart, " and end: ", end) + + let recordsLink = "/records?from=" + start + "&to=" + end + + addRows(recordsLink) + + state.trimEnd = state.trimEnd + diff + + + } + else { + console.log("Do nothing") + } + }) +async function addRows(link: string) { + let table = document.querySelector("table") + let tableBody = table?.querySelector("tbody") + let data = await (await fetch(link)).json(); + for (let row of data) { + let rowElement = document.createElement("tr") + + for (let cellText of row) { + let cellElement = document.createElement("td") + + cellElement.textContent = cellText + rowElement.appendChild(cellElement); + } + tableBody?.appendChild(rowElement) + } +} + +async function deleteRows(newHeight: number, diff: number) { + let table = document.querySelector("table") + let tableBody = table?.querySelector("tbody") + let num = newHeight - 1 + + console.log("start at ", newHeight) + + for (let i = num; i > (num + diff); i--) { + console.log("deleted a row") + tableBody!.deleteRow(i) + } + +} + // Search ID function async function searchFunction() { let id = Number($('#id-search').val()) @@ -55,27 +134,25 @@ async function pagination(recordCount: number, page: number, records: number) { let pages = Math.ceil(recordCount / records) // Calculate where records to display should start and end - let trimStart = (page - 1) * records - let trimEnd: number + state.trimStart = (page - 1) * records if (page != pages) { - trimEnd = trimStart + records - 1 + state.trimEnd = state.trimStart + records - 1 } else { - trimEnd = recordCount + state.trimEnd = recordCount } // Fetch only records that must be displayed on table - let recordsLink = "/records?from=" + trimStart + "&to=" + trimEnd - let tableData = await (await fetch(recordsLink)).json() + let recordsLink = "/records?from=" + state.trimStart + "&to=" + state.trimEnd + + addRows(recordsLink) // User info: Display number of records and pages on window - // TODO: Create a global get element function let pageDet = el('page-details') pageDet!.innerHTML = `

There are ${recordCount + 1} records and ${pages} pages

` return { - 'data': tableData, 'pages': pages } } @@ -136,7 +213,6 @@ function pageButtons(pages: number) { // Load json data into table function async function loadIntoTable(table: any) { - console.log("Records: ", RECORDCOUNT, " Headers: ", HEADERS) // Display loader $(".content").fadeOut(500); $(".loader").fadeIn(500); @@ -148,7 +224,7 @@ async function loadIntoTable(table: any) { let cnumRecords = RECORDCOUNT - 1 let hearders = HEADERS - let rows = pagination(cnumRecords, state.page, state.records) + // Clear the table tableHead.innerHTML = "" @@ -162,19 +238,8 @@ async function loadIntoTable(table: any) { tableHead.querySelector("tr").appendChild(headerElement) } - // Populate the rows - for (let row of (await rows).data) { - let rowElement = document.createElement("tr") - - for (let cellText of row) { - let cellElement = document.createElement("td") - - cellElement.textContent = cellText - rowElement.appendChild(cellElement); - } + let rows = pagination(cnumRecords, state.page, state.records) - tableBody.appendChild(rowElement) - } pageButtons((await rows).pages) // Display content diff --git a/index.html b/index.html index d11bbd73..f3ad51d8 100644 --- a/index.html +++ b/index.html @@ -24,9 +24,9 @@

IMQS Onboarding Project

-

Page

+

Page

diff --git a/style.css b/style.css index 062bed29..6edbc804 100644 --- a/style.css +++ b/style.css @@ -19,6 +19,13 @@ body { h1 { font-size: 36px; font-size: 3.6rem; + text-overflow: clip; + white-space: nowrap; +} + +.page-det { + text-overflow: clip; + white-space: nowrap; } /* Search ID and Show n records */ @@ -70,6 +77,7 @@ h1 { .table td, .table th { padding: 10px 20px; + height: 10px; overflow: hidden; text-overflow: clip; white-space: nowrap; @@ -88,7 +96,7 @@ h1 { color: #cae00d; font-weight: bold; font-size: 2.4rem; - text-align: center; + margin-left: 6rem; } /* Pagination buttons */ @@ -98,6 +106,8 @@ h1 { display: flex; justify-content: center; align-items: center; + position: absolute; + bottom: -2em; } .controls-item { From dce556753f182374f80880e11c1017f780c350af Mon Sep 17 00:00:00 2001 From: CelesteNaude <286celeste@gmail.com> Date: Wed, 2 Mar 2022 21:20:00 +0200 Subject: [PATCH 08/19] fixed table responsiveness errors --- app.ts | 195 ++++++++++++++++++++++++++++++----------------------- index.html | 9 +-- style.css | 94 +++++++++++++++----------- 3 files changed, 172 insertions(+), 126 deletions(-) diff --git a/app.ts b/app.ts index 16796a0e..b449341f 100644 --- a/app.ts +++ b/app.ts @@ -1,15 +1,15 @@ -const state = { +let state = { 'page': 1, - 'records': Math.floor((window.innerHeight - 200) / 40), + 'records': Math.floor((window.innerHeight - 160) / 40), 'window': 10, 'trimStart': 0, - 'trimEnd': 10 + 'trimEnd': 10, + 'countRec': 0 } let RECORDCOUNT = 350 let HEADERS = ["ID", "City", "Population"] -let timeOutFunctionId: any function el(element: string) { return document.getElementById(element) @@ -19,69 +19,43 @@ async function getData() { // API calls for record count and headers RECORDCOUNT = await (await fetch('/recordCount')).json() HEADERS = await (await fetch('/columns')).json() + + // Populate table with fetched data loadIntoTable(document.querySelector("table")) - console.log("The height of the window is: ", self.innerHeight) } -// Bind to the resize event of the window object -window.addEventListener('resize', function () { - let newHeight = Math.floor((window.innerHeight - 200) / 40); - let diff = Math.ceil(newHeight - state.records) - - console.log("Must be: ", newHeight) - console.log("Currently is: ", state.records) - - let table = document.querySelector("table") - let tableBody = table?.querySelector("tbody") - - // state.records = newHeight - let pages = Math.ceil(RECORDCOUNT / state.records) - pageButtons(pages) - - if (diff < 0) { - // Delete rows - console.log("Delete ", diff, " rows") - - console.log("Current record start: ", state.trimStart, " and end: ", state.trimEnd) +// Search ID function +async function searchFunction() { + let id = Number($('#id-search').val()) - deleteRows(state.records, diff) + let numRecords = RECORDCOUNT - state.trimEnd = state.trimEnd + diff - console.log("After delete record start: ", state.trimStart, " and end: ", state.trimEnd) - state.records = newHeight + if (id < 0 || id > numRecords || Number.isNaN(id)) { + // User info: Display error message + let pageInfo = el('page-number') + pageInfo!.innerHTML = `

No records to display

` } - else if (diff > 0) { - // Add rows - console.log("Add ", diff, " rows") - - state.records = newHeight - - console.log("Current record start: ", state.trimStart, " and end: ", state.trimEnd) - let start = state.trimEnd + 1 - let end = state.trimEnd + diff - console.log("After record start: ", state.trimStart, " and end: ", end) - - let recordsLink = "/records?from=" + start + "&to=" + end - - addRows(recordsLink) - - state.trimEnd = state.trimEnd + diff + else { + // Use entered ID to calculate what page it is on + console.log("Records for Id: ", state.records) + let pageNum = Math.floor(id / state.records + 1) + // Set page to the one that the searched ID is on + state.page = pageNum + loadIntoTable(el("table")) } - else { - console.log("Do nothing") - } - -}) +} +// Add rows to table async function addRows(link: string) { let table = document.querySelector("table") let tableBody = table?.querySelector("tbody") let data = await (await fetch(link)).json(); for (let row of data) { let rowElement = document.createElement("tr") + state.countRec += 1 for (let cellText of row) { let cellElement = document.createElement("td") @@ -93,13 +67,12 @@ async function addRows(link: string) { } } +// Delete rows from table async function deleteRows(newHeight: number, diff: number) { let table = document.querySelector("table") let tableBody = table?.querySelector("tbody") let num = newHeight - 1 - console.log("start at ", newHeight) - for (let i = num; i > (num + diff); i--) { console.log("deleted a row") tableBody!.deleteRow(i) @@ -107,33 +80,11 @@ async function deleteRows(newHeight: number, diff: number) { } -// Search ID function -async function searchFunction() { - let id = Number($('#id-search').val()) - - let numRecords = RECORDCOUNT - - if (id < 0 || id > numRecords || Number.isNaN(id)) { - // User info: Display error message - let pageInfo = el('page-number') - pageInfo!.innerHTML = `

No records to display

` - } - else { - // Use entered ID to calculate what page it is on - let pageNum = Math.ceil((id + 1) / state.records) - - // Set page to the one that the searched ID is on - state.page = pageNum - - loadIntoTable(el("table")) - } -} - // Records to display in table function async function pagination(recordCount: number, page: number, records: number) { - let pages = Math.ceil(recordCount / records) + let pages = Math.ceil((recordCount + 1) / records) - // Calculate where records to display should start and end + // Calculate where displayed records should start and end state.trimStart = (page - 1) * records if (page != pages) { state.trimEnd = state.trimStart + records - 1 @@ -145,12 +96,13 @@ async function pagination(recordCount: number, page: number, records: number) { // Fetch only records that must be displayed on table let recordsLink = "/records?from=" + state.trimStart + "&to=" + state.trimEnd + state.countRec = 0 addRows(recordsLink) - // User info: Display number of records and pages on window - let pageDet = el('page-details') - pageDet!.innerHTML = `

There are ${recordCount + 1} records and ${pages} pages

` + // User info: Display current page number + let pageNum = el('page-number') + pageNum!.innerHTML = `

Page ${state.page} of ${pages}

` return { 'pages': pages @@ -159,9 +111,6 @@ async function pagination(recordCount: number, page: number, records: number) { // Create paging buttons functions function pageButtons(pages: number) { - // User info: Display current page number - let pageNum = el('page-number') - pageNum!.innerHTML = `

Page ${state.page}

` // Select element to create pagination buttons in let wrapper = el('pagination-wrapper') @@ -224,8 +173,6 @@ async function loadIntoTable(table: any) { let cnumRecords = RECORDCOUNT - 1 let hearders = HEADERS - - // Clear the table tableHead.innerHTML = "" tableBody.innerHTML = "" @@ -238,8 +185,10 @@ async function loadIntoTable(table: any) { tableHead.querySelector("tr").appendChild(headerElement) } + // Add rows in pagination function let rows = pagination(cnumRecords, state.page, state.records) + // Create pagination buttons pageButtons((await rows).pages) // Display content @@ -247,6 +196,84 @@ async function loadIntoTable(table: any) { $(".content").fadeIn(500); } +// Add/remove rows from table based on resize event of the window +window.addEventListener('resize', function () { + // Calculate number rows to be added/deleted + let newHeight = Math.floor((window.innerHeight - 160) / 40) + let diff = newHeight - state.records + + let start = state.trimEnd + 1 + let end = state.trimEnd + diff + let pages = Math.ceil(RECORDCOUNT / state.records) + + + if (diff < 0 && state.countRec - 1 == newHeight && state.countRec != 1) { + // Delete rows from last page + deleteRows(state.countRec, diff) + + state.countRec = state.countRec + diff + state.trimEnd = state.trimEnd + diff + state.records = newHeight + state.page = Math.floor(state.trimEnd / (state.records - 1)) + + pages = Math.ceil(RECORDCOUNT / state.records) + pageButtons(pages) + } + else if (diff < 0 && state.page != pages && state.countRec - 1 >= newHeight) { + // Delete rows that are not on the last page + deleteRows(state.countRec, diff) + + state.countRec = state.countRec + diff + state.trimEnd = state.trimEnd + diff + state.records = newHeight + state.page = Math.floor(state.trimEnd / (state.records - 1)) + + pages = Math.ceil(RECORDCOUNT / state.records) + pageButtons(pages) + } + else if (diff > 0 && start <= RECORDCOUNT - 1) { + // Add rows if end of data is not yet reached + let recordsLink = "/records?from=" + start + "&to=" + end + addRows(recordsLink) + + state.trimEnd = state.trimEnd + diff + state.records = newHeight + state.page = Math.floor(state.trimEnd / (state.records - 1)) + + pages = Math.ceil(RECORDCOUNT / state.records) + pageButtons(pages) + } + else { + state.records = newHeight + let pages = Math.ceil(RECORDCOUNT / state.records) + pageButtons(pages) + } + +}) + + + window.onload = () => { getData() } + + + + + + + + + + + + +// o o +// /^^^^^7 +// ' ' ,oO))))))))Oo, +// ,'))))))))))))))), /{ +// ' ,'o ))))))))))))))))={ +// > ))))))))))))))))={ +// `, ))))))\ \)))))))={ +// ',))))))))\/)))))' \{ +// '*O))))))))O*' diff --git a/index.html b/index.html index f3ad51d8..295a5e41 100644 --- a/index.html +++ b/index.html @@ -13,9 +13,10 @@
-

IMQS Onboarding Project

-

-
+
+

IMQS Onboarding Project

+
+ @@ -25,7 +26,7 @@

IMQS Onboarding Project

-
+

Page

diff --git a/style.css b/style.css index 6edbc804..77d55f2b 100644 --- a/style.css +++ b/style.css @@ -1,8 +1,3 @@ -@media print { - body { - width: 100%; - } - } html { font-size: 62.5%; @@ -15,31 +10,31 @@ body { overflow: hidden; /* Hide scrollbars */ background-color: #16191e; color: #fdfdfd; -} -h1 { - font-size: 36px; - font-size: 3.6rem; - text-overflow: clip; - white-space: nowrap; + min-width: 300px; + min-width: 3.0; } -.page-det { +/* Controls above table*/ +.controls { + display: flex; text-overflow: clip; white-space: nowrap; } -/* Search ID and Show n records */ -.controls { - display: flex; - justify-content: center; +.constrols-heading { + width: 30%; } -.page-det { - margin: 1rem auto; +h1 { + font-size: 32px; + font-size: 3.2rem; } -.search-div { - margin: 1rem auto; +.constrols-search { + width: 70%; + display: flex; + justify-content: center; + padding: 2rem; } .search-btn { @@ -91,50 +86,73 @@ h1 { border-bottom: #cae00d; } -/* Page n underneath table */ -.page-num { - color: #cae00d; - font-weight: bold; - font-size: 2.4rem; - margin-left: 6rem; -} - -/* Pagination buttons */ +/* Controls underneath table */ .container { padding: 1rem; margin: 1rem auto; + width: 100%; display: flex; justify-content: center; align-items: center; position: absolute; bottom: -2em; + text-overflow: clip; + white-space: nowrap; + +} + +/* Page n underneath table */ +.page-num { + color: #cae00d; + font-size: 2.4rem; + margin: auto; + width: 30%; + text-align: center; + padding: 1rem; } -.controls-item { - display: inline-block; +/* Pagination buttons */ +.pagination-wrapper { + width: 70%; + overflow-x: auto; } .btn { color: #fdfdfd; - float: left; + /* float: left; */ padding: 1rem; text-decoration: none; border: solid 1px #45474b; background-color: #45474b; } -.button:active{ - color: #fdfdfd; - background-color: #1d1f20; - border: solid 1px #1d1f20; -} - .btn:hover:not(.selected) { color: #1d1f20; background-color: #cae00d; border: solid 1px #cae00d; + cursor: pointer; } + /* width */ + ::-webkit-scrollbar { + height: 10px; + } + + /* Track */ + ::-webkit-scrollbar-track { + background: #16191e; + } + + /* Handle */ + ::-webkit-scrollbar-thumb { + background: #888; + } + + /* Handle on hover */ + ::-webkit-scrollbar-thumb:hover { + background: #555; + } + /* Loader */ .content { display: none; From 3e48f44ed731388b36021f9f9e0cd90b97ce4768 Mon Sep 17 00:00:00 2001 From: CelesteNaude <286celeste@gmail.com> Date: Thu, 3 Mar 2022 23:53:12 +0200 Subject: [PATCH 09/19] added debounce and different pagination --- app.ts | 392 ++++++++++++++++++++++++++++++++--------------------- index.html | 15 +- style.css | 13 +- 3 files changed, 259 insertions(+), 161 deletions(-) diff --git a/app.ts b/app.ts index b449341f..bd43d1db 100644 --- a/app.ts +++ b/app.ts @@ -1,260 +1,344 @@ let state = { - 'page': 1, - 'records': Math.floor((window.innerHeight - 160) / 40), - 'window': 10, + 'records': Math.floor((window.innerHeight - 160) / 40), // Estimate of available table space 'trimStart': 0, 'trimEnd': 10, 'countRec': 0 } -let RECORDCOUNT = 350 -let HEADERS = ["ID", "City", "Population"] +// These are 'technically' constants +let RECORDCOUNT = 350; +let HEADERS = ["ID", "City", "Population"]; + +// 'Global' get element function el(element: string) { - return document.getElementById(element) + return document.getElementById(element); } + +// Fetch headers and record count async function getData() { // API calls for record count and headers - RECORDCOUNT = await (await fetch('/recordCount')).json() - HEADERS = await (await fetch('/columns')).json() + RECORDCOUNT = await (await fetch('/recordCount')).json(); + HEADERS = await (await fetch('/columns')).json(); // Populate table with fetched data - loadIntoTable(document.querySelector("table")) + loadIntoTable(el('content-table')); } -// Search ID function +// Search entered ID async function searchFunction() { - let id = Number($('#id-search').val()) + let id = Number($('#id-search').val()); + let pageInfo = el('page-number'); + let numRecords = RECORDCOUNT; - let numRecords = RECORDCOUNT + pageInfo!.innerHTML = `

`; if (id < 0 || id > numRecords || Number.isNaN(id)) { // User info: Display error message - let pageInfo = el('page-number') - pageInfo!.innerHTML = `

No records to display

` + pageInfo!.innerHTML = `

No records to display

`; } else { // Use entered ID to calculate what page it is on - console.log("Records for Id: ", state.records) - let pageNum = Math.floor(id / state.records + 1) - - // Set page to the one that the searched ID is on - state.page = pageNum - - loadIntoTable(el("table")) + if ((RECORDCOUNT - 1) - id >= state.records) { + state.trimStart = id; + state.trimEnd = state.trimStart + (state.records - 1); + } + else { + state.trimEnd = RECORDCOUNT - 1; + state.trimStart = state.trimEnd - state.records + 1; + } + loadIntoTable(el("table")); } } + // Add rows to table async function addRows(link: string) { - let table = document.querySelector("table") - let tableBody = table?.querySelector("tbody") + let table = el("content-table"); + let tableBody = table?.querySelector("tbody"); + let data = await (await fetch(link)).json(); + for (let row of data) { + let rowElement = document.createElement("tr"); + state.countRec += 1; + + for (let cellText of row) { + let cellElement = document.createElement("td"); + + cellElement.textContent = cellText; + rowElement.appendChild(cellElement); // Append cells + } + tableBody?.appendChild(rowElement); // Append rows + } +} + + +// Prepend rows to table +async function prependRows(link: string) { + let table = el("content-table"); + let tableBody = table?.querySelector("tbody"); let data = await (await fetch(link)).json(); for (let row of data) { - let rowElement = document.createElement("tr") - state.countRec += 1 + let rowElement = document.createElement("tr"); + state.countRec += 1; for (let cellText of row) { - let cellElement = document.createElement("td") + let cellElement = document.createElement("td"); - cellElement.textContent = cellText + cellElement.textContent = cellText; rowElement.appendChild(cellElement); } - tableBody?.appendChild(rowElement) + tableBody?.prepend(rowElement); // Prepend rows } } + // Delete rows from table async function deleteRows(newHeight: number, diff: number) { - let table = document.querySelector("table") - let tableBody = table?.querySelector("tbody") + let table = el("content-table"); + let tableBody = table?.querySelector("tbody"); let num = newHeight - 1 for (let i = num; i > (num + diff); i--) { - console.log("deleted a row") - tableBody!.deleteRow(i) + tableBody!.deleteRow(i); } - } -// Records to display in table function -async function pagination(recordCount: number, page: number, records: number) { - let pages = Math.ceil((recordCount + 1) / records) - // Calculate where displayed records should start and end - state.trimStart = (page - 1) * records - if (page != pages) { - state.trimEnd = state.trimStart + records - 1 +// Load json data into table function +async function loadIntoTable(table: any) { + + // Display loader + $(".content").fadeOut(500); + $(".loader").fadeIn(500); + + // UI "Aesthetic": update buttons + el('first')?.removeAttribute("disabled"); + el('prev')?.removeAttribute("disabled"); + el('next')?.removeAttribute("disabled"); + el('last')?.removeAttribute("disabled"); + + if (state.trimEnd == RECORDCOUNT - 1) { + el('last')?.setAttribute("disabled", "disabled"); + el('next')?.setAttribute("disabled", "disabled"); } - else { - state.trimEnd = recordCount + + if (state.trimStart == 0) { + el('first')?.setAttribute("disabled", "disabled"); + el('prev')?.setAttribute("disabled", "disabled"); } - // Fetch only records that must be displayed on table - let recordsLink = "/records?from=" + state.trimStart + "&to=" + state.trimEnd + // Select table elements to populate + let tableHead = el("content-thead"); + let tableBody = el("content-tbody"); - state.countRec = 0 - addRows(recordsLink) + let hearders = HEADERS; + // Clear the table + tableHead!.innerHTML = ""; + tableBody!.innerHTML = ""; - // User info: Display current page number - let pageNum = el('page-number') - pageNum!.innerHTML = `

Page ${state.page} of ${pages}

` + // Populate the headers + for (let headerText of hearders) { + let headerElement = document.createElement("th"); - return { - 'pages': pages + headerElement.textContent = headerText; + tableHead!.querySelector("tr")!.appendChild(headerElement); } + + // Fetch only records that must be displayed on table + let recordsLink = "/records?from=" + state.trimStart + "&to=" + state.trimEnd; + + state.countRec = 0; + addRows(recordsLink); + + // Display content + $(".loader").fadeOut(500); + $(".content").fadeIn(500); } -// Create paging buttons functions -function pageButtons(pages: number) { - // Select element to create pagination buttons in - let wrapper = el('pagination-wrapper') - wrapper!.innerHTML = "" +// Code is only triggered once per user input +const debounce = (fn: Function, ms = 300) => { + let timeoutId: ReturnType; + return function (this: any, ...args: any[]) { + clearTimeout(timeoutId); + timeoutId = setTimeout(() => fn.apply(this, args), ms); + }; +}; - let maxLeft = (state.page - Math.floor(state.window / 2)) - let maxRight = (state.page + Math.floor(state.window / 2)) - // Button numbers must not go below 1 - if (maxLeft < 1) { - maxLeft = 1 - maxRight = state.window - } +// Calculate what data should be fetch when page buttons are clicked +function pageFunction(btnName: string) { + let isValid = false - // Button numbers cannot exceed max number of pages - if (maxRight > pages) { - maxLeft = pages - (state.window - 1) - maxRight = pages + // Set trim to start of data + if (btnName == "first" && state.trimStart != 0) { + isValid = true; + state.trimStart = 0; + state.trimEnd = state.trimStart + state.records - 1; + } - if (maxLeft < 1) { - maxLeft = 1 + // Set trim to previous data + if (btnName == "prev" && state.trimStart != 0) { + // If previous page is end of data && there are not enough records to fill window + if ((state.trimStart - 1) - (state.records - 1) < 0) { + state.trimStart = 0; + state.trimEnd = state.trimStart + state.records - 1; } - } + else { + state.trimEnd = state.trimStart - 1; + state.trimStart = state.trimEnd - state.records + 1; + } + isValid = true; - // Create buttons - for (let page = maxLeft; page <= maxRight; page++) { - wrapper!.innerHTML += `` } - // If the current page is not 1 -> add '<< First' button - if (state.page != 1) { - wrapper!.innerHTML = `` + wrapper!.innerHTML + // Set trim to next data + if (btnName == "next" && state.trimEnd != RECORDCOUNT - 1) { + // If next page is end of data && there are not enough records to fill window + if ((RECORDCOUNT - 1) - (state.trimEnd + 1) < state.records) { + state.trimEnd = RECORDCOUNT - 1; + state.trimStart = state.trimEnd - state.records + 1; + } + else { + state.trimStart = state.trimEnd + 1; + state.trimEnd = state.trimStart + state.records - 1; + } + isValid = true; } - // If the current page is not the last page -> add 'Last >>' button - if (state.page != pages) { - wrapper!.innerHTML += `` + // Set trim to end of data + if (btnName == "last" && state.trimEnd != RECORDCOUNT - 1) { + isValid = true; + state.trimEnd = RECORDCOUNT - 1; + state.trimStart = state.trimEnd - state.records + 1; } - $('.page').on('click', function () { - - state.page = Number($(this).val()) + if (isValid) { + loadIntoTable(el("table")); + } + else { + console.log("Grey out"); + } +} - loadIntoTable(el("table")) - }) +// Last resort debounce application for buttons +function inputFirst() { + pageFunction('first'); +} +function inputPrev() { + pageFunction('prev'); +} +function inputNext() { + pageFunction('next'); } +function inputLast() { + pageFunction('last'); +} +const clickFirst = debounce(() => inputFirst(), 600); +const clickPrev = debounce(() => inputPrev(), 600); +const clickNext = debounce(() => inputNext(), 600); +const clickLast = debounce(() => inputLast(), 600); -// Load json data into table function -async function loadIntoTable(table: any) { - // Display loader - $(".content").fadeOut(500); - $(".loader").fadeIn(500); +// Add/remove rows from table based on resize event of the window +window.addEventListener("resize", debounce(() => { - // Select table elements to populate - let tableHead = table.querySelector("thead") - let tableBody = table.querySelector("tbody") + // Calculate number rows to be added/deleted + let newHeight = Math.floor((window.innerHeight - 160) / 40); + let diff = newHeight - state.records; - let cnumRecords = RECORDCOUNT - 1 - let hearders = HEADERS + let start = state.trimEnd + 1; + let end = state.trimEnd + diff; - // Clear the table - tableHead.innerHTML = "" - tableBody.innerHTML = "" - // Populate the headers - for (let headerText of hearders) { - let headerElement = document.createElement("th") + if (diff < 0) { + // Delete rows from last page + deleteRows(state.countRec, diff); - headerElement.textContent = headerText; - tableHead.querySelector("tr").appendChild(headerElement) + state.countRec = state.countRec + diff; + state.trimEnd = state.trimEnd + diff; + state.records = newHeight; } + else if (diff > 0 && state.trimEnd == RECORDCOUNT - 1) { + // Prepend rows as last page gets bigger + end = state.trimStart - 1; + start = state.trimStart - diff; - // Add rows in pagination function - let rows = pagination(cnumRecords, state.page, state.records) - // Create pagination buttons - pageButtons((await rows).pages) - - // Display content - $(".loader").fadeOut(500); - $(".content").fadeIn(500); -} - -// Add/remove rows from table based on resize event of the window -window.addEventListener('resize', function () { - // Calculate number rows to be added/deleted - let newHeight = Math.floor((window.innerHeight - 160) / 40) - let diff = newHeight - state.records - - let start = state.trimEnd + 1 - let end = state.trimEnd + diff - let pages = Math.ceil(RECORDCOUNT / state.records) + for (let i = end; i >= start; i--) { + let recordsLink = "/records?from=" + i + "&to=" + i; + prependRows(recordsLink); + } - if (diff < 0 && state.countRec - 1 == newHeight && state.countRec != 1) { - // Delete rows from last page - deleteRows(state.countRec, diff) + state.trimStart = state.trimStart + diff; + state.records = newHeight; - state.countRec = state.countRec + diff - state.trimEnd = state.trimEnd + diff - state.records = newHeight - state.page = Math.floor(state.trimEnd / (state.records - 1)) - - pages = Math.ceil(RECORDCOUNT / state.records) - pageButtons(pages) } - else if (diff < 0 && state.page != pages && state.countRec - 1 >= newHeight) { - // Delete rows that are not on the last page - deleteRows(state.countRec, diff) - - state.countRec = state.countRec + diff - state.trimEnd = state.trimEnd + diff - state.records = newHeight - state.page = Math.floor(state.trimEnd / (state.records - 1)) + else if (diff > 0 && end >= RECORDCOUNT) { + let addEnd = (RECORDCOUNT - 1) - state.trimEnd; + end = RECORDCOUNT - 1; + start = end - addEnd + 1; + let recordsLink = "/records?from=" + start + "&to=" + end; + addRows(recordsLink); + console.log("Start ", start, " and end ", end); + + let addTop = diff - addEnd; + end = state.trimStart - 1; + start = state.trimStart - addTop; + + for (let i = end; i >= start; i--) { + let recordsLink = "/records?from=" + i + "&to=" + i; + prependRows(recordsLink); + } + console.log("Start ", start, " and end ", end); - pages = Math.ceil(RECORDCOUNT / state.records) - pageButtons(pages) + state.trimEnd = RECORDCOUNT - 1; + state.trimStart = state.trimEnd - (newHeight - 1) + state.records = newHeight; } else if (diff > 0 && start <= RECORDCOUNT - 1) { // Add rows if end of data is not yet reached - let recordsLink = "/records?from=" + start + "&to=" + end - addRows(recordsLink) - - state.trimEnd = state.trimEnd + diff - state.records = newHeight - state.page = Math.floor(state.trimEnd / (state.records - 1)) + let recordsLink = "/records?from=" + start + "&to=" + end; + addRows(recordsLink); - pages = Math.ceil(RECORDCOUNT / state.records) - pageButtons(pages) + state.trimEnd = state.trimEnd + diff; + state.records = newHeight; } else { - state.records = newHeight - let pages = Math.ceil(RECORDCOUNT / state.records) - pageButtons(pages) + state.records = newHeight; } -}) + // UI "Aesthetic": update buttons + el('first')?.removeAttribute("disabled"); + el('prev')?.removeAttribute("disabled"); + el('next')?.removeAttribute("disabled"); + el('last')?.removeAttribute("disabled"); + if (state.trimEnd == RECORDCOUNT - 1) { + el('last')?.setAttribute("disabled", "disabled"); + el('next')?.setAttribute("disabled", "disabled"); + } + + if (state.trimStart == 0) { + el('first')?.setAttribute("disabled", "disabled"); + el('prev')?.setAttribute("disabled", "disabled"); + } +}, 100) +); // Log window dimensions at most every 100ms window.onload = () => { - getData() + state.trimStart = 0 + state.trimEnd = state.trimStart + state.records - 1; + el('first')?.setAttribute("disabled", "disabled"); + el('prev')?.setAttribute("disabled", "disabled"); + getData(); } diff --git a/index.html b/index.html index 295a5e41..ca8a0b3c 100644 --- a/index.html +++ b/index.html @@ -21,13 +21,18 @@

IMQS Onboarding Project

- - - +
+ +
-
-

Page

+
+ + + + +
+

diff --git a/style.css b/style.css index 77d55f2b..174c1c1a 100644 --- a/style.css +++ b/style.css @@ -95,9 +95,10 @@ h1 { justify-content: center; align-items: center; position: absolute; - bottom: -2em; + bottom: -1rem; text-overflow: clip; white-space: nowrap; + background-color: #16191e; } @@ -115,6 +116,7 @@ h1 { .pagination-wrapper { width: 70%; overflow-x: auto; + margin-left: 1rem; } .btn { @@ -126,13 +128,20 @@ h1 { background-color: #45474b; } -.btn:hover:not(.selected) { +.btn:hover:not(.btn:disabled) { color: #1d1f20; background-color: #cae00d; border: solid 1px #cae00d; cursor: pointer; } +.btn:disabled, +.btn[disabled]{ + border: 1px solid #999999; + background-color: #cccccc; + color: #666666; +} + /* width */ ::-webkit-scrollbar { height: 10px; From b0bd9c0c30aef5d7d253bd9dca8f0075a0749e97 Mon Sep 17 00:00:00 2001 From: CelesteNaude <286celeste@gmail.com> Date: Fri, 4 Mar 2022 10:06:38 +0200 Subject: [PATCH 10/19] fixed add records --- app.ts | 61 +++++++++++++++++++++++++++++-------------------------- style.css | 1 - 2 files changed, 32 insertions(+), 30 deletions(-) diff --git a/app.ts b/app.ts index bd43d1db..6c0a9363 100644 --- a/app.ts +++ b/app.ts @@ -30,13 +30,13 @@ async function getData() { // Search entered ID async function searchFunction() { + let idString = $('#id-search').val() let id = Number($('#id-search').val()); let pageInfo = el('page-number'); - let numRecords = RECORDCOUNT; + let numRecords = RECORDCOUNT - 1; - pageInfo!.innerHTML = `

`; - if (id < 0 || id > numRecords || Number.isNaN(id)) { + if (id < 0 || id > numRecords || Number.isNaN(id) || idString == "") { // User info: Display error message pageInfo!.innerHTML = `

No records to display

`; } @@ -111,8 +111,8 @@ async function deleteRows(newHeight: number, diff: number) { async function loadIntoTable(table: any) { // Display loader - $(".content").fadeOut(500); - $(".loader").fadeIn(500); + $(".content").fadeOut(200); + $(".loader").fadeIn(200); // UI "Aesthetic": update buttons el('first')?.removeAttribute("disabled"); @@ -130,6 +130,9 @@ async function loadIntoTable(table: any) { el('prev')?.setAttribute("disabled", "disabled"); } + let pageInfo = el('page-number'); + pageInfo!.innerHTML = `

`; + // Select table elements to populate let tableHead = el("content-thead"); let tableBody = el("content-tbody"); @@ -155,21 +158,11 @@ async function loadIntoTable(table: any) { addRows(recordsLink); // Display content - $(".loader").fadeOut(500); - $(".content").fadeIn(500); + $(".loader").fadeOut(200); + $(".content").fadeIn(200); } -// Code is only triggered once per user input -const debounce = (fn: Function, ms = 300) => { - let timeoutId: ReturnType; - return function (this: any, ...args: any[]) { - clearTimeout(timeoutId); - timeoutId = setTimeout(() => fn.apply(this, args), ms); - }; -}; - - // Calculate what data should be fetch when page buttons are clicked function pageFunction(btnName: string) { let isValid = false @@ -223,9 +216,20 @@ function pageFunction(btnName: string) { else { console.log("Grey out"); } + } +// Code is only triggered once per user input +const debounce = (fn: Function, ms: number) => { + let timeoutId: ReturnType; + return function (this: any, ...args: any[]) { + clearTimeout(timeoutId); + timeoutId = setTimeout(() => fn.apply(this, args), ms); + }; +}; + + // Last resort debounce application for buttons function inputFirst() { pageFunction('first'); @@ -239,14 +243,14 @@ function inputNext() { function inputLast() { pageFunction('last'); } -const clickFirst = debounce(() => inputFirst(), 600); -const clickPrev = debounce(() => inputPrev(), 600); -const clickNext = debounce(() => inputNext(), 600); -const clickLast = debounce(() => inputLast(), 600); +const clickFirst = debounce(() => inputFirst(), 800); +const clickPrev = debounce(() => inputPrev(), 800); +const clickNext = debounce(() => inputNext(), 800); +const clickLast = debounce(() => inputLast(), 800); // Add/remove rows from table based on resize event of the window -window.addEventListener("resize", debounce(() => { +window.addEventListener("resize", debounce(async () => { // Calculate number rows to be added/deleted let newHeight = Math.floor((window.innerHeight - 160) / 40); @@ -266,17 +270,18 @@ window.addEventListener("resize", debounce(() => { } else if (diff > 0 && state.trimEnd == RECORDCOUNT - 1) { // Prepend rows as last page gets bigger + let timeoutId: ReturnType; + end = state.trimStart - 1; start = state.trimStart - diff; - for (let i = end; i >= start; i--) { let recordsLink = "/records?from=" + i + "&to=" + i; - prependRows(recordsLink); + await prependRows(recordsLink); } - state.trimStart = state.trimStart + diff; + state.trimStart = state.trimStart - diff; state.records = newHeight; } @@ -286,7 +291,6 @@ window.addEventListener("resize", debounce(() => { start = end - addEnd + 1; let recordsLink = "/records?from=" + start + "&to=" + end; addRows(recordsLink); - console.log("Start ", start, " and end ", end); let addTop = diff - addEnd; end = state.trimStart - 1; @@ -294,12 +298,11 @@ window.addEventListener("resize", debounce(() => { for (let i = end; i >= start; i--) { let recordsLink = "/records?from=" + i + "&to=" + i; - prependRows(recordsLink); + await prependRows(recordsLink); } - console.log("Start ", start, " and end ", end); state.trimEnd = RECORDCOUNT - 1; - state.trimStart = state.trimEnd - (newHeight - 1) + state.trimStart = state.trimStart - addTop; state.records = newHeight; } else if (diff > 0 && start <= RECORDCOUNT - 1) { diff --git a/style.css b/style.css index 174c1c1a..07a2c1c7 100644 --- a/style.css +++ b/style.css @@ -109,7 +109,6 @@ h1 { margin: auto; width: 30%; text-align: center; - padding: 1rem; } /* Pagination buttons */ From 2fdaee1a9f0dbf353f7cb42ed440bc9ce0d43132 Mon Sep 17 00:00:00 2001 From: CelesteNaude <286celeste@gmail.com> Date: Mon, 7 Mar 2022 10:50:19 +0200 Subject: [PATCH 11/19] Fixed global variables and repetitive code --- app.ts | 262 +++++++++++++++++++++++++++-------------------------- index.html | 2 +- style.css | 38 ++++---- 3 files changed, 153 insertions(+), 149 deletions(-) diff --git a/app.ts b/app.ts index 6c0a9363..028f0cba 100644 --- a/app.ts +++ b/app.ts @@ -1,38 +1,45 @@ -let state = { - 'records': Math.floor((window.innerHeight - 160) / 40), // Estimate of available table space - 'trimStart': 0, - 'trimEnd': 10, - 'countRec': 0 -} +let records = Math.floor((window.innerHeight - 160) / 40); // Estimate of available table space +let trimStart: number; +let trimEnd: number; +let countRec: number; +let isAppend: boolean; +// Variables fetched once with load of window +let RECORDCOUNT: number; +let HEADERS: string[]; -// These are 'technically' constants -let RECORDCOUNT = 350; -let HEADERS = ["ID", "City", "Population"]; +// Global document elements +let contentTable: HTMLElement | null; +let tableBody: HTMLTableSectionElement | null; +let pageInfo: HTMLElement | null; +let firstBtn: HTMLElement | null; +let prevBtn: HTMLElement | null; +let nextBtn: HTMLElement | null; +let lastBtn: HTMLElement | null; +let tableHead: HTMLElement | null; +let inputBox: HTMLElement | null; -// 'Global' get element -function el(element: string) { - return document.getElementById(element); -} // Fetch headers and record count async function getData() { // API calls for record count and headers - RECORDCOUNT = await (await fetch('/recordCount')).json(); - HEADERS = await (await fetch('/columns')).json(); + RECORDCOUNT = await fetch('/recordCount') + .then(resp => resp.json()); + HEADERS = await fetch('/columns') + .then(resp => resp.json()); // Populate table with fetched data - loadIntoTable(el('content-table')); + loadIntoTable(contentTable); } +// TODO Pierre's changes // Search entered ID async function searchFunction() { let idString = $('#id-search').val() let id = Number($('#id-search').val()); - let pageInfo = el('page-number'); let numRecords = RECORDCOUNT - 1; @@ -41,28 +48,29 @@ async function searchFunction() { pageInfo!.innerHTML = `

No records to display

`; } else { - // Use entered ID to calculate what page it is on - if ((RECORDCOUNT - 1) - id >= state.records) { - state.trimStart = id; - state.trimEnd = state.trimStart + (state.records - 1); + // Use entered ID to calculate what records should display + if ((RECORDCOUNT - 1) - id >= records) { + trimStart = id; + trimEnd = trimStart + (records - 1); } else { - state.trimEnd = RECORDCOUNT - 1; - state.trimStart = state.trimEnd - state.records + 1; + trimEnd = RECORDCOUNT - 1; + trimStart = trimEnd - records + 1; } - loadIntoTable(el("table")); + loadIntoTable(contentTable); } + (inputBox).value = ''; } // Add rows to table async function addRows(link: string) { - let table = el("content-table"); - let tableBody = table?.querySelector("tbody"); - let data = await (await fetch(link)).json(); + let data = await fetch(link) + .then(resp => resp.json()); + for (let row of data) { let rowElement = document.createElement("tr"); - state.countRec += 1; + countRec += 1; for (let cellText of row) { let cellElement = document.createElement("td"); @@ -70,36 +78,20 @@ async function addRows(link: string) { cellElement.textContent = cellText; rowElement.appendChild(cellElement); // Append cells } - tableBody?.appendChild(rowElement); // Append rows - } -} - - -// Prepend rows to table -async function prependRows(link: string) { - let table = el("content-table"); - let tableBody = table?.querySelector("tbody"); - let data = await (await fetch(link)).json(); - for (let row of data) { - let rowElement = document.createElement("tr"); - state.countRec += 1; - - for (let cellText of row) { - let cellElement = document.createElement("td"); - - cellElement.textContent = cellText; - rowElement.appendChild(cellElement); + if (isAppend) { + tableBody!.appendChild(rowElement); // Append rows } - tableBody?.prepend(rowElement); // Prepend rows + else { + tableBody?.prepend(rowElement); /**Prepend rows*/ + } + } } // Delete rows from table async function deleteRows(newHeight: number, diff: number) { - let table = el("content-table"); - let tableBody = table?.querySelector("tbody"); - let num = newHeight - 1 + let num = newHeight - 1; for (let i = num; i > (num + diff); i--) { tableBody!.deleteRow(i); @@ -115,36 +107,29 @@ async function loadIntoTable(table: any) { $(".loader").fadeIn(200); // UI "Aesthetic": update buttons - el('first')?.removeAttribute("disabled"); - el('prev')?.removeAttribute("disabled"); - el('next')?.removeAttribute("disabled"); - el('last')?.removeAttribute("disabled"); - - if (state.trimEnd == RECORDCOUNT - 1) { - el('last')?.setAttribute("disabled", "disabled"); - el('next')?.setAttribute("disabled", "disabled"); + firstBtn?.removeAttribute("disabled"); + prevBtn?.removeAttribute("disabled"); + nextBtn?.removeAttribute("disabled"); + lastBtn?.removeAttribute("disabled"); + + if (trimEnd == RECORDCOUNT - 1) { + lastBtn?.setAttribute("disabled", "disabled"); + nextBtn?.setAttribute("disabled", "disabled"); } - if (state.trimStart == 0) { - el('first')?.setAttribute("disabled", "disabled"); - el('prev')?.setAttribute("disabled", "disabled"); + if (trimStart == 0) { + firstBtn?.setAttribute("disabled", "disabled"); + prevBtn?.setAttribute("disabled", "disabled"); } - let pageInfo = el('page-number'); pageInfo!.innerHTML = `

`; - // Select table elements to populate - let tableHead = el("content-thead"); - let tableBody = el("content-tbody"); - - let hearders = HEADERS; - // Clear the table tableHead!.innerHTML = ""; tableBody!.innerHTML = ""; // Populate the headers - for (let headerText of hearders) { + for (let headerText of HEADERS) { let headerElement = document.createElement("th"); headerElement.textContent = headerText; @@ -152,9 +137,10 @@ async function loadIntoTable(table: any) { } // Fetch only records that must be displayed on table - let recordsLink = "/records?from=" + state.trimStart + "&to=" + state.trimEnd; + let recordsLink = "/records?from=" + trimStart + "&to=" + trimEnd; - state.countRec = 0; + countRec = 0; + isAppend = true; addRows(recordsLink); // Display content @@ -163,55 +149,56 @@ async function loadIntoTable(table: any) { } +// TODO Divide function into onclick events // Calculate what data should be fetch when page buttons are clicked function pageFunction(btnName: string) { let isValid = false // Set trim to start of data - if (btnName == "first" && state.trimStart != 0) { + if (btnName == "first" && trimStart != 0) { isValid = true; - state.trimStart = 0; - state.trimEnd = state.trimStart + state.records - 1; + trimStart = 0; + trimEnd = trimStart + records - 1; } // Set trim to previous data - if (btnName == "prev" && state.trimStart != 0) { + if (btnName == "prev" && trimStart != 0) { // If previous page is end of data && there are not enough records to fill window - if ((state.trimStart - 1) - (state.records - 1) < 0) { - state.trimStart = 0; - state.trimEnd = state.trimStart + state.records - 1; + if ((trimStart - 1) - (records - 1) < 0) { + trimStart = 0; + trimEnd = trimStart + records - 1; } else { - state.trimEnd = state.trimStart - 1; - state.trimStart = state.trimEnd - state.records + 1; + trimEnd = trimStart - 1; + trimStart = trimEnd - records + 1; } isValid = true; } // Set trim to next data - if (btnName == "next" && state.trimEnd != RECORDCOUNT - 1) { + if (btnName == "next" && trimEnd != RECORDCOUNT - 1) { // If next page is end of data && there are not enough records to fill window - if ((RECORDCOUNT - 1) - (state.trimEnd + 1) < state.records) { - state.trimEnd = RECORDCOUNT - 1; - state.trimStart = state.trimEnd - state.records + 1; + if ((RECORDCOUNT - 1) - (trimEnd + 1) < records) { + trimEnd = RECORDCOUNT - 1; + trimStart = trimEnd - records + 1; } else { - state.trimStart = state.trimEnd + 1; - state.trimEnd = state.trimStart + state.records - 1; + trimStart = trimEnd + 1; + trimEnd = trimStart + records - 1; } isValid = true; } // Set trim to end of data - if (btnName == "last" && state.trimEnd != RECORDCOUNT - 1) { + if (btnName == "last" && trimEnd != RECORDCOUNT - 1) { isValid = true; - state.trimEnd = RECORDCOUNT - 1; - state.trimStart = state.trimEnd - state.records + 1; + trimEnd = RECORDCOUNT - 1; + trimStart = trimEnd - records + 1; } if (isValid) { - loadIntoTable(el("table")); + loadIntoTable(contentTable); } else { console.log("Grey out"); @@ -251,96 +238,113 @@ const clickLast = debounce(() => inputLast(), 800); // Add/remove rows from table based on resize event of the window window.addEventListener("resize", debounce(async () => { + isAppend = false; // Calculate number rows to be added/deleted let newHeight = Math.floor((window.innerHeight - 160) / 40); - let diff = newHeight - state.records; + let diff = newHeight - records; - let start = state.trimEnd + 1; - let end = state.trimEnd + diff; + let start = trimEnd + 1; + let end = trimEnd + diff; if (diff < 0) { // Delete rows from last page - deleteRows(state.countRec, diff); + deleteRows(countRec, diff); - state.countRec = state.countRec + diff; - state.trimEnd = state.trimEnd + diff; - state.records = newHeight; + countRec = countRec + diff; + trimEnd = trimEnd + diff; + records = newHeight; } - else if (diff > 0 && state.trimEnd == RECORDCOUNT - 1) { + else if (diff > 0 && trimEnd == RECORDCOUNT - 1) { // Prepend rows as last page gets bigger let timeoutId: ReturnType; - end = state.trimStart - 1; - start = state.trimStart - diff; + end = trimStart - 1; + start = trimStart - diff; + isAppend = false; for (let i = end; i >= start; i--) { let recordsLink = "/records?from=" + i + "&to=" + i; - await prependRows(recordsLink); + await addRows(recordsLink); } - state.trimStart = state.trimStart - diff; - state.records = newHeight; + trimStart = trimStart - diff; + records = newHeight; } else if (diff > 0 && end >= RECORDCOUNT) { - let addEnd = (RECORDCOUNT - 1) - state.trimEnd; + let addEnd = (RECORDCOUNT - 1) - trimEnd; end = RECORDCOUNT - 1; start = end - addEnd + 1; + isAppend = true; let recordsLink = "/records?from=" + start + "&to=" + end; addRows(recordsLink); let addTop = diff - addEnd; - end = state.trimStart - 1; - start = state.trimStart - addTop; + end = trimStart - 1; + start = trimStart - addTop; + isAppend = false; for (let i = end; i >= start; i--) { let recordsLink = "/records?from=" + i + "&to=" + i; - await prependRows(recordsLink); + await addRows(recordsLink); } - state.trimEnd = RECORDCOUNT - 1; - state.trimStart = state.trimStart - addTop; - state.records = newHeight; + trimEnd = RECORDCOUNT - 1; + trimStart = trimStart - addTop; + records = newHeight; } else if (diff > 0 && start <= RECORDCOUNT - 1) { // Add rows if end of data is not yet reached + isAppend = true; let recordsLink = "/records?from=" + start + "&to=" + end; addRows(recordsLink); - state.trimEnd = state.trimEnd + diff; - state.records = newHeight; + trimEnd = trimEnd + diff; + records = newHeight; } else { - state.records = newHeight; + records = newHeight; } // UI "Aesthetic": update buttons - el('first')?.removeAttribute("disabled"); - el('prev')?.removeAttribute("disabled"); - el('next')?.removeAttribute("disabled"); - el('last')?.removeAttribute("disabled"); - - if (state.trimEnd == RECORDCOUNT - 1) { - el('last')?.setAttribute("disabled", "disabled"); - el('next')?.setAttribute("disabled", "disabled"); + firstBtn?.removeAttribute("disabled"); + prevBtn?.removeAttribute("disabled"); + nextBtn?.removeAttribute("disabled"); + lastBtn?.removeAttribute("disabled"); + + if (trimEnd == RECORDCOUNT - 1) { + lastBtn?.setAttribute("disabled", "disabled"); + nextBtn?.setAttribute("disabled", "disabled"); } - if (state.trimStart == 0) { - el('first')?.setAttribute("disabled", "disabled"); - el('prev')?.setAttribute("disabled", "disabled"); + if (trimStart == 0) { + firstBtn?.setAttribute("disabled", "disabled"); + prevBtn?.setAttribute("disabled", "disabled"); } }, 100) ); // Log window dimensions at most every 100ms window.onload = () => { - state.trimStart = 0 - state.trimEnd = state.trimStart + state.records - 1; - el('first')?.setAttribute("disabled", "disabled"); - el('prev')?.setAttribute("disabled", "disabled"); + trimStart = 0 + trimEnd = trimStart + records - 1; + + firstBtn?.setAttribute("disabled", "disabled"); + prevBtn?.setAttribute("disabled", "disabled"); + + // Get document elements when page loads + contentTable = document.getElementById('content-table'); + tableBody = contentTable!.querySelector("tbody"); + tableHead = document.getElementById("content-thead"); + pageInfo = document.getElementById('page-number'); + firstBtn = document.getElementById('first'); + prevBtn = document.getElementById('prev'); + nextBtn = document.getElementById('next'); + lastBtn = document.getElementById('last'); + inputBox = document.getElementById('id-search'); getData(); } diff --git a/index.html b/index.html index ca8a0b3c..8ccda8e8 100644 --- a/index.html +++ b/index.html @@ -17,7 +17,7 @@

IMQS Onboarding Project

diff --git a/style.css b/style.css index 07a2c1c7..24923107 100644 --- a/style.css +++ b/style.css @@ -1,7 +1,7 @@ html { font-size: 62.5%; - } +} body { font-size: 16px; @@ -136,30 +136,30 @@ h1 { .btn:disabled, .btn[disabled]{ - border: 1px solid #999999; - background-color: #cccccc; - color: #666666; + border: 1px solid #999999; + background-color: #cccccc; + color: #666666; } - /* width */ - ::-webkit-scrollbar { +/* width */ +::-webkit-scrollbar { height: 10px; - } - - /* Track */ - ::-webkit-scrollbar-track { +} + +/* Track */ +::-webkit-scrollbar-track { background: #16191e; - } - - /* Handle */ - ::-webkit-scrollbar-thumb { +} + +/* Handle */ +::-webkit-scrollbar-thumb { background: #888; - } - - /* Handle on hover */ - ::-webkit-scrollbar-thumb:hover { +} + +/* Handle on hover */ +::-webkit-scrollbar-thumb:hover { background: #555; - } +} /* Loader */ .content { From 2feb35f3cbd9dab11821902426704b2804042df9 Mon Sep 17 00:00:00 2001 From: CelesteNaude <286celeste@gmail.com> Date: Mon, 7 Mar 2022 11:00:34 +0200 Subject: [PATCH 12/19] Improved search function --- app.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/app.ts b/app.ts index 028f0cba..11da575a 100644 --- a/app.ts +++ b/app.ts @@ -35,15 +35,12 @@ async function getData() { } -// TODO Pierre's changes // Search entered ID async function searchFunction() { - let idString = $('#id-search').val() - let id = Number($('#id-search').val()); + let id = parseInt((inputBox).value); let numRecords = RECORDCOUNT - 1; - - if (id < 0 || id > numRecords || Number.isNaN(id) || idString == "") { + if (id < 0 || id > numRecords || isNaN(id)) { // User info: Display error message pageInfo!.innerHTML = `

No records to display

`; } @@ -59,7 +56,7 @@ async function searchFunction() { } loadIntoTable(contentTable); } - (inputBox).value = ''; + (inputBox).value = 'Enter ID number'; } From 9773ed67bd0a029c97cf969db41aa3ffab3468a3 Mon Sep 17 00:00:00 2001 From: CelesteNaude <286celeste@gmail.com> Date: Mon, 7 Mar 2022 15:23:15 +0200 Subject: [PATCH 13/19] Improved pagination buttons' click events --- app.ts | 165 +++++++++++++++++++++-------------------------------- index.html | 13 +++-- style.css | 2 +- 3 files changed, 72 insertions(+), 108 deletions(-) diff --git a/app.ts b/app.ts index 11da575a..152b0439 100644 --- a/app.ts +++ b/app.ts @@ -10,16 +10,15 @@ let RECORDCOUNT: number; let HEADERS: string[]; // Global document elements -let contentTable: HTMLElement | null; -let tableBody: HTMLTableSectionElement | null; -let pageInfo: HTMLElement | null; -let firstBtn: HTMLElement | null; -let prevBtn: HTMLElement | null; -let nextBtn: HTMLElement | null; -let lastBtn: HTMLElement | null; -let tableHead: HTMLElement | null; -let inputBox: HTMLElement | null; - +let contentTable: HTMLElement | null = document.getElementById('content-table'); +let tableBody: HTMLTableSectionElement | null = contentTable!.querySelector("tbody"); +let tableHead: HTMLElement | null = document.getElementById("content-thead"); +let pageInfo: HTMLElement | null = document.getElementById('page-info'); +let firstBtn: HTMLElement | null = document.getElementById('first'); +let prevBtn: HTMLElement | null = document.getElementById('prev'); +let nextBtn: HTMLElement | null = document.getElementById('next'); +let lastBtn: HTMLElement | null = document.getElementById('last'); +let inputBox: HTMLElement | null = document.getElementById('id-search'); // Fetch headers and record count @@ -35,6 +34,17 @@ async function getData() { } +window.onload = () => { + trimStart = 0 + trimEnd = trimStart + records - 1; + + firstBtn?.setAttribute("disabled", "disabled"); + prevBtn?.setAttribute("disabled", "disabled"); + + getData(); +} + + // Search entered ID async function searchFunction() { let id = parseInt((inputBox).value); @@ -79,7 +89,7 @@ async function addRows(link: string) { tableBody!.appendChild(rowElement); // Append rows } else { - tableBody?.prepend(rowElement); /**Prepend rows*/ + tableBody!.prepend(rowElement); /**Prepend rows*/ } } @@ -145,92 +155,64 @@ async function loadIntoTable(table: any) { $(".content").fadeIn(200); } +// Code is only triggered once per user input +const debounce = (fn: Function, ms: number) => { + let timeoutId: ReturnType; + return function (this: any, ...args: any[]) { + clearTimeout(timeoutId); + timeoutId = setTimeout(() => fn.apply(this, args), ms); + }; +}; + -// TODO Divide function into onclick events -// Calculate what data should be fetch when page buttons are clicked -function pageFunction(btnName: string) { - let isValid = false +// Set trim to start of data +firstBtn!.addEventListener("click", debounce(() => { + trimStart = 0; + trimEnd = trimStart + records - 1; + loadIntoTable(contentTable); +}, 800) +); - // Set trim to start of data - if (btnName == "first" && trimStart != 0) { - isValid = true; + +// Set trim to previous data +prevBtn!.addEventListener("click", debounce(() => { + // If previous page is end of data && there are not enough records to fill window + if ((trimStart - 1) - (records - 1) < 0) { trimStart = 0; trimEnd = trimStart + records - 1; } - - // Set trim to previous data - if (btnName == "prev" && trimStart != 0) { - // If previous page is end of data && there are not enough records to fill window - if ((trimStart - 1) - (records - 1) < 0) { - trimStart = 0; - trimEnd = trimStart + records - 1; - } - else { - trimEnd = trimStart - 1; - trimStart = trimEnd - records + 1; - } - isValid = true; - + else { + trimEnd = trimStart - 1; + trimStart = trimEnd - records + 1; } + loadIntoTable(contentTable); +}, 800) +); - // Set trim to next data - if (btnName == "next" && trimEnd != RECORDCOUNT - 1) { - // If next page is end of data && there are not enough records to fill window - if ((RECORDCOUNT - 1) - (trimEnd + 1) < records) { - trimEnd = RECORDCOUNT - 1; - trimStart = trimEnd - records + 1; - } - else { - trimStart = trimEnd + 1; - trimEnd = trimStart + records - 1; - } - isValid = true; - } - // Set trim to end of data - if (btnName == "last" && trimEnd != RECORDCOUNT - 1) { - isValid = true; +// Set trim to next data +nextBtn!.addEventListener("click", debounce(() => { + // If next page is end of data && there are not enough records to fill window + if ((RECORDCOUNT - 1) - (trimEnd + 1) < records) { trimEnd = RECORDCOUNT - 1; trimStart = trimEnd - records + 1; } - - if (isValid) { - loadIntoTable(contentTable); - } else { - console.log("Grey out"); + trimStart = trimEnd + 1; + trimEnd = trimStart + records - 1; } - -} - - -// Code is only triggered once per user input -const debounce = (fn: Function, ms: number) => { - let timeoutId: ReturnType; - return function (this: any, ...args: any[]) { - clearTimeout(timeoutId); - timeoutId = setTimeout(() => fn.apply(this, args), ms); - }; -}; + loadIntoTable(contentTable); +}, 800) +); -// Last resort debounce application for buttons -function inputFirst() { - pageFunction('first'); -} -function inputPrev() { - pageFunction('prev'); -} -function inputNext() { - pageFunction('next'); -} -function inputLast() { - pageFunction('last'); -} -const clickFirst = debounce(() => inputFirst(), 800); -const clickPrev = debounce(() => inputPrev(), 800); -const clickNext = debounce(() => inputNext(), 800); -const clickLast = debounce(() => inputLast(), 800); +// Set trim to end of data +lastBtn!.addEventListener("click", debounce(() => { + trimEnd = RECORDCOUNT - 1; + trimStart = trimEnd - records + 1; + loadIntoTable(contentTable); +}, 800) +); // Add/remove rows from table based on resize event of the window @@ -325,25 +307,6 @@ window.addEventListener("resize", debounce(async () => { ); // Log window dimensions at most every 100ms -window.onload = () => { - trimStart = 0 - trimEnd = trimStart + records - 1; - - firstBtn?.setAttribute("disabled", "disabled"); - prevBtn?.setAttribute("disabled", "disabled"); - - // Get document elements when page loads - contentTable = document.getElementById('content-table'); - tableBody = contentTable!.querySelector("tbody"); - tableHead = document.getElementById("content-thead"); - pageInfo = document.getElementById('page-number'); - firstBtn = document.getElementById('first'); - prevBtn = document.getElementById('prev'); - nextBtn = document.getElementById('next'); - lastBtn = document.getElementById('last'); - inputBox = document.getElementById('id-search'); - getData(); -} diff --git a/index.html b/index.html index 8ccda8e8..ae3aba7a 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ JS Onboard Project - + @@ -27,14 +27,15 @@

IMQS Onboarding Project

- - - - + + + +
-

+

+ diff --git a/style.css b/style.css index 24923107..f8b47c06 100644 --- a/style.css +++ b/style.css @@ -103,7 +103,7 @@ h1 { } /* Page n underneath table */ -.page-num { +.page-info { color: #cae00d; font-size: 2.4rem; margin: auto; From 5cae6548c8143014919c8c54b57741f6407a236b Mon Sep 17 00:00:00 2001 From: CelesteNaude <286celeste@gmail.com> Date: Tue, 8 Mar 2022 15:30:41 +0200 Subject: [PATCH 14/19] Moved global variables into seperate class --- app.ts | 308 +++++++++++++++++++++++---------------------------- index.html | 4 +- state.js | 50 +++++++++ state.js.map | 1 + state.ts | 63 +++++++++++ 5 files changed, 252 insertions(+), 174 deletions(-) create mode 100644 state.js create mode 100644 state.js.map create mode 100644 state.ts diff --git a/app.ts b/app.ts index 152b0439..5c5ac3c6 100644 --- a/app.ts +++ b/app.ts @@ -1,83 +1,68 @@ - -let records = Math.floor((window.innerHeight - 160) / 40); // Estimate of available table space -let trimStart: number; -let trimEnd: number; -let countRec: number; -let isAppend: boolean; - -// Variables fetched once with load of window -let RECORDCOUNT: number; -let HEADERS: string[]; - -// Global document elements -let contentTable: HTMLElement | null = document.getElementById('content-table'); -let tableBody: HTMLTableSectionElement | null = contentTable!.querySelector("tbody"); -let tableHead: HTMLElement | null = document.getElementById("content-thead"); -let pageInfo: HTMLElement | null = document.getElementById('page-info'); -let firstBtn: HTMLElement | null = document.getElementById('first'); -let prevBtn: HTMLElement | null = document.getElementById('prev'); -let nextBtn: HTMLElement | null = document.getElementById('next'); -let lastBtn: HTMLElement | null = document.getElementById('last'); -let inputBox: HTMLElement | null = document.getElementById('id-search'); - +let state = new State(); // Fetch headers and record count async function getData() { // API calls for record count and headers - RECORDCOUNT = await fetch('/recordCount') - .then(resp => resp.json()); - HEADERS = await fetch('/columns') - .then(resp => resp.json()); + await fetch('/recordCount') + .then(resp => { + return resp.json(); + }) + .then(count => { + state.RECORDCOUNT = count; + }); + + await fetch('/columns') + .then(resp => { + return resp.json(); + }) + .then(count => { + state.HEADERS = count; + }); // Populate table with fetched data - loadIntoTable(contentTable); + loadIntoTable(state.contentTable); } - window.onload = () => { - trimStart = 0 - trimEnd = trimStart + records - 1; - - firstBtn?.setAttribute("disabled", "disabled"); - prevBtn?.setAttribute("disabled", "disabled"); - + state.firstBtn?.setAttribute("disabled", "disabled"); + state.prevBtn?.setAttribute("disabled", "disabled"); getData(); -} - +}; // Search entered ID async function searchFunction() { - let id = parseInt((inputBox).value); - let numRecords = RECORDCOUNT - 1; + let id = parseInt((state.inputBox).value); + let numRecords = state.RECORDCOUNT - 1; if (id < 0 || id > numRecords || isNaN(id)) { // User info: Display error message - pageInfo!.innerHTML = `

No records to display

`; - } - else { + state.pageInfo!.innerHTML = `

No records to display

`; + } else { // Use entered ID to calculate what records should display - if ((RECORDCOUNT - 1) - id >= records) { - trimStart = id; - trimEnd = trimStart + (records - 1); + if ((state.RECORDCOUNT - 1) - id >= state.getRecords()) { + state.setTrimStart(id); + state.setTrimEnd(state.getTrimStart() + (state.getRecords() - 1)); + } else { + state.setTrimEnd(state.RECORDCOUNT - 1); + state.setTrimStart(state.getTrimEnd() - state.getRecords() + 1); } - else { - trimEnd = RECORDCOUNT - 1; - trimStart = trimEnd - records + 1; - } - loadIntoTable(contentTable); + loadIntoTable(state.contentTable); } - (inputBox).value = 'Enter ID number'; + (state.inputBox).value = 'Enter ID number'; } - +// TODO fix add rows // Add rows to table -async function addRows(link: string) { +async function addRows(this: any, start: number, end: number, isAppend: boolean) { + // let newTableBody = document.createElement("tbody"); + // let reversedTableBody = document.createElement("tbody"); + let link = "/records?from=" + start + "&to=" + end; let data = await fetch(link) .then(resp => resp.json()); for (let row of data) { let rowElement = document.createElement("tr"); - countRec += 1; + state.setCountRec(state.getCountRec() + 1); for (let cellText of row) { let cellElement = document.createElement("td"); @@ -85,27 +70,39 @@ async function addRows(link: string) { cellElement.textContent = cellText; rowElement.appendChild(cellElement); // Append cells } + if (isAppend) { - tableBody!.appendChild(rowElement); // Append rows - } - else { - tableBody!.prepend(rowElement); /**Prepend rows*/ - } + state.tableBody!.appendChild(rowElement);// Append rows + } else { + state.tableBody!.prepend(rowElement); + + } } -} + // let rows = newTableBody!.rows; + // if (isAppend) { + // this.tableBody.parentNode.replaceChild(newTableBody, this.tableBody)// Append rows + // } + // else { + // for (let i = rows.length - 1; i >= 0; i--) { + // reversedTableBody!.appendChild(rows[i]); // Prepend rows + // } + // contentTable!.prepend(reversedTableBody); + + // } + +} // Delete rows from table async function deleteRows(newHeight: number, diff: number) { let num = newHeight - 1; for (let i = num; i > (num + diff); i--) { - tableBody!.deleteRow(i); + state.tableBody!.deleteRow(i); } } - // Load json data into table function async function loadIntoTable(table: any) { @@ -114,41 +111,38 @@ async function loadIntoTable(table: any) { $(".loader").fadeIn(200); // UI "Aesthetic": update buttons - firstBtn?.removeAttribute("disabled"); - prevBtn?.removeAttribute("disabled"); - nextBtn?.removeAttribute("disabled"); - lastBtn?.removeAttribute("disabled"); - - if (trimEnd == RECORDCOUNT - 1) { - lastBtn?.setAttribute("disabled", "disabled"); - nextBtn?.setAttribute("disabled", "disabled"); + state.firstBtn?.removeAttribute("disabled"); + state.prevBtn?.removeAttribute("disabled"); + state.nextBtn?.removeAttribute("disabled"); + state.lastBtn?.removeAttribute("disabled"); + + if (state.getTrimEnd() == state.RECORDCOUNT - 1) { + state.lastBtn?.setAttribute("disabled", "disabled"); + state.nextBtn?.setAttribute("disabled", "disabled"); } - if (trimStart == 0) { - firstBtn?.setAttribute("disabled", "disabled"); - prevBtn?.setAttribute("disabled", "disabled"); + if (state.getTrimStart() == 0) { + state.firstBtn?.setAttribute("disabled", "disabled"); + state.prevBtn?.setAttribute("disabled", "disabled"); } - pageInfo!.innerHTML = `

`; + state.pageInfo!.innerHTML = `

`; // Clear the table - tableHead!.innerHTML = ""; - tableBody!.innerHTML = ""; + state.tableHead!.innerHTML = ""; + state.tableBody!.innerHTML = ""; // Populate the headers - for (let headerText of HEADERS) { + for (let headerText of state.HEADERS) { let headerElement = document.createElement("th"); headerElement.textContent = headerText; - tableHead!.querySelector("tr")!.appendChild(headerElement); + state.tableHead!.querySelector("tr")!.appendChild(headerElement); } - // Fetch only records that must be displayed on table - let recordsLink = "/records?from=" + trimStart + "&to=" + trimEnd; - - countRec = 0; - isAppend = true; - addRows(recordsLink); + // Add only records that must be displayed on table + state.setCountRec(0); + addRows(state.getTrimStart(), state.getTrimEnd(), true); // Display content $(".loader").fadeOut(200); @@ -164,144 +158,114 @@ const debounce = (fn: Function, ms: number) => { }; }; - // Set trim to start of data -firstBtn!.addEventListener("click", debounce(() => { - trimStart = 0; - trimEnd = trimStart + records - 1; - loadIntoTable(contentTable); +state.firstBtn!.addEventListener("click", debounce(() => { + state.setTrimStart(0); + state.setTrimEnd(state.getTrimStart() + state.getRecords() - 1); + loadIntoTable(state.contentTable); }, 800) ); - // Set trim to previous data -prevBtn!.addEventListener("click", debounce(() => { +state.prevBtn!.addEventListener("click", debounce(() => { // If previous page is end of data && there are not enough records to fill window - if ((trimStart - 1) - (records - 1) < 0) { - trimStart = 0; - trimEnd = trimStart + records - 1; + if ((state.getTrimStart() - 1) - (state.getRecords() - 1) < 0) { + state.setTrimStart(0); + state.setTrimEnd(state.getTrimStart() + state.getRecords() - 1); + } else { + state.setTrimEnd(state.getTrimStart() - 1); + state.setTrimStart(state.getTrimEnd() - state.getRecords() + 1); } - else { - trimEnd = trimStart - 1; - trimStart = trimEnd - records + 1; - } - loadIntoTable(contentTable); + loadIntoTable(state.contentTable); }, 800) ); - // Set trim to next data -nextBtn!.addEventListener("click", debounce(() => { +state.nextBtn!.addEventListener("click", debounce(() => { // If next page is end of data && there are not enough records to fill window - if ((RECORDCOUNT - 1) - (trimEnd + 1) < records) { - trimEnd = RECORDCOUNT - 1; - trimStart = trimEnd - records + 1; + if ((state.RECORDCOUNT - 1) - (state.getTrimEnd() + 1) < state.getRecords()) { + state.setTrimEnd(state.RECORDCOUNT - 1); + state.setTrimStart(state.getTrimEnd() - state.getRecords() + 1); + } else { + state.setTrimStart(state.getTrimEnd() + 1); + state.setTrimEnd(state.getTrimStart() + state.getRecords() - 1); } - else { - trimStart = trimEnd + 1; - trimEnd = trimStart + records - 1; - } - loadIntoTable(contentTable); + loadIntoTable(state.contentTable); }, 800) ); - // Set trim to end of data -lastBtn!.addEventListener("click", debounce(() => { - trimEnd = RECORDCOUNT - 1; - trimStart = trimEnd - records + 1; - loadIntoTable(contentTable); +state.lastBtn!.addEventListener("click", debounce(() => { + state.setTrimEnd(state.RECORDCOUNT - 1); + state.setTrimStart(state.getTrimEnd() - state.getRecords() + 1); + loadIntoTable(state.contentTable); }, 800) ); - // Add/remove rows from table based on resize event of the window window.addEventListener("resize", debounce(async () => { - isAppend = false; // Calculate number rows to be added/deleted let newHeight = Math.floor((window.innerHeight - 160) / 40); - let diff = newHeight - records; + let diff = newHeight - state.getRecords(); - let start = trimEnd + 1; - let end = trimEnd + diff; + let start = state.getTrimEnd() + 1; + let end = state.getTrimEnd() + diff; if (diff < 0) { // Delete rows from last page - deleteRows(countRec, diff); + deleteRows(state.getCountRec(), diff); - countRec = countRec + diff; - trimEnd = trimEnd + diff; - records = newHeight; + state.setCountRec(state.getCountRec() + diff); + state.setTrimEnd(state.getTrimEnd() + diff); } - else if (diff > 0 && trimEnd == RECORDCOUNT - 1) { + else if (diff > 0 && state.getTrimEnd() == state.RECORDCOUNT - 1) { // Prepend rows as last page gets bigger - let timeoutId: ReturnType; + end = state.getTrimStart() - 1; + start = state.getTrimStart() - diff; - end = trimStart - 1; - start = trimStart - diff; - isAppend = false; - - for (let i = end; i >= start; i--) { - let recordsLink = "/records?from=" + i + "&to=" + i; - await addRows(recordsLink); - } - - - trimStart = trimStart - diff; - records = newHeight; + await addRows(start, end, false); + state.setTrimStart(state.getTrimStart() - diff); } - else if (diff > 0 && end >= RECORDCOUNT) { - let addEnd = (RECORDCOUNT - 1) - trimEnd; - end = RECORDCOUNT - 1; + else if (diff > 0 && end >= state.RECORDCOUNT) { + let addEnd = (state.RECORDCOUNT - 1) - state.getTrimEnd(); + end = state.RECORDCOUNT - 1; start = end - addEnd + 1; - isAppend = true; - let recordsLink = "/records?from=" + start + "&to=" + end; - addRows(recordsLink); + addRows(start, end, true); let addTop = diff - addEnd; - end = trimStart - 1; - start = trimStart - addTop; - isAppend = false; + end = state.getTrimStart() - 1; + start = state.getTrimStart() - addTop; - for (let i = end; i >= start; i--) { - let recordsLink = "/records?from=" + i + "&to=" + i; - await addRows(recordsLink); - } + await addRows(start, end, false); - trimEnd = RECORDCOUNT - 1; - trimStart = trimStart - addTop; - records = newHeight; + state.setTrimEnd(state.RECORDCOUNT - 1); + state.setTrimStart(state.getTrimStart() - addTop) } - else if (diff > 0 && start <= RECORDCOUNT - 1) { + else if (diff > 0 && start <= state.RECORDCOUNT - 1) { // Add rows if end of data is not yet reached - isAppend = true; - let recordsLink = "/records?from=" + start + "&to=" + end; - addRows(recordsLink); + addRows(start, end, true); - trimEnd = trimEnd + diff; - records = newHeight; - } - else { - records = newHeight; + state.setTrimEnd(state.getTrimEnd() + diff) } + state.setRecords(newHeight); // UI "Aesthetic": update buttons - firstBtn?.removeAttribute("disabled"); - prevBtn?.removeAttribute("disabled"); - nextBtn?.removeAttribute("disabled"); - lastBtn?.removeAttribute("disabled"); - - if (trimEnd == RECORDCOUNT - 1) { - lastBtn?.setAttribute("disabled", "disabled"); - nextBtn?.setAttribute("disabled", "disabled"); + state.firstBtn?.removeAttribute("disabled"); + state.prevBtn?.removeAttribute("disabled"); + state.nextBtn?.removeAttribute("disabled"); + state.lastBtn?.removeAttribute("disabled"); + + if (state.getTrimEnd() == state.RECORDCOUNT - 1) { + state.lastBtn?.setAttribute("disabled", "disabled"); + state.nextBtn?.setAttribute("disabled", "disabled"); } - if (trimStart == 0) { - firstBtn?.setAttribute("disabled", "disabled"); - prevBtn?.setAttribute("disabled", "disabled"); + if (state.getTrimStart() == 0) { + state.firstBtn?.setAttribute("disabled", "disabled"); + state.prevBtn?.setAttribute("disabled", "disabled"); } }, 100) ); // Log window dimensions at most every 100ms diff --git a/index.html b/index.html index ae3aba7a..ed92d7da 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,6 @@ JS Onboard Project - @@ -35,7 +34,8 @@

IMQS Onboarding Project

- + + diff --git a/state.js b/state.js new file mode 100644 index 00000000..38fd1046 --- /dev/null +++ b/state.js @@ -0,0 +1,50 @@ +"use strict"; +var State = /** @class */ (function () { + function State() { + this.contentTable = document.getElementById('content-table'); + this.tableBody = document.querySelector('tbody'); + this.tableHead = document.getElementById("content-thead"); + this.pageInfo = document.getElementById('page-info'); + this.firstBtn = document.getElementById('first'); + this.prevBtn = document.getElementById('prev'); + this.nextBtn = document.getElementById('next'); + this.lastBtn = document.getElementById('last'); + this.inputBox = document.getElementById('id-search'); + this.RECORDCOUNT = 350; + this.HEADERS = ["ID", "City", "Population"]; + this.data = [[0, "Cape Town", 3500000], [1, "New York", 8500000], [2, "Johannesburg", 4500000]]; + this.records = this.calculateRecords(); + this.trimStart = 0; + this.trimEnd = this.records - 1; + this.countRec = 0; + } + State.prototype.getRecords = function () { + return this.records; + }; + State.prototype.getTrimStart = function () { + return this.trimStart; + }; + State.prototype.getTrimEnd = function () { + return this.trimEnd; + }; + State.prototype.getCountRec = function () { + return this.countRec; + }; + State.prototype.setRecords = function (value) { + this.records = value; + }; + State.prototype.setTrimStart = function (value) { + this.trimStart = value; + }; + State.prototype.setTrimEnd = function (value) { + this.trimEnd = value; + }; + State.prototype.setCountRec = function (value) { + this.countRec = value; + }; + State.prototype.calculateRecords = function () { + return Math.floor((window.innerHeight - 160) / 40); // Estimate of available table space + }; + return State; +}()); +//# sourceMappingURL=state.js.map \ No newline at end of file diff --git a/state.js.map b/state.js.map new file mode 100644 index 00000000..bde66eb4 --- /dev/null +++ b/state.js.map @@ -0,0 +1 @@ +{"version":3,"file":"state.js","sourceRoot":"","sources":["state.ts"],"names":[],"mappings":";AAAA;IAoBC;QAdA,iBAAY,GAAuB,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QAC5E,cAAS,GAAmC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAC5E,cAAS,GAAuB,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QACzE,aAAQ,GAAuB,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QACpE,aAAQ,GAAuB,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAChE,YAAO,GAAuB,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC9D,YAAO,GAAuB,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC9D,YAAO,GAAuB,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC9D,aAAQ,GAAuB,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QAEpE,gBAAW,GAAW,GAAG,CAAC;QAC1B,YAAO,GAAa,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QACjD,SAAI,GAAQ,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC;QAG/F,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACvC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QACnB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;QAChC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;IACnB,CAAC;IAED,0BAAU,GAAV;QACC,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED,4BAAY,GAAZ;QACC,OAAO,IAAI,CAAC,SAAS,CAAC;IACvB,CAAC;IAED,0BAAU,GAAV;QACC,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED,2BAAW,GAAX;QACC,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;IAED,0BAAU,GAAV,UAAW,KAAa;QACvB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,4BAAY,GAAZ,UAAa,KAAa;QACzB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;IACxB,CAAC;IAED,0BAAU,GAAV,UAAW,KAAa;QACvB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,2BAAW,GAAX,UAAY,KAAa;QACxB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;IACvB,CAAC;IAED,gCAAgB,GAAhB;QACC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,WAAW,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,oCAAoC;IACzF,CAAC;IACF,YAAC;AAAD,CAAC,AA9DD,IA8DC"} \ No newline at end of file diff --git a/state.ts b/state.ts new file mode 100644 index 00000000..56bf06da --- /dev/null +++ b/state.ts @@ -0,0 +1,63 @@ +class State { + private records: number; + private trimStart: number; + private trimEnd: number; + private countRec: number; + + contentTable: HTMLElement | null = document.getElementById('content-table'); + tableBody: HTMLTableSectionElement | null = document.querySelector('tbody'); + tableHead: HTMLElement | null = document.getElementById("content-thead"); + pageInfo: HTMLElement | null = document.getElementById('page-info'); + firstBtn: HTMLElement | null = document.getElementById('first'); + prevBtn: HTMLElement | null = document.getElementById('prev'); + nextBtn: HTMLElement | null = document.getElementById('next'); + lastBtn: HTMLElement | null = document.getElementById('last'); + inputBox: HTMLElement | null = document.getElementById('id-search'); + + RECORDCOUNT: number = 350; + HEADERS: string[] = ["ID", "City", "Population"]; + data: any = [[0, "Cape Town", 3500000], [1, "New York", 8500000], [2, "Johannesburg", 4500000]]; + + constructor() { + this.records = this.calculateRecords(); + this.trimStart = 0; + this.trimEnd = this.records - 1; + this.countRec = 0; + } + + getRecords() { + return this.records; + } + + getTrimStart() { + return this.trimStart; + } + + getTrimEnd() { + return this.trimEnd; + } + + getCountRec() { + return this.countRec; + } + + setRecords(value: number) { + this.records = value; + } + + setTrimStart(value: number) { + this.trimStart = value; + } + + setTrimEnd(value: number) { + this.trimEnd = value; + } + + setCountRec(value: number) { + this.countRec = value; + } + + calculateRecords() { + return Math.floor((window.innerHeight - 160) / 40); // Estimate of available table space + } +} From a8fa4fff8f6ba51d12191895a4a516897c756eb8 Mon Sep 17 00:00:00 2001 From: CelesteNaude <286celeste@gmail.com> Date: Tue, 8 Mar 2022 17:25:54 +0200 Subject: [PATCH 15/19] Logic fixes + code cleanup --- app.ts | 145 +++++++++++++++++++++++++++++---------------------- index.html | 4 +- state.js | 2 + state.js.map | 2 +- state.ts | 3 ++ style.css | 17 +++--- 6 files changed, 98 insertions(+), 75 deletions(-) diff --git a/app.ts b/app.ts index 5c5ac3c6..18b4f471 100644 --- a/app.ts +++ b/app.ts @@ -1,67 +1,71 @@ let state = new State(); // Fetch headers and record count -async function getData() { +async function getData(): Promise { // API calls for record count and headers await fetch('/recordCount') .then(resp => { - return resp.json(); + if (resp.ok) { + return resp.json(); + } + throw new Error('Something went wrong'); }) .then(count => { state.RECORDCOUNT = count; + }) + .catch((error) => { + console.log(error); }); await fetch('/columns') .then(resp => { - return resp.json(); + if (resp.ok) { + return resp.json(); + } + throw new Error('Something went wrong'); }) .then(count => { state.HEADERS = count; + }) + .catch((error) => { + console.log(error); }); // Populate table with fetched data - loadIntoTable(state.contentTable); + loadIntoTable(); + // TODO: Add return statement } window.onload = () => { - state.firstBtn?.setAttribute("disabled", "disabled"); - state.prevBtn?.setAttribute("disabled", "disabled"); + // TODO: Check if buttons exits + state.firstBtn!.setAttribute("disabled", "disabled"); + state.prevBtn!.setAttribute("disabled", "disabled"); getData(); }; -// Search entered ID -async function searchFunction() { - let id = parseInt((state.inputBox).value); - let numRecords = state.RECORDCOUNT - 1; - - if (id < 0 || id > numRecords || isNaN(id)) { - // User info: Display error message - state.pageInfo!.innerHTML = `

No records to display

`; - } else { - // Use entered ID to calculate what records should display - if ((state.RECORDCOUNT - 1) - id >= state.getRecords()) { - state.setTrimStart(id); - state.setTrimEnd(state.getTrimStart() + (state.getRecords() - 1)); - } else { - state.setTrimEnd(state.RECORDCOUNT - 1); - state.setTrimStart(state.getTrimEnd() - state.getRecords() + 1); - } - loadIntoTable(state.contentTable); - } - (state.inputBox).value = 'Enter ID number'; -} - -// TODO fix add rows +// TODO: Fix add rows // Add rows to table async function addRows(this: any, start: number, end: number, isAppend: boolean) { // let newTableBody = document.createElement("tbody"); // let reversedTableBody = document.createElement("tbody"); let link = "/records?from=" + start + "&to=" + end; - let data = await fetch(link) - .then(resp => resp.json()); + await fetch(link) + .then(resp => { + if (resp.ok) { + return resp.json(); + } + throw new Error('Something went wrong'); + }) + .then(count => { + state.data = count; + }) + .catch((error) => { + console.log(error); + }); - for (let row of data) { + for (let row of state.data) { let rowElement = document.createElement("tr"); + // TODO: Set total records after addRows is called state.setCountRec(state.getCountRec() + 1); for (let cellText of row) { @@ -70,16 +74,14 @@ async function addRows(this: any, start: number, end: number, isAppend: boolean) cellElement.textContent = cellText; rowElement.appendChild(cellElement); // Append cells } - if (isAppend) { state.tableBody!.appendChild(rowElement);// Append rows } else { - state.tableBody!.prepend(rowElement); - } } + // TODO: Fix prepend feature // let rows = newTableBody!.rows; // if (isAppend) { // this.tableBody.parentNode.replaceChild(newTableBody, this.tableBody)// Append rows @@ -89,13 +91,11 @@ async function addRows(this: any, start: number, end: number, isAppend: boolean) // reversedTableBody!.appendChild(rows[i]); // Prepend rows // } // contentTable!.prepend(reversedTableBody); - // } - } // Delete rows from table -async function deleteRows(newHeight: number, diff: number) { +function deleteRows(newHeight: number, diff: number) { let num = newHeight - 1; for (let i = num; i > (num + diff); i--) { @@ -104,7 +104,7 @@ async function deleteRows(newHeight: number, diff: number) { } // Load json data into table function -async function loadIntoTable(table: any) { +function loadIntoTable() { // Display loader $(".content").fadeOut(200); @@ -129,17 +129,21 @@ async function loadIntoTable(table: any) { state.pageInfo!.innerHTML = `

`; // Clear the table - state.tableHead!.innerHTML = ""; + state.tableHead!.innerHTML = ""; state.tableBody!.innerHTML = ""; + let headerRow = document.createElement("tr"); + // Populate the headers for (let headerText of state.HEADERS) { let headerElement = document.createElement("th"); headerElement.textContent = headerText; - state.tableHead!.querySelector("tr")!.appendChild(headerElement); + headerRow.appendChild(headerElement); } + state.tableHead!.appendChild(headerRow) + // Add only records that must be displayed on table state.setCountRec(0); addRows(state.getTrimStart(), state.getTrimEnd(), true); @@ -158,13 +162,34 @@ const debounce = (fn: Function, ms: number) => { }; }; +// Search entered ID +state.searchBtn!.addEventListener("click", debounce(() => { + let id = parseInt((state.inputBox).value); + let numRecords = state.RECORDCOUNT - 1; + + if (id < 0 || id > numRecords || isNaN(id)) { + // User info: Display error message + state.pageInfo!.innerHTML = `

No records to display

`; + } else { + // Use entered ID to calculate what records should display + if ((state.RECORDCOUNT - 1) - id >= state.getRecords()) { + state.setTrimStart(id); + state.setTrimEnd(state.getTrimStart() + (state.getRecords() - 1)); + } else { + state.setTrimEnd(state.RECORDCOUNT - 1); + state.setTrimStart(state.getTrimEnd() - state.getRecords() + 1); + } + loadIntoTable(); + } + (state.inputBox).value = 'Enter ID number'; +}, 300)); + // Set trim to start of data state.firstBtn!.addEventListener("click", debounce(() => { state.setTrimStart(0); state.setTrimEnd(state.getTrimStart() + state.getRecords() - 1); - loadIntoTable(state.contentTable); -}, 800) -); + loadIntoTable(); +}, 300)); // Set trim to previous data state.prevBtn!.addEventListener("click", debounce(() => { @@ -176,9 +201,8 @@ state.prevBtn!.addEventListener("click", debounce(() => { state.setTrimEnd(state.getTrimStart() - 1); state.setTrimStart(state.getTrimEnd() - state.getRecords() + 1); } - loadIntoTable(state.contentTable); -}, 800) -); + loadIntoTable(); +}, 300)); // Set trim to next data state.nextBtn!.addEventListener("click", debounce(() => { @@ -190,46 +214,45 @@ state.nextBtn!.addEventListener("click", debounce(() => { state.setTrimStart(state.getTrimEnd() + 1); state.setTrimEnd(state.getTrimStart() + state.getRecords() - 1); } - loadIntoTable(state.contentTable); -}, 800) -); + loadIntoTable(); +}, 300)); // Set trim to end of data state.lastBtn!.addEventListener("click", debounce(() => { state.setTrimEnd(state.RECORDCOUNT - 1); state.setTrimStart(state.getTrimEnd() - state.getRecords() + 1); - loadIntoTable(state.contentTable); -}, 800) -); + loadIntoTable(); +}, 300)); // Add/remove rows from table based on resize event of the window window.addEventListener("resize", debounce(async () => { // Calculate number rows to be added/deleted + // The calculation is an estimate of how many space there is for rows (160 is estimate space for header and footer of website) let newHeight = Math.floor((window.innerHeight - 160) / 40); let diff = newHeight - state.getRecords(); let start = state.getTrimEnd() + 1; let end = state.getTrimEnd() + diff; - if (diff < 0) { // Delete rows from last page deleteRows(state.getCountRec(), diff); state.setCountRec(state.getCountRec() + diff); state.setTrimEnd(state.getTrimEnd() + diff); - } - else if (diff > 0 && state.getTrimEnd() == state.RECORDCOUNT - 1) { + } else if (diff > 0 && state.getTrimEnd() == state.RECORDCOUNT - 1) { // Prepend rows as last page gets bigger + // 'start' and 'end' only fetches the amount that should be prepended end = state.getTrimStart() - 1; start = state.getTrimStart() - diff; await addRows(start, end, false); state.setTrimStart(state.getTrimStart() - diff); - } - else if (diff > 0 && end >= state.RECORDCOUNT) { + } else if (diff > 0 && end >= state.RECORDCOUNT) { + // Appends remaining records until RECORDCOUNT - 1, + // then prepends the rest let addEnd = (state.RECORDCOUNT - 1) - state.getTrimEnd(); end = state.RECORDCOUNT - 1; start = end - addEnd + 1; @@ -243,8 +266,7 @@ window.addEventListener("resize", debounce(async () => { state.setTrimEnd(state.RECORDCOUNT - 1); state.setTrimStart(state.getTrimStart() - addTop) - } - else if (diff > 0 && start <= state.RECORDCOUNT - 1) { + } else if (diff > 0 && start <= state.RECORDCOUNT - 1) { // Add rows if end of data is not yet reached addRows(start, end, true); @@ -267,8 +289,7 @@ window.addEventListener("resize", debounce(async () => { state.firstBtn?.setAttribute("disabled", "disabled"); state.prevBtn?.setAttribute("disabled", "disabled"); } -}, 100) -); // Log window dimensions at most every 100ms +}, 100)); // Log window dimensions at most every 100ms diff --git a/index.html b/index.html index ed92d7da..21de8ca3 100644 --- a/index.html +++ b/index.html @@ -16,7 +16,7 @@

IMQS Onboarding Project

@@ -34,8 +34,8 @@

IMQS Onboarding Project

+ - diff --git a/state.js b/state.js index 38fd1046..81d7ff5c 100644 --- a/state.js +++ b/state.js @@ -5,11 +5,13 @@ var State = /** @class */ (function () { this.tableBody = document.querySelector('tbody'); this.tableHead = document.getElementById("content-thead"); this.pageInfo = document.getElementById('page-info'); + this.searchBtn = document.getElementById('id-search-btn'); this.firstBtn = document.getElementById('first'); this.prevBtn = document.getElementById('prev'); this.nextBtn = document.getElementById('next'); this.lastBtn = document.getElementById('last'); this.inputBox = document.getElementById('id-search'); + // Default values for variables that stores server data this.RECORDCOUNT = 350; this.HEADERS = ["ID", "City", "Population"]; this.data = [[0, "Cape Town", 3500000], [1, "New York", 8500000], [2, "Johannesburg", 4500000]]; diff --git a/state.js.map b/state.js.map index bde66eb4..ea1f789c 100644 --- a/state.js.map +++ b/state.js.map @@ -1 +1 @@ -{"version":3,"file":"state.js","sourceRoot":"","sources":["state.ts"],"names":[],"mappings":";AAAA;IAoBC;QAdA,iBAAY,GAAuB,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QAC5E,cAAS,GAAmC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAC5E,cAAS,GAAuB,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QACzE,aAAQ,GAAuB,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QACpE,aAAQ,GAAuB,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAChE,YAAO,GAAuB,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC9D,YAAO,GAAuB,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC9D,YAAO,GAAuB,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC9D,aAAQ,GAAuB,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QAEpE,gBAAW,GAAW,GAAG,CAAC;QAC1B,YAAO,GAAa,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QACjD,SAAI,GAAQ,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC;QAG/F,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACvC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QACnB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;QAChC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;IACnB,CAAC;IAED,0BAAU,GAAV;QACC,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED,4BAAY,GAAZ;QACC,OAAO,IAAI,CAAC,SAAS,CAAC;IACvB,CAAC;IAED,0BAAU,GAAV;QACC,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED,2BAAW,GAAX;QACC,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;IAED,0BAAU,GAAV,UAAW,KAAa;QACvB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,4BAAY,GAAZ,UAAa,KAAa;QACzB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;IACxB,CAAC;IAED,0BAAU,GAAV,UAAW,KAAa;QACvB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,2BAAW,GAAX,UAAY,KAAa;QACxB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;IACvB,CAAC;IAED,gCAAgB,GAAhB;QACC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,WAAW,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,oCAAoC;IACzF,CAAC;IACF,YAAC;AAAD,CAAC,AA9DD,IA8DC"} \ No newline at end of file +{"version":3,"file":"state.js","sourceRoot":"","sources":["state.ts"],"names":[],"mappings":";AAAA;IAsBC;QAhBA,iBAAY,GAAuB,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QAC5E,cAAS,GAAmC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAC5E,cAAS,GAAuB,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QACzE,aAAQ,GAAuB,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QACpE,cAAS,GAAuB,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QACzE,aAAQ,GAAuB,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAChE,YAAO,GAAuB,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC9D,YAAO,GAAuB,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC9D,YAAO,GAAuB,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC9D,aAAQ,GAAuB,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QAEpE,uDAAuD;QACvD,gBAAW,GAAW,GAAG,CAAC;QAC1B,YAAO,GAAa,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QACjD,SAAI,GAAQ,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC;QAG/F,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACvC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QACnB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;QAChC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;IACnB,CAAC;IAED,0BAAU,GAAV;QACC,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED,4BAAY,GAAZ;QACC,OAAO,IAAI,CAAC,SAAS,CAAC;IACvB,CAAC;IAED,0BAAU,GAAV;QACC,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED,2BAAW,GAAX;QACC,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;IAED,0BAAU,GAAV,UAAW,KAAa;QACvB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,4BAAY,GAAZ,UAAa,KAAa;QACzB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;IACxB,CAAC;IAED,0BAAU,GAAV,UAAW,KAAa;QACvB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,2BAAW,GAAX,UAAY,KAAa;QACxB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;IACvB,CAAC;IAED,gCAAgB,GAAhB;QACC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,WAAW,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,oCAAoC;IACzF,CAAC;IACF,YAAC;AAAD,CAAC,AAhED,IAgEC"} \ No newline at end of file diff --git a/state.ts b/state.ts index 56bf06da..3b59afbb 100644 --- a/state.ts +++ b/state.ts @@ -1,4 +1,5 @@ class State { + // TODO: change variable to public/private and add/remove getters and setters private records: number; private trimStart: number; private trimEnd: number; @@ -8,12 +9,14 @@ class State { tableBody: HTMLTableSectionElement | null = document.querySelector('tbody'); tableHead: HTMLElement | null = document.getElementById("content-thead"); pageInfo: HTMLElement | null = document.getElementById('page-info'); + searchBtn: HTMLElement | null = document.getElementById('id-search-btn'); firstBtn: HTMLElement | null = document.getElementById('first'); prevBtn: HTMLElement | null = document.getElementById('prev'); nextBtn: HTMLElement | null = document.getElementById('next'); lastBtn: HTMLElement | null = document.getElementById('last'); inputBox: HTMLElement | null = document.getElementById('id-search'); + // Default values for variables that stores server data RECORDCOUNT: number = 350; HEADERS: string[] = ["ID", "City", "Population"]; data: any = [[0, "Cape Town", 3500000], [1, "New York", 8500000], [2, "Johannesburg", 4500000]]; diff --git a/style.css b/style.css index f8b47c06..0655219e 100644 --- a/style.css +++ b/style.css @@ -1,4 +1,3 @@ - html { font-size: 62.5%; } @@ -18,7 +17,7 @@ body { .controls { display: flex; text-overflow: clip; - white-space: nowrap; + white-space: nowrap; } .constrols-heading { @@ -51,7 +50,6 @@ h1 { border: solid 1px #cae00d; } - /* Table */ .table { box-shadow: 0 0 10px rgba(94, 102, 80, 0.918); @@ -74,8 +72,8 @@ h1 { padding: 10px 20px; height: 10px; overflow: hidden; - text-overflow: clip; - white-space: nowrap; + text-overflow: clip; + white-space: nowrap; } .table tbody tr:nth-of-type(even) { @@ -97,12 +95,11 @@ h1 { position: absolute; bottom: -1rem; text-overflow: clip; - white-space: nowrap; + white-space: nowrap; background-color: #16191e; - } -/* Page n underneath table */ +/* Page info underneath table */ .page-info { color: #cae00d; font-size: 2.4rem; @@ -113,13 +110,13 @@ h1 { /* Pagination buttons */ .pagination-wrapper { - width: 70%; + width: 70%; overflow-x: auto; margin-left: 1rem; } .btn { - color: #fdfdfd; + color: #fdfdfd; /* float: left; */ padding: 1rem; text-decoration: none; From b3c8dbae44b0b9263419203b848e10eb3830ca8b Mon Sep 17 00:00:00 2001 From: CelesteNaude <286celeste@gmail.com> Date: Wed, 9 Mar 2022 12:34:19 +0200 Subject: [PATCH 16/19] Added seperate file for doc element variables --- app.ts | 175 +++++++++++++++++++++++----------------------- docElement.js | 17 +++++ docElement.js.map | 1 + docElement.ts | 26 +++++++ index.html | 1 + state.js | 29 +------- state.js.map | 2 +- state.ts | 64 ++++++----------- 8 files changed, 158 insertions(+), 157 deletions(-) create mode 100644 docElement.js create mode 100644 docElement.js.map create mode 100644 docElement.ts diff --git a/app.ts b/app.ts index 18b4f471..af2cdd7f 100644 --- a/app.ts +++ b/app.ts @@ -1,4 +1,5 @@ let state = new State(); +let el = new docElement(); // Fetch headers and record count async function getData(): Promise { @@ -8,10 +9,10 @@ async function getData(): Promise { if (resp.ok) { return resp.json(); } - throw new Error('Something went wrong'); + throw new Error('Could not retrieve data'); }) .then(count => { - state.RECORDCOUNT = count; + state.setRecordCount(count); }) .catch((error) => { console.log(error); @@ -22,10 +23,10 @@ async function getData(): Promise { if (resp.ok) { return resp.json(); } - throw new Error('Something went wrong'); + throw new Error('Could not retrieve data'); }) .then(count => { - state.HEADERS = count; + state.setHeaders(count); }) .catch((error) => { console.log(error); @@ -38,8 +39,8 @@ async function getData(): Promise { window.onload = () => { // TODO: Check if buttons exits - state.firstBtn!.setAttribute("disabled", "disabled"); - state.prevBtn!.setAttribute("disabled", "disabled"); + el.firstBtn!.setAttribute("disabled", "disabled"); + el.prevBtn!.setAttribute("disabled", "disabled"); getData(); }; @@ -66,7 +67,7 @@ async function addRows(this: any, start: number, end: number, isAppend: boolean) for (let row of state.data) { let rowElement = document.createElement("tr"); // TODO: Set total records after addRows is called - state.setCountRec(state.getCountRec() + 1); + state.countRec = state.countRec + 1; for (let cellText of row) { let cellElement = document.createElement("td"); @@ -75,9 +76,9 @@ async function addRows(this: any, start: number, end: number, isAppend: boolean) rowElement.appendChild(cellElement); // Append cells } if (isAppend) { - state.tableBody!.appendChild(rowElement);// Append rows + el.tableBody!.appendChild(rowElement);// Append rows } else { - state.tableBody!.prepend(rowElement); + el.tableBody!.prepend(rowElement); } } @@ -99,7 +100,7 @@ function deleteRows(newHeight: number, diff: number) { let num = newHeight - 1; for (let i = num; i > (num + diff); i--) { - state.tableBody!.deleteRow(i); + el.tableBody!.deleteRow(i); } } @@ -111,42 +112,42 @@ function loadIntoTable() { $(".loader").fadeIn(200); // UI "Aesthetic": update buttons - state.firstBtn?.removeAttribute("disabled"); - state.prevBtn?.removeAttribute("disabled"); - state.nextBtn?.removeAttribute("disabled"); - state.lastBtn?.removeAttribute("disabled"); - - if (state.getTrimEnd() == state.RECORDCOUNT - 1) { - state.lastBtn?.setAttribute("disabled", "disabled"); - state.nextBtn?.setAttribute("disabled", "disabled"); + el.firstBtn?.removeAttribute("disabled"); + el.prevBtn?.removeAttribute("disabled"); + el.nextBtn?.removeAttribute("disabled"); + el.lastBtn?.removeAttribute("disabled"); + + if (state.trimEnd == state.getRecordCount() - 1) { + el.lastBtn?.setAttribute("disabled", "disabled"); + el.nextBtn?.setAttribute("disabled", "disabled"); } - if (state.getTrimStart() == 0) { - state.firstBtn?.setAttribute("disabled", "disabled"); - state.prevBtn?.setAttribute("disabled", "disabled"); + if (state.trimStart == 0) { + el.firstBtn?.setAttribute("disabled", "disabled"); + el.prevBtn?.setAttribute("disabled", "disabled"); } - state.pageInfo!.innerHTML = `

`; + el.pageInfo!.innerHTML = `

`; // Clear the table - state.tableHead!.innerHTML = ""; - state.tableBody!.innerHTML = ""; + el.tableHead!.innerHTML = ""; + el.tableBody!.innerHTML = ""; let headerRow = document.createElement("tr"); // Populate the headers - for (let headerText of state.HEADERS) { + for (let headerText of state.getHeaders()) { let headerElement = document.createElement("th"); headerElement.textContent = headerText; headerRow.appendChild(headerElement); } - state.tableHead!.appendChild(headerRow) + el.tableHead!.appendChild(headerRow) // Add only records that must be displayed on table - state.setCountRec(0); - addRows(state.getTrimStart(), state.getTrimEnd(), true); + state.countRec = 0; + addRows(state.trimStart, state.trimEnd, true); // Display content $(".loader").fadeOut(200); @@ -163,64 +164,64 @@ const debounce = (fn: Function, ms: number) => { }; // Search entered ID -state.searchBtn!.addEventListener("click", debounce(() => { - let id = parseInt((state.inputBox).value); - let numRecords = state.RECORDCOUNT - 1; +el.searchBtn!.addEventListener("click", debounce(() => { + let id = parseInt((el.inputBox).value); + let numRecords = state.getRecordCount() - 1; if (id < 0 || id > numRecords || isNaN(id)) { // User info: Display error message - state.pageInfo!.innerHTML = `

No records to display

`; + el.pageInfo!.innerHTML = `

No records to display

`; } else { // Use entered ID to calculate what records should display - if ((state.RECORDCOUNT - 1) - id >= state.getRecords()) { - state.setTrimStart(id); - state.setTrimEnd(state.getTrimStart() + (state.getRecords() - 1)); + if ((state.getRecordCount() - 1) - id >= state.records) { + state.trimStart = id; + state.trimEnd = state.trimStart + (state.records - 1); } else { - state.setTrimEnd(state.RECORDCOUNT - 1); - state.setTrimStart(state.getTrimEnd() - state.getRecords() + 1); + state.trimEnd = state.getRecordCount() - 1; + state.trimStart = state.trimEnd - state.records + 1; } loadIntoTable(); } - (state.inputBox).value = 'Enter ID number'; + (el.inputBox).value = 'Enter ID number'; }, 300)); // Set trim to start of data -state.firstBtn!.addEventListener("click", debounce(() => { - state.setTrimStart(0); - state.setTrimEnd(state.getTrimStart() + state.getRecords() - 1); +el.firstBtn!.addEventListener("click", debounce(() => { + state.trimStart = 0; + state.trimEnd = state.trimStart + state.records - 1; loadIntoTable(); }, 300)); // Set trim to previous data -state.prevBtn!.addEventListener("click", debounce(() => { +el.prevBtn!.addEventListener("click", debounce(() => { // If previous page is end of data && there are not enough records to fill window - if ((state.getTrimStart() - 1) - (state.getRecords() - 1) < 0) { - state.setTrimStart(0); - state.setTrimEnd(state.getTrimStart() + state.getRecords() - 1); + if ((state.trimStart - 1) - (state.records - 1) < 0) { + state.trimStart = 0; + state.trimEnd = state.trimStart + state.records - 1; } else { - state.setTrimEnd(state.getTrimStart() - 1); - state.setTrimStart(state.getTrimEnd() - state.getRecords() + 1); + state.trimEnd = state.trimStart - 1; + state.trimStart = state.trimEnd - state.records + 1; } loadIntoTable(); }, 300)); // Set trim to next data -state.nextBtn!.addEventListener("click", debounce(() => { +el.nextBtn!.addEventListener("click", debounce(() => { // If next page is end of data && there are not enough records to fill window - if ((state.RECORDCOUNT - 1) - (state.getTrimEnd() + 1) < state.getRecords()) { - state.setTrimEnd(state.RECORDCOUNT - 1); - state.setTrimStart(state.getTrimEnd() - state.getRecords() + 1); + if ((state.getRecordCount() - 1) - (state.trimEnd + 1) < state.records) { + state.trimEnd = state.getRecordCount() - 1; + state.trimStart = state.trimEnd - state.records + 1; } else { - state.setTrimStart(state.getTrimEnd() + 1); - state.setTrimEnd(state.getTrimStart() + state.getRecords() - 1); + state.trimStart = state.trimEnd + 1; + state.trimEnd = state.trimStart + state.records - 1; } loadIntoTable(); }, 300)); // Set trim to end of data -state.lastBtn!.addEventListener("click", debounce(() => { - state.setTrimEnd(state.RECORDCOUNT - 1); - state.setTrimStart(state.getTrimEnd() - state.getRecords() + 1); +el.lastBtn!.addEventListener("click", debounce(() => { + state.trimEnd = state.getRecordCount() - 1; + state.trimStart = state.trimEnd - state.records + 1; loadIntoTable(); }, 300)); @@ -230,64 +231,64 @@ window.addEventListener("resize", debounce(async () => { // Calculate number rows to be added/deleted // The calculation is an estimate of how many space there is for rows (160 is estimate space for header and footer of website) let newHeight = Math.floor((window.innerHeight - 160) / 40); - let diff = newHeight - state.getRecords(); + let diff = newHeight - state.records; - let start = state.getTrimEnd() + 1; - let end = state.getTrimEnd() + diff; + let start = state.trimEnd + 1; + let end = state.trimEnd + diff; if (diff < 0) { // Delete rows from last page - deleteRows(state.getCountRec(), diff); + deleteRows(state.countRec, diff); - state.setCountRec(state.getCountRec() + diff); - state.setTrimEnd(state.getTrimEnd() + diff); - } else if (diff > 0 && state.getTrimEnd() == state.RECORDCOUNT - 1) { + state.countRec = state.countRec + diff; + state.trimEnd = state.trimEnd + diff; + } else if (diff > 0 && state.trimEnd == state.getRecordCount() - 1) { // Prepend rows as last page gets bigger // 'start' and 'end' only fetches the amount that should be prepended - end = state.getTrimStart() - 1; - start = state.getTrimStart() - diff; + end = state.trimStart - 1; + start = state.trimStart - diff; await addRows(start, end, false); - state.setTrimStart(state.getTrimStart() - diff); - } else if (diff > 0 && end >= state.RECORDCOUNT) { + state.trimStart = state.trimStart - diff; + } else if (diff > 0 && end >= state.getRecordCount()) { // Appends remaining records until RECORDCOUNT - 1, // then prepends the rest - let addEnd = (state.RECORDCOUNT - 1) - state.getTrimEnd(); - end = state.RECORDCOUNT - 1; + let addEnd = (state.getRecordCount() - 1) - state.trimEnd; + end = state.getRecordCount() - 1; start = end - addEnd + 1; addRows(start, end, true); let addTop = diff - addEnd; - end = state.getTrimStart() - 1; - start = state.getTrimStart() - addTop; + end = state.trimStart - 1; + start = state.trimStart - addTop; await addRows(start, end, false); - state.setTrimEnd(state.RECORDCOUNT - 1); - state.setTrimStart(state.getTrimStart() - addTop) - } else if (diff > 0 && start <= state.RECORDCOUNT - 1) { + state.trimEnd = state.getRecordCount() - 1; + state.trimStart = state.trimStart - addTop + } else if (diff > 0 && start <= state.getRecordCount() - 1) { // Add rows if end of data is not yet reached addRows(start, end, true); - state.setTrimEnd(state.getTrimEnd() + diff) + state.trimEnd = state.trimEnd + diff } - state.setRecords(newHeight); + state.records = newHeight; // UI "Aesthetic": update buttons - state.firstBtn?.removeAttribute("disabled"); - state.prevBtn?.removeAttribute("disabled"); - state.nextBtn?.removeAttribute("disabled"); - state.lastBtn?.removeAttribute("disabled"); - - if (state.getTrimEnd() == state.RECORDCOUNT - 1) { - state.lastBtn?.setAttribute("disabled", "disabled"); - state.nextBtn?.setAttribute("disabled", "disabled"); + el.firstBtn?.removeAttribute("disabled"); + el.prevBtn?.removeAttribute("disabled"); + el.nextBtn?.removeAttribute("disabled"); + el.lastBtn?.removeAttribute("disabled"); + + if (state.trimEnd == state.getRecordCount() - 1) { + el.lastBtn?.setAttribute("disabled", "disabled"); + el.nextBtn?.setAttribute("disabled", "disabled"); } - if (state.getTrimStart() == 0) { - state.firstBtn?.setAttribute("disabled", "disabled"); - state.prevBtn?.setAttribute("disabled", "disabled"); + if (state.trimStart == 0) { + el.firstBtn?.setAttribute("disabled", "disabled"); + el.prevBtn?.setAttribute("disabled", "disabled"); } }, 100)); // Log window dimensions at most every 100ms diff --git a/docElement.js b/docElement.js new file mode 100644 index 00000000..eb428853 --- /dev/null +++ b/docElement.js @@ -0,0 +1,17 @@ +"use strict"; +var docElement = /** @class */ (function () { + function docElement() { + this.contentTable = document.getElementById('content-table'); + this.tableBody = this.contentTable.querySelector('tbody'); + this.tableHead = document.getElementById('content-thead'); + this.pageInfo = document.getElementById('page-info'); + this.searchBtn = document.getElementById('id-search-btn'); + this.firstBtn = document.getElementById('first'); + this.prevBtn = document.getElementById('prev'); + this.nextBtn = document.getElementById('next'); + this.lastBtn = document.getElementById('last'); + this.inputBox = document.getElementById('id-search'); + } + return docElement; +}()); +//# sourceMappingURL=docElement.js.map \ No newline at end of file diff --git a/docElement.js.map b/docElement.js.map new file mode 100644 index 00000000..fb52c3b6 --- /dev/null +++ b/docElement.js.map @@ -0,0 +1 @@ +{"version":3,"file":"docElement.js","sourceRoot":"","sources":["docElement.ts"],"names":[],"mappings":";AAAA;IAaC;QACC,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QAC7D,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,YAAa,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAC3D,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QAC1D,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QACrD,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QAC1D,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QACjD,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC/C,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;IACtD,CAAC;IACF,iBAAC;AAAD,CAAC,AAzBD,IAyBC"} \ No newline at end of file diff --git a/docElement.ts b/docElement.ts new file mode 100644 index 00000000..674f67df --- /dev/null +++ b/docElement.ts @@ -0,0 +1,26 @@ +class docElement { + + private contentTable: HTMLElement | null; + tableBody: HTMLTableSectionElement | null; + tableHead: HTMLElement | null; + pageInfo: HTMLElement | null; + searchBtn: HTMLElement | null; + firstBtn: HTMLElement | null; + prevBtn: HTMLElement | null; + nextBtn: HTMLElement | null; + lastBtn: HTMLElement | null; + inputBox: HTMLElement | null; + + constructor() { + this.contentTable = document.getElementById('content-table'); + this.tableBody = this.contentTable!.querySelector('tbody'); + this.tableHead = document.getElementById('content-thead'); + this.pageInfo = document.getElementById('page-info'); + this.searchBtn = document.getElementById('id-search-btn'); + this.firstBtn = document.getElementById('first'); + this.prevBtn = document.getElementById('prev'); + this.nextBtn = document.getElementById('next'); + this.lastBtn = document.getElementById('last'); + this.inputBox = document.getElementById('id-search'); + } +} diff --git a/index.html b/index.html index 21de8ca3..26aff2a0 100644 --- a/index.html +++ b/index.html @@ -36,6 +36,7 @@

IMQS Onboarding Project

+ diff --git a/state.js b/state.js index 81d7ff5c..2b32c797 100644 --- a/state.js +++ b/state.js @@ -1,49 +1,26 @@ "use strict"; var State = /** @class */ (function () { function State() { - this.contentTable = document.getElementById('content-table'); - this.tableBody = document.querySelector('tbody'); - this.tableHead = document.getElementById("content-thead"); - this.pageInfo = document.getElementById('page-info'); - this.searchBtn = document.getElementById('id-search-btn'); - this.firstBtn = document.getElementById('first'); - this.prevBtn = document.getElementById('prev'); - this.nextBtn = document.getElementById('next'); - this.lastBtn = document.getElementById('last'); - this.inputBox = document.getElementById('id-search'); - // Default values for variables that stores server data - this.RECORDCOUNT = 350; - this.HEADERS = ["ID", "City", "Population"]; - this.data = [[0, "Cape Town", 3500000], [1, "New York", 8500000], [2, "Johannesburg", 4500000]]; this.records = this.calculateRecords(); this.trimStart = 0; this.trimEnd = this.records - 1; this.countRec = 0; + this.RECORDCOUNT = 350; + this.HEADERS = ["ID", "City", "Population"]; + this.data = [[0, "Cape Town", 3500000], [1, "New York", 8500000], [2, "Johannesburg", 4500000]]; } - State.prototype.getRecords = function () { - return this.records; - }; State.prototype.getTrimStart = function () { return this.trimStart; }; State.prototype.getTrimEnd = function () { return this.trimEnd; }; - State.prototype.getCountRec = function () { - return this.countRec; - }; - State.prototype.setRecords = function (value) { - this.records = value; - }; State.prototype.setTrimStart = function (value) { this.trimStart = value; }; State.prototype.setTrimEnd = function (value) { this.trimEnd = value; }; - State.prototype.setCountRec = function (value) { - this.countRec = value; - }; State.prototype.calculateRecords = function () { return Math.floor((window.innerHeight - 160) / 40); // Estimate of available table space }; diff --git a/state.js.map b/state.js.map index ea1f789c..e0957de9 100644 --- a/state.js.map +++ b/state.js.map @@ -1 +1 @@ -{"version":3,"file":"state.js","sourceRoot":"","sources":["state.ts"],"names":[],"mappings":";AAAA;IAsBC;QAhBA,iBAAY,GAAuB,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QAC5E,cAAS,GAAmC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAC5E,cAAS,GAAuB,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QACzE,aAAQ,GAAuB,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QACpE,cAAS,GAAuB,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QACzE,aAAQ,GAAuB,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAChE,YAAO,GAAuB,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC9D,YAAO,GAAuB,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC9D,YAAO,GAAuB,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC9D,aAAQ,GAAuB,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QAEpE,uDAAuD;QACvD,gBAAW,GAAW,GAAG,CAAC;QAC1B,YAAO,GAAa,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QACjD,SAAI,GAAQ,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC;QAG/F,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACvC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QACnB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;QAChC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;IACnB,CAAC;IAED,0BAAU,GAAV;QACC,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED,4BAAY,GAAZ;QACC,OAAO,IAAI,CAAC,SAAS,CAAC;IACvB,CAAC;IAED,0BAAU,GAAV;QACC,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED,2BAAW,GAAX;QACC,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;IAED,0BAAU,GAAV,UAAW,KAAa;QACvB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,4BAAY,GAAZ,UAAa,KAAa;QACzB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;IACxB,CAAC;IAED,0BAAU,GAAV,UAAW,KAAa;QACvB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,2BAAW,GAAX,UAAY,KAAa;QACxB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;IACvB,CAAC;IAED,gCAAgB,GAAhB;QACC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,WAAW,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,oCAAoC;IACzF,CAAC;IACF,YAAC;AAAD,CAAC,AAhED,IAgEC"} \ No newline at end of file +{"version":3,"file":"state.js","sourceRoot":"","sources":["state.ts"],"names":[],"mappings":";AAAA;IAYC;QACC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACvC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QACnB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;QAChC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;QAElB,IAAI,CAAC,WAAW,GAAG,GAAG,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC;IACjG,CAAC;IAED,4BAAY,GAAZ;QACC,OAAO,IAAI,CAAC,SAAS,CAAC;IACvB,CAAC;IAED,0BAAU,GAAV;QACC,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED,4BAAY,GAAZ,UAAa,KAAa;QACzB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;IACxB,CAAC;IAED,0BAAU,GAAV,UAAW,KAAa;QACvB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,gCAAgB,GAAhB;QACC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,WAAW,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,oCAAoC;IACzF,CAAC;IACF,YAAC;AAAD,CAAC,AA1CD,IA0CC"} \ No newline at end of file diff --git a/state.ts b/state.ts index 3b59afbb..8277bf9c 100644 --- a/state.ts +++ b/state.ts @@ -1,66 +1,44 @@ class State { - // TODO: change variable to public/private and add/remove getters and setters - private records: number; - private trimStart: number; - private trimEnd: number; - private countRec: number; - - contentTable: HTMLElement | null = document.getElementById('content-table'); - tableBody: HTMLTableSectionElement | null = document.querySelector('tbody'); - tableHead: HTMLElement | null = document.getElementById("content-thead"); - pageInfo: HTMLElement | null = document.getElementById('page-info'); - searchBtn: HTMLElement | null = document.getElementById('id-search-btn'); - firstBtn: HTMLElement | null = document.getElementById('first'); - prevBtn: HTMLElement | null = document.getElementById('prev'); - nextBtn: HTMLElement | null = document.getElementById('next'); - lastBtn: HTMLElement | null = document.getElementById('last'); - inputBox: HTMLElement | null = document.getElementById('id-search'); + records: number; + trimStart: number; + trimEnd: number; + countRec: number; // Default values for variables that stores server data - RECORDCOUNT: number = 350; - HEADERS: string[] = ["ID", "City", "Population"]; - data: any = [[0, "Cape Town", 3500000], [1, "New York", 8500000], [2, "Johannesburg", 4500000]]; + private RECORDCOUNT: number; + private HEADERS: string[]; + data: any; constructor() { this.records = this.calculateRecords(); this.trimStart = 0; this.trimEnd = this.records - 1; this.countRec = 0; - } - - getRecords() { - return this.records; - } - - getTrimStart() { - return this.trimStart; - } - - getTrimEnd() { - return this.trimEnd; - } - getCountRec() { - return this.countRec; + this.RECORDCOUNT = 350; + this.HEADERS = ["ID", "City", "Population"]; + this.data = [[0, "Cape Town", 3500000], [1, "New York", 8500000], [2, "Johannesburg", 4500000]]; } - setRecords(value: number) { - this.records = value; + getRecordCount() { + return this.RECORDCOUNT; } - setTrimStart(value: number) { - this.trimStart = value; + getHeaders() { + return this.HEADERS; } - setTrimEnd(value: number) { - this.trimEnd = value; + setRecordCount(value: number) { + this.RECORDCOUNT = value; } - setCountRec(value: number) { - this.countRec = value; + setHeaders(value: string[]) { + this.HEADERS = value; } calculateRecords() { - return Math.floor((window.innerHeight - 160) / 40); // Estimate of available table space + // Estimate of available table space + // The calculation is an estimate of how many space there is for rows (160 is estimate space for header and footer of website) + return Math.floor((window.innerHeight - 160) / 40); } } From 3eb7c41072273d724bf9ea1c13773d3dc752d9c6 Mon Sep 17 00:00:00 2001 From: CelesteNaude <286celeste@gmail.com> Date: Thu, 10 Mar 2022 12:56:53 +0200 Subject: [PATCH 17/19] Fixed add rows function again --- app.ts | 75 ++++++++++++++++++++++++----------------------- docElement.js | 3 +- docElement.js.map | 2 +- docElement.ts | 6 ++-- index.html | 2 +- state.js | 23 ++++++++------- state.js.map | 2 +- state.ts | 6 ++-- 8 files changed, 64 insertions(+), 55 deletions(-) diff --git a/app.ts b/app.ts index af2cdd7f..92814993 100644 --- a/app.ts +++ b/app.ts @@ -37,25 +37,21 @@ async function getData(): Promise { // TODO: Add return statement } -window.onload = () => { - // TODO: Check if buttons exits - el.firstBtn!.setAttribute("disabled", "disabled"); - el.prevBtn!.setAttribute("disabled", "disabled"); - getData(); +window.onload = async () => { + await getData(); + console.log(state.getRecordCount()) }; -// TODO: Fix add rows // Add rows to table async function addRows(this: any, start: number, end: number, isAppend: boolean) { - // let newTableBody = document.createElement("tbody"); - // let reversedTableBody = document.createElement("tbody"); + let link = "/records?from=" + start + "&to=" + end; await fetch(link) .then(resp => { if (resp.ok) { return resp.json(); } - throw new Error('Something went wrong'); + throw new Error('Could not retrieve data'); }) .then(count => { state.data = count; @@ -64,35 +60,43 @@ async function addRows(this: any, start: number, end: number, isAppend: boolean) console.log(error); }); - for (let row of state.data) { - let rowElement = document.createElement("tr"); - // TODO: Set total records after addRows is called - state.countRec = state.countRec + 1; + // Append or prepend rows to table + if (isAppend) { + for (let row of state.data) { + let rowElement = document.createElement("tr"); - for (let cellText of row) { - let cellElement = document.createElement("td"); + for (let cellText of row) { + let cellElement = document.createElement("td"); - cellElement.textContent = cellText; - rowElement.appendChild(cellElement); // Append cells - } - if (isAppend) { + cellElement.textContent = cellText; + rowElement.appendChild(cellElement); // Append cells + } el.tableBody!.appendChild(rowElement);// Append rows - } else { - el.tableBody!.prepend(rowElement); } - } + } else { + // Reverse order of data and save in temp variable + let rowData: any; + rowData = []; + let k = 0; + for (let i = state.data.length - 1; i >= 0; i--) { + rowData[k] = state.data[i]; + k++; + } + + // Use temp variable to append rows to table in correct order + for (let row of rowData) { + let rowElement = document.createElement("tr"); + + for (let cellText of row) { + let cellElement = document.createElement("td"); - // TODO: Fix prepend feature - // let rows = newTableBody!.rows; - // if (isAppend) { - // this.tableBody.parentNode.replaceChild(newTableBody, this.tableBody)// Append rows - // } - // else { - // for (let i = rows.length - 1; i >= 0; i--) { - // reversedTableBody!.appendChild(rows[i]); // Prepend rows - // } - // contentTable!.prepend(reversedTableBody); - // } + cellElement.textContent = cellText; + rowElement.appendChild(cellElement); // Append cells + } + el.tableBody!.prepend(rowElement);// Prepend rows + } + } + el.contentTable!.appendChild(el.tableBody!); } // Delete rows from table @@ -132,6 +136,7 @@ function loadIntoTable() { // Clear the table el.tableHead!.innerHTML = ""; el.tableBody!.innerHTML = ""; + el.reversedTableBody!.innerHTML = ""; let headerRow = document.createElement("tr"); @@ -146,7 +151,6 @@ function loadIntoTable() { el.tableHead!.appendChild(headerRow) // Add only records that must be displayed on table - state.countRec = 0; addRows(state.trimStart, state.trimEnd, true); // Display content @@ -238,9 +242,8 @@ window.addEventListener("resize", debounce(async () => { if (diff < 0) { // Delete rows from last page - deleteRows(state.countRec, diff); + deleteRows(state.records, diff); - state.countRec = state.countRec + diff; state.trimEnd = state.trimEnd + diff; } else if (diff > 0 && state.trimEnd == state.getRecordCount() - 1) { // Prepend rows as last page gets bigger diff --git a/docElement.js b/docElement.js index eb428853..3c020860 100644 --- a/docElement.js +++ b/docElement.js @@ -2,7 +2,8 @@ var docElement = /** @class */ (function () { function docElement() { this.contentTable = document.getElementById('content-table'); - this.tableBody = this.contentTable.querySelector('tbody'); + this.tableBody = document.createElement('tbody'); + this.reversedTableBody = document.createElement('tbody'); this.tableHead = document.getElementById('content-thead'); this.pageInfo = document.getElementById('page-info'); this.searchBtn = document.getElementById('id-search-btn'); diff --git a/docElement.js.map b/docElement.js.map index fb52c3b6..af83dd33 100644 --- a/docElement.js.map +++ b/docElement.js.map @@ -1 +1 @@ -{"version":3,"file":"docElement.js","sourceRoot":"","sources":["docElement.ts"],"names":[],"mappings":";AAAA;IAaC;QACC,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QAC7D,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,YAAa,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAC3D,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QAC1D,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QACrD,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QAC1D,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QACjD,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC/C,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;IACtD,CAAC;IACF,iBAAC;AAAD,CAAC,AAzBD,IAyBC"} \ No newline at end of file +{"version":3,"file":"docElement.js","sourceRoot":"","sources":["docElement.ts"],"names":[],"mappings":";AAAA;IAcC;QACC,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QAC7D,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QACjD,IAAI,CAAC,iBAAiB,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QACzD,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QAC1D,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QACrD,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QAC1D,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QACjD,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC/C,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;IACtD,CAAC;IACF,iBAAC;AAAD,CAAC,AA3BD,IA2BC"} \ No newline at end of file diff --git a/docElement.ts b/docElement.ts index 674f67df..96d8d101 100644 --- a/docElement.ts +++ b/docElement.ts @@ -1,7 +1,8 @@ class docElement { - private contentTable: HTMLElement | null; + contentTable: HTMLElement | null; tableBody: HTMLTableSectionElement | null; + reversedTableBody: HTMLTableSectionElement | null; tableHead: HTMLElement | null; pageInfo: HTMLElement | null; searchBtn: HTMLElement | null; @@ -13,7 +14,8 @@ class docElement { constructor() { this.contentTable = document.getElementById('content-table'); - this.tableBody = this.contentTable!.querySelector('tbody'); + this.tableBody = document.createElement('tbody'); + this.reversedTableBody = document.createElement('tbody'); this.tableHead = document.getElementById('content-thead'); this.pageInfo = document.getElementById('page-info'); this.searchBtn = document.getElementById('id-search-btn'); diff --git a/index.html b/index.html index 26aff2a0..ac236142 100644 --- a/index.html +++ b/index.html @@ -22,7 +22,7 @@

IMQS Onboarding Project

- +
diff --git a/state.js b/state.js index 2b32c797..68dec9c7 100644 --- a/state.js +++ b/state.js @@ -4,25 +4,28 @@ var State = /** @class */ (function () { this.records = this.calculateRecords(); this.trimStart = 0; this.trimEnd = this.records - 1; - this.countRec = 0; + this.isDefaultNode = true; + // Default values for variables that stores server data this.RECORDCOUNT = 350; this.HEADERS = ["ID", "City", "Population"]; this.data = [[0, "Cape Town", 3500000], [1, "New York", 8500000], [2, "Johannesburg", 4500000]]; } - State.prototype.getTrimStart = function () { - return this.trimStart; + State.prototype.getRecordCount = function () { + return this.RECORDCOUNT; }; - State.prototype.getTrimEnd = function () { - return this.trimEnd; + State.prototype.getHeaders = function () { + return this.HEADERS; }; - State.prototype.setTrimStart = function (value) { - this.trimStart = value; + State.prototype.setRecordCount = function (value) { + this.RECORDCOUNT = value; }; - State.prototype.setTrimEnd = function (value) { - this.trimEnd = value; + State.prototype.setHeaders = function (value) { + this.HEADERS = value; }; State.prototype.calculateRecords = function () { - return Math.floor((window.innerHeight - 160) / 40); // Estimate of available table space + // Estimate of available table space + // The calculation is an estimate of how many space there is for rows (160 is estimate space for header and footer of website) + return Math.floor((window.innerHeight - 160) / 40); }; return State; }()); diff --git a/state.js.map b/state.js.map index e0957de9..1858e3c0 100644 --- a/state.js.map +++ b/state.js.map @@ -1 +1 @@ -{"version":3,"file":"state.js","sourceRoot":"","sources":["state.ts"],"names":[],"mappings":";AAAA;IAYC;QACC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACvC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QACnB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;QAChC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;QAElB,IAAI,CAAC,WAAW,GAAG,GAAG,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC;IACjG,CAAC;IAED,4BAAY,GAAZ;QACC,OAAO,IAAI,CAAC,SAAS,CAAC;IACvB,CAAC;IAED,0BAAU,GAAV;QACC,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED,4BAAY,GAAZ,UAAa,KAAa;QACzB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;IACxB,CAAC;IAED,0BAAU,GAAV,UAAW,KAAa;QACvB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,gCAAgB,GAAhB;QACC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,WAAW,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,oCAAoC;IACzF,CAAC;IACF,YAAC;AAAD,CAAC,AA1CD,IA0CC"} \ No newline at end of file +{"version":3,"file":"state.js","sourceRoot":"","sources":["state.ts"],"names":[],"mappings":";AAAA;IAUC;QACC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACvC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QACnB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;QAChC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAE1B,uDAAuD;QACvD,IAAI,CAAC,WAAW,GAAG,GAAG,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC;IACjG,CAAC;IAED,8BAAc,GAAd;QACC,OAAO,IAAI,CAAC,WAAW,CAAC;IACzB,CAAC;IAED,0BAAU,GAAV;QACC,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED,8BAAc,GAAd,UAAe,KAAa;QAC3B,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;IAC1B,CAAC;IAED,0BAAU,GAAV,UAAW,KAAe;QACzB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,gCAAgB,GAAhB;QACC,oCAAoC;QACpC,8HAA8H;QAC9H,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,WAAW,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;IACpD,CAAC;IACF,YAAC;AAAD,CAAC,AA3CD,IA2CC"} \ No newline at end of file diff --git a/state.ts b/state.ts index 8277bf9c..5b969181 100644 --- a/state.ts +++ b/state.ts @@ -2,9 +2,8 @@ class State { records: number; trimStart: number; trimEnd: number; - countRec: number; + isDefaultNode: boolean; - // Default values for variables that stores server data private RECORDCOUNT: number; private HEADERS: string[]; data: any; @@ -13,8 +12,9 @@ class State { this.records = this.calculateRecords(); this.trimStart = 0; this.trimEnd = this.records - 1; - this.countRec = 0; + this.isDefaultNode = true; + // Default values for variables that stores server data this.RECORDCOUNT = 350; this.HEADERS = ["ID", "City", "Population"]; this.data = [[0, "Cape Town", 3500000], [1, "New York", 8500000], [2, "Johannesburg", 4500000]]; From be96066a9a0f7e2e572fb4d464e3d01ee074c78b Mon Sep 17 00:00:00 2001 From: CelesteNaude <286celeste@gmail.com> Date: Fri, 11 Mar 2022 16:49:49 +0200 Subject: [PATCH 18/19] Class restructure --- app.ts | 350 ++++++++-------------------------------------- docElement.js | 18 --- docElement.js.map | 1 - docElement.ts | 28 ---- index.html | 3 +- state.js | 348 ++++++++++++++++++++++++++++++++++++++++++++- state.js.map | 2 +- state.ts | 317 ++++++++++++++++++++++++++++++++++++++++- 8 files changed, 723 insertions(+), 344 deletions(-) delete mode 100644 docElement.js delete mode 100644 docElement.js.map delete mode 100644 docElement.ts diff --git a/app.ts b/app.ts index 92814993..9f80c060 100644 --- a/app.ts +++ b/app.ts @@ -1,162 +1,15 @@ -let state = new State(); -let el = new docElement(); - -// Fetch headers and record count -async function getData(): Promise { - // API calls for record count and headers - await fetch('/recordCount') - .then(resp => { - if (resp.ok) { - return resp.json(); - } - throw new Error('Could not retrieve data'); - }) - .then(count => { - state.setRecordCount(count); - }) - .catch((error) => { - console.log(error); - }); - - await fetch('/columns') - .then(resp => { - if (resp.ok) { - return resp.json(); - } - throw new Error('Could not retrieve data'); - }) - .then(count => { - state.setHeaders(count); - }) - .catch((error) => { - console.log(error); - }); - - // Populate table with fetched data - loadIntoTable(); - // TODO: Add return statement -} window.onload = async () => { - await getData(); - console.log(state.getRecordCount()) -}; - -// Add rows to table -async function addRows(this: any, start: number, end: number, isAppend: boolean) { + let state = new State(); - let link = "/records?from=" + start + "&to=" + end; - await fetch(link) + // Get data from server and load into table + await state.getData() .then(resp => { - if (resp.ok) { - return resp.json(); + if (resp == true) { + state.loadIntoTable(true); } - throw new Error('Could not retrieve data'); - }) - .then(count => { - state.data = count; }) - .catch((error) => { - console.log(error); - }); - - // Append or prepend rows to table - if (isAppend) { - for (let row of state.data) { - let rowElement = document.createElement("tr"); - - for (let cellText of row) { - let cellElement = document.createElement("td"); - - cellElement.textContent = cellText; - rowElement.appendChild(cellElement); // Append cells - } - el.tableBody!.appendChild(rowElement);// Append rows - } - } else { - // Reverse order of data and save in temp variable - let rowData: any; - rowData = []; - let k = 0; - for (let i = state.data.length - 1; i >= 0; i--) { - rowData[k] = state.data[i]; - k++; - } - - // Use temp variable to append rows to table in correct order - for (let row of rowData) { - let rowElement = document.createElement("tr"); - - for (let cellText of row) { - let cellElement = document.createElement("td"); - - cellElement.textContent = cellText; - rowElement.appendChild(cellElement); // Append cells - } - el.tableBody!.prepend(rowElement);// Prepend rows - } - } - el.contentTable!.appendChild(el.tableBody!); -} - -// Delete rows from table -function deleteRows(newHeight: number, diff: number) { - let num = newHeight - 1; - - for (let i = num; i > (num + diff); i--) { - el.tableBody!.deleteRow(i); - } -} - -// Load json data into table function -function loadIntoTable() { - - // Display loader - $(".content").fadeOut(200); - $(".loader").fadeIn(200); - - // UI "Aesthetic": update buttons - el.firstBtn?.removeAttribute("disabled"); - el.prevBtn?.removeAttribute("disabled"); - el.nextBtn?.removeAttribute("disabled"); - el.lastBtn?.removeAttribute("disabled"); - - if (state.trimEnd == state.getRecordCount() - 1) { - el.lastBtn?.setAttribute("disabled", "disabled"); - el.nextBtn?.setAttribute("disabled", "disabled"); - } - - if (state.trimStart == 0) { - el.firstBtn?.setAttribute("disabled", "disabled"); - el.prevBtn?.setAttribute("disabled", "disabled"); - } - - el.pageInfo!.innerHTML = `

`; - - // Clear the table - el.tableHead!.innerHTML = ""; - el.tableBody!.innerHTML = ""; - el.reversedTableBody!.innerHTML = ""; - - let headerRow = document.createElement("tr"); - - // Populate the headers - for (let headerText of state.getHeaders()) { - let headerElement = document.createElement("th"); - - headerElement.textContent = headerText; - headerRow.appendChild(headerElement); - } - - el.tableHead!.appendChild(headerRow) - - // Add only records that must be displayed on table - addRows(state.trimStart, state.trimEnd, true); - - // Display content - $(".loader").fadeOut(200); - $(".content").fadeIn(200); -} +}; // Code is only triggered once per user input const debounce = (fn: Function, ms: number) => { @@ -168,152 +21,67 @@ const debounce = (fn: Function, ms: number) => { }; // Search entered ID -el.searchBtn!.addEventListener("click", debounce(() => { - let id = parseInt((el.inputBox).value); - let numRecords = state.getRecordCount() - 1; - - if (id < 0 || id > numRecords || isNaN(id)) { - // User info: Display error message - el.pageInfo!.innerHTML = `

No records to display

`; - } else { - // Use entered ID to calculate what records should display - if ((state.getRecordCount() - 1) - id >= state.records) { - state.trimStart = id; - state.trimEnd = state.trimStart + (state.records - 1); - } else { - state.trimEnd = state.getRecordCount() - 1; - state.trimStart = state.trimEnd - state.records + 1; - } - loadIntoTable(); - } - (el.inputBox).value = 'Enter ID number'; -}, 300)); +document.getElementById('id-search-btn')!.addEventListener("click", debounce(async () => { + let state = new State(); + await state.getData() + .then(resp => { + if (resp == true) { + state.searchId(); + } + }) +}, 250)); // Set trim to start of data -el.firstBtn!.addEventListener("click", debounce(() => { - state.trimStart = 0; - state.trimEnd = state.trimStart + state.records - 1; - loadIntoTable(); -}, 300)); +document.getElementById('first')!.addEventListener("click", debounce(async () => { + let state = new State(); + await state.getData() + .then(resp => { + if (resp == true) { + state.goToFirst(); + } + }) +}, 250)); // Set trim to previous data -el.prevBtn!.addEventListener("click", debounce(() => { - // If previous page is end of data && there are not enough records to fill window - if ((state.trimStart - 1) - (state.records - 1) < 0) { - state.trimStart = 0; - state.trimEnd = state.trimStart + state.records - 1; - } else { - state.trimEnd = state.trimStart - 1; - state.trimStart = state.trimEnd - state.records + 1; - } - loadIntoTable(); -}, 300)); +document.getElementById('prev')!.addEventListener("click", debounce(async () => { + let state = new State(); + await state.getData() + .then(resp => { + if (resp == true) { + state.goToPrev(); + } + }) +}, 250)); // Set trim to next data -el.nextBtn!.addEventListener("click", debounce(() => { - // If next page is end of data && there are not enough records to fill window - if ((state.getRecordCount() - 1) - (state.trimEnd + 1) < state.records) { - state.trimEnd = state.getRecordCount() - 1; - state.trimStart = state.trimEnd - state.records + 1; - } else { - state.trimStart = state.trimEnd + 1; - state.trimEnd = state.trimStart + state.records - 1; - } - loadIntoTable(); -}, 300)); +document.getElementById('next')!.addEventListener("click", debounce(async () => { + let state = new State(); + await state.getData() + .then(resp => { + if (resp == true) { + state.goToNext(); + } + }) +}, 250)); // Set trim to end of data -el.lastBtn!.addEventListener("click", debounce(() => { - state.trimEnd = state.getRecordCount() - 1; - state.trimStart = state.trimEnd - state.records + 1; - loadIntoTable(); -}, 300)); +document.getElementById('last')!.addEventListener("click", debounce(async () => { + let state = new State(); + await state.getData() + .then(resp => { + if (resp == true) { + state.goToLast(); + } + }) +}, 250)); // Add/remove rows from table based on resize event of the window window.addEventListener("resize", debounce(async () => { - - // Calculate number rows to be added/deleted - // The calculation is an estimate of how many space there is for rows (160 is estimate space for header and footer of website) - let newHeight = Math.floor((window.innerHeight - 160) / 40); - let diff = newHeight - state.records; - - let start = state.trimEnd + 1; - let end = state.trimEnd + diff; - - if (diff < 0) { - // Delete rows from last page - deleteRows(state.records, diff); - - state.trimEnd = state.trimEnd + diff; - } else if (diff > 0 && state.trimEnd == state.getRecordCount() - 1) { - // Prepend rows as last page gets bigger - // 'start' and 'end' only fetches the amount that should be prepended - end = state.trimStart - 1; - start = state.trimStart - diff; - - await addRows(start, end, false); - - state.trimStart = state.trimStart - diff; - } else if (diff > 0 && end >= state.getRecordCount()) { - // Appends remaining records until RECORDCOUNT - 1, - // then prepends the rest - let addEnd = (state.getRecordCount() - 1) - state.trimEnd; - end = state.getRecordCount() - 1; - start = end - addEnd + 1; - addRows(start, end, true); - - let addTop = diff - addEnd; - end = state.trimStart - 1; - start = state.trimStart - addTop; - - await addRows(start, end, false); - - state.trimEnd = state.getRecordCount() - 1; - state.trimStart = state.trimStart - addTop - } else if (diff > 0 && start <= state.getRecordCount() - 1) { - // Add rows if end of data is not yet reached - addRows(start, end, true); - - state.trimEnd = state.trimEnd + diff - } - state.records = newHeight; - - // UI "Aesthetic": update buttons - el.firstBtn?.removeAttribute("disabled"); - el.prevBtn?.removeAttribute("disabled"); - el.nextBtn?.removeAttribute("disabled"); - el.lastBtn?.removeAttribute("disabled"); - - if (state.trimEnd == state.getRecordCount() - 1) { - el.lastBtn?.setAttribute("disabled", "disabled"); - el.nextBtn?.setAttribute("disabled", "disabled"); - } - - if (state.trimStart == 0) { - el.firstBtn?.setAttribute("disabled", "disabled"); - el.prevBtn?.setAttribute("disabled", "disabled"); - } -}, 100)); // Log window dimensions at most every 100ms - - - - - - - - - - - - - - -// o o -// /^^^^^7 -// ' ' ,oO))))))))Oo, -// ,'))))))))))))))), /{ -// ' ,'o ))))))))))))))))={ -// > ))))))))))))))))={ -// `, ))))))\ \)))))))={ -// ',))))))))\/)))))' \{ -// '*O))))))))O*' + let state = new State(); + await state.getData() + .then(resp => { + if (resp == true) { + state.resize(); + } + }) +}, 150)); // Log window dimensions at most every 100ms diff --git a/docElement.js b/docElement.js deleted file mode 100644 index 3c020860..00000000 --- a/docElement.js +++ /dev/null @@ -1,18 +0,0 @@ -"use strict"; -var docElement = /** @class */ (function () { - function docElement() { - this.contentTable = document.getElementById('content-table'); - this.tableBody = document.createElement('tbody'); - this.reversedTableBody = document.createElement('tbody'); - this.tableHead = document.getElementById('content-thead'); - this.pageInfo = document.getElementById('page-info'); - this.searchBtn = document.getElementById('id-search-btn'); - this.firstBtn = document.getElementById('first'); - this.prevBtn = document.getElementById('prev'); - this.nextBtn = document.getElementById('next'); - this.lastBtn = document.getElementById('last'); - this.inputBox = document.getElementById('id-search'); - } - return docElement; -}()); -//# sourceMappingURL=docElement.js.map \ No newline at end of file diff --git a/docElement.js.map b/docElement.js.map deleted file mode 100644 index af83dd33..00000000 --- a/docElement.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"docElement.js","sourceRoot":"","sources":["docElement.ts"],"names":[],"mappings":";AAAA;IAcC;QACC,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QAC7D,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QACjD,IAAI,CAAC,iBAAiB,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QACzD,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QAC1D,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QACrD,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QAC1D,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QACjD,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC/C,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;IACtD,CAAC;IACF,iBAAC;AAAD,CAAC,AA3BD,IA2BC"} \ No newline at end of file diff --git a/docElement.ts b/docElement.ts deleted file mode 100644 index 96d8d101..00000000 --- a/docElement.ts +++ /dev/null @@ -1,28 +0,0 @@ -class docElement { - - contentTable: HTMLElement | null; - tableBody: HTMLTableSectionElement | null; - reversedTableBody: HTMLTableSectionElement | null; - tableHead: HTMLElement | null; - pageInfo: HTMLElement | null; - searchBtn: HTMLElement | null; - firstBtn: HTMLElement | null; - prevBtn: HTMLElement | null; - nextBtn: HTMLElement | null; - lastBtn: HTMLElement | null; - inputBox: HTMLElement | null; - - constructor() { - this.contentTable = document.getElementById('content-table'); - this.tableBody = document.createElement('tbody'); - this.reversedTableBody = document.createElement('tbody'); - this.tableHead = document.getElementById('content-thead'); - this.pageInfo = document.getElementById('page-info'); - this.searchBtn = document.getElementById('id-search-btn'); - this.firstBtn = document.getElementById('first'); - this.prevBtn = document.getElementById('prev'); - this.nextBtn = document.getElementById('next'); - this.lastBtn = document.getElementById('last'); - this.inputBox = document.getElementById('id-search'); - } -} diff --git a/index.html b/index.html index ac236142..21de8ca3 100644 --- a/index.html +++ b/index.html @@ -22,7 +22,7 @@

IMQS Onboarding Project

- +
@@ -36,7 +36,6 @@

IMQS Onboarding Project

- diff --git a/state.js b/state.js index 68dec9c7..748fee42 100644 --- a/state.js +++ b/state.js @@ -1,14 +1,59 @@ "use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; var State = /** @class */ (function () { function State() { this.records = this.calculateRecords(); this.trimStart = 0; this.trimEnd = this.records - 1; - this.isDefaultNode = true; // Default values for variables that stores server data this.RECORDCOUNT = 350; this.HEADERS = ["ID", "City", "Population"]; this.data = [[0, "Cape Town", 3500000], [1, "New York", 8500000], [2, "Johannesburg", 4500000]]; + this.contentTable = document.getElementById('content-table'); + this.tableBody = document.querySelector('tbody'); + this.tableHead = document.getElementById('content-thead'); + this.pageInfo = document.getElementById('page-info'); + this.searchBtn = document.getElementById('id-search-btn'); + this.firstBtn = document.getElementById('first'); + this.prevBtn = document.getElementById('prev'); + this.nextBtn = document.getElementById('next'); + this.lastBtn = document.getElementById('last'); + this.inputBox = document.getElementById('id-search'); } State.prototype.getRecordCount = function () { return this.RECORDCOUNT; @@ -27,6 +72,307 @@ var State = /** @class */ (function () { // The calculation is an estimate of how many space there is for rows (160 is estimate space for header and footer of website) return Math.floor((window.innerHeight - 160) / 40); }; + State.prototype.setCurrentState = function () { + var tableBody = document.querySelector('tbody'); + this.records = tableBody.rows.length; + if (this.records != 0) { + this.trimStart = parseInt(tableBody.rows[0].cells[0].innerHTML); + this.trimEnd = parseInt(tableBody.rows[this.records - 1].cells[0].innerHTML); + } + else { + return; + } + console.log("Num records: ", this.records, " start: ", this.trimStart, " end: ", this.trimEnd); + }; + // Fetch headers and record count + State.prototype.getData = function () { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + // API calls for record count and headers + return [4 /*yield*/, fetch('/recordCount') + .then(function (resp) { + if (resp.ok) { + return resp.json(); + } + throw new Error('Could not retrieve data'); + }) + .then(function (count) { + _this.setRecordCount(count); + }) + .catch(function (error) { + console.log(error); + })]; + case 1: + // API calls for record count and headers + _a.sent(); + return [4 /*yield*/, fetch('/columns') + .then(function (resp) { + if (resp.ok) { + return resp.json(); + } + throw new Error('Could not retrieve data'); + }) + .then(function (count) { + _this.setHeaders(count); + }) + .catch(function (error) { + console.log(error); + })]; + case 2: + _a.sent(); + return [2 /*return*/, true]; + } + }); + }); + }; + // Add rows to table + State.prototype.addRows = function (start, end, isAppend) { + return __awaiter(this, void 0, void 0, function () { + var table, newTableBody, link, _i, _a, row, rowElement, _b, row_1, cellText, cellElement, rowData, k, i, _c, rowData_1, row, rowElement, _d, row_2, cellText, cellElement; + var _this = this; + return __generator(this, function (_e) { + switch (_e.label) { + case 0: + table = document.getElementById("content-table"); + newTableBody = document.createElement("tbody"); + link = "/records?from=" + start + "&to=" + end; + return [4 /*yield*/, fetch(link) + .then(function (resp) { + if (resp.ok) { + return resp.json(); + } + throw new Error('Could not retrieve data'); + }) + .then(function (count) { + _this.data = count; + }) + .catch(function (error) { + console.log(error); + })]; + case 1: + _e.sent(); + // Append or prepend rows to table + if (isAppend) { + for (_i = 0, _a = this.data; _i < _a.length; _i++) { + row = _a[_i]; + rowElement = document.createElement("tr"); + for (_b = 0, row_1 = row; _b < row_1.length; _b++) { + cellText = row_1[_b]; + cellElement = document.createElement("td"); + cellElement.textContent = cellText; + rowElement.appendChild(cellElement); // Append cells + } + newTableBody.appendChild(rowElement); // Append rows + } + } + else { + rowData = void 0; + rowData = []; + k = 0; + for (i = this.data.length - 1; i >= 0; i--) { + rowData[k] = this.data[i]; + k++; + } + // Use temp variable to append rows to table in correct order + for (_c = 0, rowData_1 = rowData; _c < rowData_1.length; _c++) { + row = rowData_1[_c]; + rowElement = document.createElement("tr"); + for (_d = 0, row_2 = row; _d < row_2.length; _d++) { + cellText = row_2[_d]; + cellElement = document.createElement("td"); + cellElement.textContent = cellText; + rowElement.appendChild(cellElement); // Append cells + } + newTableBody.prepend(rowElement); // Prepend rows + } + } + if (!table) + return [2 /*return*/]; + table.replaceChild(newTableBody, this.tableBody); + return [2 /*return*/]; + } + }); + }); + }; + // Delete rows from table + State.prototype.deleteRows = function (newHeight, diff) { + var num = newHeight - 1; + for (var i = num; i > (num + diff); i--) { + this.tableBody.deleteRow(i); + } + }; + // Load json data into table function + State.prototype.loadIntoTable = function (clearHeader) { + var _a, _b, _c, _d, _e, _f, _g, _h; + // Display loader + $(".content").fadeOut(200); + $(".loader").fadeIn(200); + // UI "Aesthetic": update buttons + (_a = this.firstBtn) === null || _a === void 0 ? void 0 : _a.removeAttribute("disabled"); + (_b = this.prevBtn) === null || _b === void 0 ? void 0 : _b.removeAttribute("disabled"); + (_c = this.nextBtn) === null || _c === void 0 ? void 0 : _c.removeAttribute("disabled"); + (_d = this.lastBtn) === null || _d === void 0 ? void 0 : _d.removeAttribute("disabled"); + if (this.trimEnd == this.getRecordCount() - 1) { + (_e = this.lastBtn) === null || _e === void 0 ? void 0 : _e.setAttribute("disabled", "disabled"); + (_f = this.nextBtn) === null || _f === void 0 ? void 0 : _f.setAttribute("disabled", "disabled"); + } + if (this.trimStart == 0) { + (_g = this.firstBtn) === null || _g === void 0 ? void 0 : _g.setAttribute("disabled", "disabled"); + (_h = this.prevBtn) === null || _h === void 0 ? void 0 : _h.setAttribute("disabled", "disabled"); + } + this.pageInfo.innerHTML = "

"; + if (clearHeader) { + this.tableHead.innerHTML = ""; + var headerRow = document.createElement("tr"); + // Populate the headers + for (var _i = 0, _j = this.getHeaders(); _i < _j.length; _i++) { + var headerText = _j[_i]; + var headerElement = document.createElement("th"); + headerElement.textContent = headerText; + headerRow.appendChild(headerElement); + } + this.tableHead.appendChild(headerRow); + } + // Clear the table + this.tableBody.innerHTML = ""; + // Add only records that must be displayed on table + this.addRows(this.trimStart, this.trimEnd, true); + // Display content + $(".loader").fadeOut(200); + $(".content").fadeIn(200); + }; + State.prototype.searchId = function () { + this.setCurrentState(); + var id = parseInt(this.inputBox.value); + var numRecords = this.getRecordCount() - 1; + if (id < 0 || id > numRecords || isNaN(id)) { + // User info: Display error message + this.pageInfo.innerHTML = "

No records to display

"; + } + else { + // Use entered ID to calculate what records should display + if ((this.getRecordCount() - 1) - id >= this.records) { + this.trimStart = id; + this.trimEnd = this.trimStart + (this.records - 1); + } + else { + this.trimEnd = this.getRecordCount() - 1; + this.trimStart = this.trimEnd - this.records + 1; + } + this.loadIntoTable(false); + } + document.getElementById('id-search').value = 'Enter ID number'; + }; + State.prototype.goToFirst = function () { + this.trimStart = 0; + this.trimEnd = this.trimStart + this.records - 1; + this.loadIntoTable(false); + }; + State.prototype.goToPrev = function () { + this.setCurrentState(); + // If previous page is end of data && there are not enough records to fill window + if ((this.trimStart - 1) - (this.records - 1) < 0) { + this.trimStart = 0; + this.trimEnd = this.trimStart + this.records - 1; + } + else { + this.trimEnd = this.trimStart - 1; + this.trimStart = this.trimEnd - this.records + 1; + } + this.loadIntoTable(false); + }; + State.prototype.goToNext = function () { + this.setCurrentState(); + // If next page is end of data && there are not enough records to fill window + if ((this.getRecordCount() - 1) - (this.trimEnd + 1) < this.records) { + this.trimEnd = this.getRecordCount() - 1; + this.trimStart = this.trimEnd - this.records + 1; + } + else { + this.trimStart = this.trimEnd + 1; + this.trimEnd = this.trimStart + this.records - 1; + } + this.loadIntoTable(false); + }; + State.prototype.goToLast = function () { + this.trimEnd = this.getRecordCount() - 1; + this.trimStart = this.trimEnd - this.records + 1; + this.loadIntoTable(false); + }; + State.prototype.resize = function () { + var _a, _b, _c, _d, _e, _f, _g, _h; + return __awaiter(this, void 0, void 0, function () { + var newHeight, diff, start, end, addEnd, addTop; + return __generator(this, function (_j) { + switch (_j.label) { + case 0: + this.setCurrentState(); + newHeight = this.calculateRecords(); + console.log("records ", this.records, " vs numRows ", this.records); + diff = newHeight - this.records; + start = this.trimStart; + end = this.trimEnd + diff; + if (!(diff < 0)) return [3 /*break*/, 1]; + // Delete rows from last page + this.deleteRows(this.records, diff); + this.trimEnd = this.trimEnd + diff; + return [3 /*break*/, 6]; + case 1: + if (!(diff > 0 && this.trimEnd == this.getRecordCount() - 1)) return [3 /*break*/, 3]; + // Prepend rows as last page gets bigger + // 'start' and 'end' only fetches the amount that should be prepended + end = this.RECORDCOUNT - 1; + start = this.trimStart - diff; + return [4 /*yield*/, this.addRows(start, end, false)]; + case 2: + _j.sent(); + this.trimStart = this.trimStart - diff; + return [3 /*break*/, 6]; + case 3: + if (!(diff > 0 && end >= this.getRecordCount())) return [3 /*break*/, 5]; + addEnd = (this.getRecordCount() - 1) - this.trimEnd; + end = this.getRecordCount() - 1; + start = end - addEnd + 1; + this.addRows(start, end, true); + addTop = diff - addEnd; + end = this.trimStart - 1; + start = this.trimStart - addTop; + return [4 /*yield*/, this.addRows(start, end, false)]; + case 4: + _j.sent(); + this.trimEnd = this.getRecordCount() - 1; + this.trimStart = this.trimStart - addTop; + return [3 /*break*/, 6]; + case 5: + if (diff > 0 && start <= this.getRecordCount() - 1) { + // Add rows if end of data is not yet reached + this.addRows(start, end, true); + this.trimEnd = this.trimEnd + diff; + } + _j.label = 6; + case 6: + this.records = newHeight; + // UI "Aesthetic": update buttons + (_a = this.firstBtn) === null || _a === void 0 ? void 0 : _a.removeAttribute("disabled"); + (_b = this.prevBtn) === null || _b === void 0 ? void 0 : _b.removeAttribute("disabled"); + (_c = this.nextBtn) === null || _c === void 0 ? void 0 : _c.removeAttribute("disabled"); + (_d = this.lastBtn) === null || _d === void 0 ? void 0 : _d.removeAttribute("disabled"); + if (this.trimEnd == this.getRecordCount() - 1) { + (_e = this.lastBtn) === null || _e === void 0 ? void 0 : _e.setAttribute("disabled", "disabled"); + (_f = this.nextBtn) === null || _f === void 0 ? void 0 : _f.setAttribute("disabled", "disabled"); + } + if (this.trimStart == 0) { + (_g = this.firstBtn) === null || _g === void 0 ? void 0 : _g.setAttribute("disabled", "disabled"); + (_h = this.prevBtn) === null || _h === void 0 ? void 0 : _h.setAttribute("disabled", "disabled"); + } + return [2 /*return*/]; + } + }); + }); + }; return State; }()); //# sourceMappingURL=state.js.map \ No newline at end of file diff --git a/state.js.map b/state.js.map index 1858e3c0..a26dfbc1 100644 --- a/state.js.map +++ b/state.js.map @@ -1 +1 @@ -{"version":3,"file":"state.js","sourceRoot":"","sources":["state.ts"],"names":[],"mappings":";AAAA;IAUC;QACC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACvC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QACnB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;QAChC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAE1B,uDAAuD;QACvD,IAAI,CAAC,WAAW,GAAG,GAAG,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC;IACjG,CAAC;IAED,8BAAc,GAAd;QACC,OAAO,IAAI,CAAC,WAAW,CAAC;IACzB,CAAC;IAED,0BAAU,GAAV;QACC,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED,8BAAc,GAAd,UAAe,KAAa;QAC3B,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;IAC1B,CAAC;IAED,0BAAU,GAAV,UAAW,KAAe;QACzB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,gCAAgB,GAAhB;QACC,oCAAoC;QACpC,8HAA8H;QAC9H,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,WAAW,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;IACpD,CAAC;IACF,YAAC;AAAD,CAAC,AA3CD,IA2CC"} \ No newline at end of file +{"version":3,"file":"state.js","sourceRoot":"","sources":["state.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/state.ts b/state.ts index 5b969181..389fe9bd 100644 --- a/state.ts +++ b/state.ts @@ -2,22 +2,42 @@ class State { records: number; trimStart: number; trimEnd: number; - isDefaultNode: boolean; private RECORDCOUNT: number; private HEADERS: string[]; data: any; + contentTable: HTMLElement | null; + tableBody: HTMLTableSectionElement | null; + tableHead: HTMLElement | null; + pageInfo: HTMLElement | null; + searchBtn: HTMLElement | null; + firstBtn: HTMLElement | null; + prevBtn: HTMLElement | null; + nextBtn: HTMLElement | null; + lastBtn: HTMLElement | null; + inputBox: HTMLElement | null; + constructor() { this.records = this.calculateRecords(); this.trimStart = 0; this.trimEnd = this.records - 1; - this.isDefaultNode = true; // Default values for variables that stores server data this.RECORDCOUNT = 350; this.HEADERS = ["ID", "City", "Population"]; this.data = [[0, "Cape Town", 3500000], [1, "New York", 8500000], [2, "Johannesburg", 4500000]]; + + this.contentTable = document.getElementById('content-table'); + this.tableBody = document.querySelector('tbody'); + this.tableHead = document.getElementById('content-thead'); + this.pageInfo = document.getElementById('page-info'); + this.searchBtn = document.getElementById('id-search-btn'); + this.firstBtn = document.getElementById('first'); + this.prevBtn = document.getElementById('prev'); + this.nextBtn = document.getElementById('next'); + this.lastBtn = document.getElementById('last'); + this.inputBox = document.getElementById('id-search'); } getRecordCount() { @@ -41,4 +61,297 @@ class State { // The calculation is an estimate of how many space there is for rows (160 is estimate space for header and footer of website) return Math.floor((window.innerHeight - 160) / 40); } + + setCurrentState() { + let tableBody = document.querySelector('tbody'); + this.records = tableBody!.rows.length; + + if (this.records != 0) { + this.trimStart = parseInt(tableBody!.rows[0].cells[0].innerHTML); + this.trimEnd = parseInt(tableBody!.rows[this.records - 1].cells[0].innerHTML); + } else { + return; + } + console.log("Num records: ", this.records, " start: ", this.trimStart, " end: ", this.trimEnd); + } + + // Fetch headers and record count + async getData(): Promise { + // API calls for record count and headers + await fetch('/recordCount') + .then(resp => { + if (resp.ok) { + return resp.json(); + } + throw new Error('Could not retrieve data'); + }) + .then(count => { + this.setRecordCount(count); + }) + .catch((error) => { + console.log(error); + }); + + await fetch('/columns') + .then(resp => { + if (resp.ok) { + return resp.json(); + } + throw new Error('Could not retrieve data'); + }) + .then(count => { + this.setHeaders(count); + }) + .catch((error) => { + console.log(error); + }); + + return true; + } + + // Add rows to table + async addRows(start: number, end: number, isAppend: boolean) { + let table = document.getElementById("content-table"); + let newTableBody = document.createElement("tbody"); + + let link = "/records?from=" + start + "&to=" + end; + await fetch(link) + .then(resp => { + if (resp.ok) { + return resp.json(); + } + throw new Error('Could not retrieve data'); + }) + .then(count => { + this.data = count; + }) + .catch((error) => { + console.log(error); + }); + + // Append or prepend rows to table + if (isAppend) { + for (let row of this.data) { + let rowElement = document.createElement("tr"); + + for (let cellText of row) { + let cellElement = document.createElement("td"); + + cellElement.textContent = cellText; + rowElement.appendChild(cellElement); // Append cells + } + newTableBody.appendChild(rowElement);// Append rows + } + } else { + // Reverse order of data and save in temp variable + let rowData: any; + rowData = []; + let k = 0; + for (let i = this.data.length - 1; i >= 0; i--) { + rowData[k] = this.data[i]; + k++; + } + + // Use temp variable to append rows to table in correct order + for (let row of rowData) { + let rowElement = document.createElement("tr"); + + for (let cellText of row) { + let cellElement = document.createElement("td"); + + cellElement.textContent = cellText; + rowElement.appendChild(cellElement); // Append cells + } + newTableBody.prepend(rowElement);// Prepend rows + } + } + if (!table) + return; + table.replaceChild(newTableBody, this.tableBody!); + } + + // Delete rows from table + deleteRows(newHeight: number, diff: number) { + let num = newHeight - 1; + + for (let i = num; i > (num + diff); i--) { + this.tableBody!.deleteRow(i); + } + } + + + // Load json data into table function + loadIntoTable(clearHeader: boolean) { + + // Display loader + $(".content").fadeOut(200); + $(".loader").fadeIn(200); + + // UI "Aesthetic": update buttons + this.firstBtn?.removeAttribute("disabled"); + this.prevBtn?.removeAttribute("disabled"); + this.nextBtn?.removeAttribute("disabled"); + this.lastBtn?.removeAttribute("disabled"); + + if (this.trimEnd == this.getRecordCount() - 1) { + this.lastBtn?.setAttribute("disabled", "disabled"); + this.nextBtn?.setAttribute("disabled", "disabled"); + } + + if (this.trimStart == 0) { + this.firstBtn?.setAttribute("disabled", "disabled"); + this.prevBtn?.setAttribute("disabled", "disabled"); + } + + this.pageInfo!.innerHTML = `

`; + + if (clearHeader) { + this.tableHead!.innerHTML = ""; + let headerRow = document.createElement("tr"); + + // Populate the headers + for (let headerText of this.getHeaders()) { + let headerElement = document.createElement("th"); + + headerElement.textContent = headerText; + headerRow.appendChild(headerElement); + } + this.tableHead!.appendChild(headerRow) + } + + // Clear the table + this.tableBody!.innerHTML = ""; + + // Add only records that must be displayed on table + this.addRows(this.trimStart, this.trimEnd, true); + + // Display content + $(".loader").fadeOut(200); + $(".content").fadeIn(200); + } + + searchId() { + this.setCurrentState(); + let id = parseInt((this.inputBox).value); + let numRecords = this.getRecordCount() - 1; + + if (id < 0 || id > numRecords || isNaN(id)) { + // User info: Display error message + this.pageInfo!.innerHTML = `

No records to display

`; + } else { + // Use entered ID to calculate what records should display + if ((this.getRecordCount() - 1) - id >= this.records) { + this.trimStart = id; + this.trimEnd = this.trimStart + (this.records - 1); + } else { + this.trimEnd = this.getRecordCount() - 1; + this.trimStart = this.trimEnd - this.records + 1; + } + this.loadIntoTable(false); + } + (document.getElementById('id-search')).value = 'Enter ID number'; + } + + goToFirst() { + this.trimStart = 0; + this.trimEnd = this.trimStart + this.records - 1; + this.loadIntoTable(false); + } + + goToPrev() { + this.setCurrentState(); + // If previous page is end of data && there are not enough records to fill window + if ((this.trimStart - 1) - (this.records - 1) < 0) { + this.trimStart = 0; + this.trimEnd = this.trimStart + this.records - 1; + } else { + this.trimEnd = this.trimStart - 1; + this.trimStart = this.trimEnd - this.records + 1; + } + this.loadIntoTable(false); + } + + goToNext() { + this.setCurrentState(); + // If next page is end of data && there are not enough records to fill window + if ((this.getRecordCount() - 1) - (this.trimEnd + 1) < this.records) { + this.trimEnd = this.getRecordCount() - 1; + this.trimStart = this.trimEnd - this.records + 1; + } else { + this.trimStart = this.trimEnd + 1; + this.trimEnd = this.trimStart + this.records - 1; + } + this.loadIntoTable(false); + } + + goToLast() { + this.trimEnd = this.getRecordCount() - 1; + this.trimStart = this.trimEnd - this.records + 1; + this.loadIntoTable(false); + } + + async resize() { + this.setCurrentState(); + // Calculate number rows to be added/deleted + let newHeight = this.calculateRecords(); + console.log("records ", this.records, " vs numRows ", this.records); + let diff = newHeight - this.records; + + let start = this.trimStart; + let end = this.trimEnd + diff; + + if (diff < 0) { + // Delete rows from last page + this.deleteRows(this.records, diff); + + this.trimEnd = this.trimEnd + diff; + } else if (diff > 0 && this.trimEnd == this.getRecordCount() - 1) { + // Prepend rows as last page gets bigger + // 'start' and 'end' only fetches the amount that should be prepended + end = this.RECORDCOUNT - 1; + start = this.trimStart - diff; + + await this.addRows(start, end, false); + + this.trimStart = this.trimStart - diff; + } else if (diff > 0 && end >= this.getRecordCount()) { + // Appends remaining records until RECORDCOUNT - 1, + // then prepends the rest + let addEnd = (this.getRecordCount() - 1) - this.trimEnd; + end = this.getRecordCount() - 1; + start = end - addEnd + 1; + this.addRows(start, end, true); + + let addTop = diff - addEnd; + end = this.trimStart - 1; + start = this.trimStart - addTop; + + await this.addRows(start, end, false); + + this.trimEnd = this.getRecordCount() - 1; + this.trimStart = this.trimStart - addTop + } else if (diff > 0 && start <= this.getRecordCount() - 1) { + // Add rows if end of data is not yet reached + this.addRows(start, end, true); + + this.trimEnd = this.trimEnd + diff + } + this.records = newHeight; + + // UI "Aesthetic": update buttons + this.firstBtn?.removeAttribute("disabled"); + this.prevBtn?.removeAttribute("disabled"); + this.nextBtn?.removeAttribute("disabled"); + this.lastBtn?.removeAttribute("disabled"); + + if (this.trimEnd == this.getRecordCount() - 1) { + this.lastBtn?.setAttribute("disabled", "disabled"); + this.nextBtn?.setAttribute("disabled", "disabled"); + } + + if (this.trimStart == 0) { + this.firstBtn?.setAttribute("disabled", "disabled"); + this.prevBtn?.setAttribute("disabled", "disabled"); + } + } } From d6e7e06ed415672035ab407cf11f857d3f234aeb Mon Sep 17 00:00:00 2001 From: CelesteNaude <286celeste@gmail.com> Date: Mon, 14 Mar 2022 14:04:47 +0200 Subject: [PATCH 19/19] Added methods in state.ts for event listeners --- app.ts | 92 +++-------------------- index.html | 5 +- state.js | 208 ++++++++++++++++++++++++++------------------------- state.js.map | 2 +- state.ts | 199 ++++++++++++++++++++++++------------------------ style.css | 1 - 6 files changed, 221 insertions(+), 286 deletions(-) diff --git a/app.ts b/app.ts index 9f80c060..89ba051a 100644 --- a/app.ts +++ b/app.ts @@ -1,87 +1,15 @@ - window.onload = async () => { let state = new State(); // Get data from server and load into table - await state.getData() - .then(resp => { - if (resp == true) { - state.loadIntoTable(true); - } - }) -}; - -// Code is only triggered once per user input -const debounce = (fn: Function, ms: number) => { - let timeoutId: ReturnType; - return function (this: any, ...args: any[]) { - clearTimeout(timeoutId); - timeoutId = setTimeout(() => fn.apply(this, args), ms); - }; + await state.getData().then(resp => { + if (resp == true) { + state.loadIntoTable(true); + } + }) + + // Set needed navigation controls + state.setSearchButton(); + state.setPageButtons(); + state.setResizeEvent(); }; - -// Search entered ID -document.getElementById('id-search-btn')!.addEventListener("click", debounce(async () => { - let state = new State(); - await state.getData() - .then(resp => { - if (resp == true) { - state.searchId(); - } - }) -}, 250)); - -// Set trim to start of data -document.getElementById('first')!.addEventListener("click", debounce(async () => { - let state = new State(); - await state.getData() - .then(resp => { - if (resp == true) { - state.goToFirst(); - } - }) -}, 250)); - -// Set trim to previous data -document.getElementById('prev')!.addEventListener("click", debounce(async () => { - let state = new State(); - await state.getData() - .then(resp => { - if (resp == true) { - state.goToPrev(); - } - }) -}, 250)); - -// Set trim to next data -document.getElementById('next')!.addEventListener("click", debounce(async () => { - let state = new State(); - await state.getData() - .then(resp => { - if (resp == true) { - state.goToNext(); - } - }) -}, 250)); - -// Set trim to end of data -document.getElementById('last')!.addEventListener("click", debounce(async () => { - let state = new State(); - await state.getData() - .then(resp => { - if (resp == true) { - state.goToLast(); - } - }) -}, 250)); - -// Add/remove rows from table based on resize event of the window -window.addEventListener("resize", debounce(async () => { - let state = new State(); - await state.getData() - .then(resp => { - if (resp == true) { - state.resize(); - } - }) -}, 150)); // Log window dimensions at most every 100ms diff --git a/index.html b/index.html index 21de8ca3..7e6b2aed 100644 --- a/index.html +++ b/index.html @@ -4,6 +4,8 @@ JS Onboard Project + + @@ -34,8 +36,5 @@

IMQS Onboarding Project

- - - diff --git a/state.js b/state.js index 748fee42..2cf32de6 100644 --- a/state.js +++ b/state.js @@ -35,12 +35,26 @@ var __generator = (this && this.__generator) || function (thisArg, body) { if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; +// Code is only triggered once per user input +var debounce = function (fn, ms) { + var timeoutId; + return function () { + var _this = this; + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + clearTimeout(timeoutId); + timeoutId = setTimeout(function () { return fn.apply(_this, args); }, ms); + }; +}; var State = /** @class */ (function () { function State() { + // Starting values for when page is first loaded this.records = this.calculateRecords(); this.trimStart = 0; this.trimEnd = this.records - 1; - // Default values for variables that stores server data + // Default values for server data variables this.RECORDCOUNT = 350; this.HEADERS = ["ID", "City", "Population"]; this.data = [[0, "Cape Town", 3500000], [1, "New York", 8500000], [2, "Johannesburg", 4500000]]; @@ -55,34 +69,54 @@ var State = /** @class */ (function () { this.lastBtn = document.getElementById('last'); this.inputBox = document.getElementById('id-search'); } + // Record count and headers should not be changed outside the class + // hence there are only get methods for them State.prototype.getRecordCount = function () { return this.RECORDCOUNT; }; State.prototype.getHeaders = function () { return this.HEADERS; }; - State.prototype.setRecordCount = function (value) { - this.RECORDCOUNT = value; - }; - State.prototype.setHeaders = function (value) { - this.HEADERS = value; - }; State.prototype.calculateRecords = function () { // Estimate of available table space - // The calculation is an estimate of how many space there is for rows (160 is estimate space for header and footer of website) + // The calculation is an estimate of how many space there is for rows + // 160 is estimate space for header and footer of website and 40 is estimated space of a single row return Math.floor((window.innerHeight - 160) / 40); }; - State.prototype.setCurrentState = function () { - var tableBody = document.querySelector('tbody'); - this.records = tableBody.rows.length; - if (this.records != 0) { - this.trimStart = parseInt(tableBody.rows[0].cells[0].innerHTML); - this.trimEnd = parseInt(tableBody.rows[this.records - 1].cells[0].innerHTML); - } - else { - return; - } - console.log("Num records: ", this.records, " start: ", this.trimStart, " end: ", this.trimEnd); + // The setPageButtons, setSearchButton, and setResizeEvent are seperate functions + // so that only the needed functions are used + State.prototype.setPageButtons = function () { + var _this = this; + // Event listener for button that goes to first page + this.firstBtn.addEventListener("click", debounce(function () { + _this.goToFirst(); + }, 250)); + // Event listener for button that goes to previous page + this.prevBtn.addEventListener("click", debounce(function () { + _this.goToPrev(); + }, 250)); + // Event listener for button that goes to next page + this.nextBtn.addEventListener("click", debounce(function () { + _this.goToNext(); + }, 250)); + // Event listener for button that goes to last page + this.lastBtn.addEventListener("click", debounce(function () { + _this.goToLast(); + }, 250)); + }; + State.prototype.setSearchButton = function () { + var _this = this; + // // Event listener for button that searches entered ID + this.searchBtn.addEventListener("click", debounce(function () { + _this.searchId(); + }, 250)); + }; + State.prototype.setResizeEvent = function () { + var _this = this; + // Event listener for when user resizes the page + window.addEventListener("resize", debounce(function () { + _this.resize(); + }, 150)); // Log window dimensions at most every 150ms }; // Fetch headers and record count State.prototype.getData = function () { @@ -100,10 +134,10 @@ var State = /** @class */ (function () { throw new Error('Could not retrieve data'); }) .then(function (count) { - _this.setRecordCount(count); + _this.RECORDCOUNT = count; }) .catch(function (error) { - console.log(error); + console.error(error); })]; case 1: // API calls for record count and headers @@ -116,10 +150,10 @@ var State = /** @class */ (function () { throw new Error('Could not retrieve data'); }) .then(function (count) { - _this.setHeaders(count); + _this.HEADERS = count; }) .catch(function (error) { - console.log(error); + console.error(error); })]; case 2: _a.sent(); @@ -129,15 +163,16 @@ var State = /** @class */ (function () { }); }; // Add rows to table - State.prototype.addRows = function (start, end, isAppend) { + State.prototype.addRows = function (start, end) { return __awaiter(this, void 0, void 0, function () { - var table, newTableBody, link, _i, _a, row, rowElement, _b, row_1, cellText, cellElement, rowData, k, i, _c, rowData_1, row, rowElement, _d, row_2, cellText, cellElement; + var table, newTableBody, oldTableBody, link, _i, _a, row, rowElement, _b, row_1, cellText, cellElement; var _this = this; - return __generator(this, function (_e) { - switch (_e.label) { + return __generator(this, function (_c) { + switch (_c.label) { case 0: table = document.getElementById("content-table"); newTableBody = document.createElement("tbody"); + oldTableBody = table.querySelector("tbody"); link = "/records?from=" + start + "&to=" + end; return [4 /*yield*/, fetch(link) .then(function (resp) { @@ -150,48 +185,29 @@ var State = /** @class */ (function () { _this.data = count; }) .catch(function (error) { - console.log(error); + console.error(error); })]; case 1: - _e.sent(); - // Append or prepend rows to table - if (isAppend) { - for (_i = 0, _a = this.data; _i < _a.length; _i++) { - row = _a[_i]; - rowElement = document.createElement("tr"); - for (_b = 0, row_1 = row; _b < row_1.length; _b++) { - cellText = row_1[_b]; - cellElement = document.createElement("td"); - cellElement.textContent = cellText; - rowElement.appendChild(cellElement); // Append cells - } - newTableBody.appendChild(rowElement); // Append rows + _c.sent(); + for (_i = 0, _a = this.data; _i < _a.length; _i++) { + row = _a[_i]; + rowElement = document.createElement("tr"); + for (_b = 0, row_1 = row; _b < row_1.length; _b++) { + cellText = row_1[_b]; + cellElement = document.createElement("td"); + cellElement.textContent = cellText; + rowElement.appendChild(cellElement); // Append cells to row } + newTableBody.appendChild(rowElement); // Append rows to tbody + } + // If table exists, replace the new tbody with the old one + if (!table) { + console.error("Table is undefined"); + return [2 /*return*/]; } else { - rowData = void 0; - rowData = []; - k = 0; - for (i = this.data.length - 1; i >= 0; i--) { - rowData[k] = this.data[i]; - k++; - } - // Use temp variable to append rows to table in correct order - for (_c = 0, rowData_1 = rowData; _c < rowData_1.length; _c++) { - row = rowData_1[_c]; - rowElement = document.createElement("tr"); - for (_d = 0, row_2 = row; _d < row_2.length; _d++) { - cellText = row_2[_d]; - cellElement = document.createElement("td"); - cellElement.textContent = cellText; - rowElement.appendChild(cellElement); // Append cells - } - newTableBody.prepend(rowElement); // Prepend rows - } + table.replaceChild(newTableBody, oldTableBody); } - if (!table) - return [2 /*return*/]; - table.replaceChild(newTableBody, this.tableBody); return [2 /*return*/]; } }); @@ -199,17 +215,18 @@ var State = /** @class */ (function () { }; // Delete rows from table State.prototype.deleteRows = function (newHeight, diff) { + var tableBod = this.contentTable.querySelector('tbody'); var num = newHeight - 1; for (var i = num; i > (num + diff); i--) { - this.tableBody.deleteRow(i); + tableBod.deleteRow(i); } }; // Load json data into table function State.prototype.loadIntoTable = function (clearHeader) { var _a, _b, _c, _d, _e, _f, _g, _h; // Display loader - $(".content").fadeOut(200); - $(".loader").fadeIn(200); + $(".content").fadeOut(230); + $(".loader").fadeIn(230); // UI "Aesthetic": update buttons (_a = this.firstBtn) === null || _a === void 0 ? void 0 : _a.removeAttribute("disabled"); (_b = this.prevBtn) === null || _b === void 0 ? void 0 : _b.removeAttribute("disabled"); @@ -224,6 +241,7 @@ var State = /** @class */ (function () { (_h = this.prevBtn) === null || _h === void 0 ? void 0 : _h.setAttribute("disabled", "disabled"); } this.pageInfo.innerHTML = "

"; + // Add header only if 'clearHeader' is true if (clearHeader) { this.tableHead.innerHTML = ""; var headerRow = document.createElement("tr"); @@ -239,13 +257,13 @@ var State = /** @class */ (function () { // Clear the table this.tableBody.innerHTML = ""; // Add only records that must be displayed on table - this.addRows(this.trimStart, this.trimEnd, true); + this.addRows(this.trimStart, this.trimEnd); // Display content - $(".loader").fadeOut(200); - $(".content").fadeIn(200); + $(".loader").fadeOut(230); + $(".content").fadeIn(230); }; + // Search entered ID State.prototype.searchId = function () { - this.setCurrentState(); var id = parseInt(this.inputBox.value); var numRecords = this.getRecordCount() - 1; if (id < 0 || id > numRecords || isNaN(id)) { @@ -266,13 +284,14 @@ var State = /** @class */ (function () { } document.getElementById('id-search').value = 'Enter ID number'; }; + // Set trim to start of data State.prototype.goToFirst = function () { this.trimStart = 0; this.trimEnd = this.trimStart + this.records - 1; this.loadIntoTable(false); }; + // Set trim to previous data State.prototype.goToPrev = function () { - this.setCurrentState(); // If previous page is end of data && there are not enough records to fill window if ((this.trimStart - 1) - (this.records - 1) < 0) { this.trimStart = 0; @@ -284,8 +303,8 @@ var State = /** @class */ (function () { } this.loadIntoTable(false); }; + // Set trim to next data State.prototype.goToNext = function () { - this.setCurrentState(); // If next page is end of data && there are not enough records to fill window if ((this.getRecordCount() - 1) - (this.trimEnd + 1) < this.records) { this.trimEnd = this.getRecordCount() - 1; @@ -297,63 +316,50 @@ var State = /** @class */ (function () { } this.loadIntoTable(false); }; + // Set trim to end of data State.prototype.goToLast = function () { this.trimEnd = this.getRecordCount() - 1; this.trimStart = this.trimEnd - this.records + 1; this.loadIntoTable(false); }; + // Add/remove rows from table based on resize event of the window State.prototype.resize = function () { var _a, _b, _c, _d, _e, _f, _g, _h; return __awaiter(this, void 0, void 0, function () { - var newHeight, diff, start, end, addEnd, addTop; + var newHeight, diff, start, end; return __generator(this, function (_j) { switch (_j.label) { case 0: - this.setCurrentState(); newHeight = this.calculateRecords(); - console.log("records ", this.records, " vs numRows ", this.records); diff = newHeight - this.records; start = this.trimStart; end = this.trimEnd + diff; if (!(diff < 0)) return [3 /*break*/, 1]; - // Delete rows from last page + // If screen is made smaller, call delete rows function with this.records (amount of rows that were on the screen) + // and diff (how many rows should be deleted) this.deleteRows(this.records, diff); this.trimEnd = this.trimEnd + diff; - return [3 /*break*/, 6]; + return [3 /*break*/, 4]; case 1: - if (!(diff > 0 && this.trimEnd == this.getRecordCount() - 1)) return [3 /*break*/, 3]; + if (!(diff > 0 && end >= this.getRecordCount())) return [3 /*break*/, 3]; // Prepend rows as last page gets bigger - // 'start' and 'end' only fetches the amount that should be prepended - end = this.RECORDCOUNT - 1; - start = this.trimStart - diff; - return [4 /*yield*/, this.addRows(start, end, false)]; + end = this.getRecordCount() - 1; + start = end - (newHeight - 1); + console.log("End reached, displaying record ", start, " to ", end); + return [4 /*yield*/, this.addRows(start, end)]; case 2: _j.sent(); this.trimStart = this.trimStart - diff; - return [3 /*break*/, 6]; - case 3: - if (!(diff > 0 && end >= this.getRecordCount())) return [3 /*break*/, 5]; - addEnd = (this.getRecordCount() - 1) - this.trimEnd; - end = this.getRecordCount() - 1; - start = end - addEnd + 1; - this.addRows(start, end, true); - addTop = diff - addEnd; - end = this.trimStart - 1; - start = this.trimStart - addTop; - return [4 /*yield*/, this.addRows(start, end, false)]; - case 4: - _j.sent(); this.trimEnd = this.getRecordCount() - 1; - this.trimStart = this.trimStart - addTop; - return [3 /*break*/, 6]; - case 5: + return [3 /*break*/, 4]; + case 3: if (diff > 0 && start <= this.getRecordCount() - 1) { // Add rows if end of data is not yet reached - this.addRows(start, end, true); + this.addRows(start, end); this.trimEnd = this.trimEnd + diff; } - _j.label = 6; - case 6: + _j.label = 4; + case 4: this.records = newHeight; // UI "Aesthetic": update buttons (_a = this.firstBtn) === null || _a === void 0 ? void 0 : _a.removeAttribute("disabled"); diff --git a/state.js.map b/state.js.map index a26dfbc1..d436bc07 100644 --- a/state.js.map +++ b/state.js.map @@ -1 +1 @@ -{"version":3,"file":"state.js","sourceRoot":"","sources":["state.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"state.js","sourceRoot":"","sources":["state.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/state.ts b/state.ts index 389fe9bd..0f9aeb37 100644 --- a/state.ts +++ b/state.ts @@ -1,12 +1,25 @@ +// Code is only triggered once per user input +const debounce = (fn: Function, ms: number) => { + let timeoutId: ReturnType; + return function (this: any, ...args: any[]) { + clearTimeout(timeoutId); + timeoutId = setTimeout(() => fn.apply(this, args), ms); + }; +}; + class State { + // Variables to determine how many records there should be on the screen (records) + // and where these records should start and end (trimStart and trimEnd) > (display record 15 to 25) records: number; trimStart: number; trimEnd: number; + // Variables for server data private RECORDCOUNT: number; private HEADERS: string[]; - data: any; + data: any[]; + // Variables for DOM elements contentTable: HTMLElement | null; tableBody: HTMLTableSectionElement | null; tableHead: HTMLElement | null; @@ -19,11 +32,12 @@ class State { inputBox: HTMLElement | null; constructor() { + // Starting values for when page is first loaded this.records = this.calculateRecords(); this.trimStart = 0; this.trimEnd = this.records - 1; - // Default values for variables that stores server data + // Default values for server data variables this.RECORDCOUNT = 350; this.HEADERS = ["ID", "City", "Population"]; this.data = [[0, "Cape Town", 3500000], [1, "New York", 8500000], [2, "Johannesburg", 4500000]]; @@ -40,6 +54,8 @@ class State { this.inputBox = document.getElementById('id-search'); } + // Record count and headers should not be changed outside the class + // hence there are only get methods for them getRecordCount() { return this.RECORDCOUNT; } @@ -48,31 +64,49 @@ class State { return this.HEADERS; } - setRecordCount(value: number) { - this.RECORDCOUNT = value; - } - - setHeaders(value: string[]) { - this.HEADERS = value; - } - calculateRecords() { // Estimate of available table space - // The calculation is an estimate of how many space there is for rows (160 is estimate space for header and footer of website) + // The calculation is an estimate of how many space there is for rows + // 160 is estimate space for header and footer of website and 40 is estimated space of a single row return Math.floor((window.innerHeight - 160) / 40); } - setCurrentState() { - let tableBody = document.querySelector('tbody'); - this.records = tableBody!.rows.length; + // The setPageButtons, setSearchButton, and setResizeEvent are seperate functions + // so that only the needed functions are used + setPageButtons() { + // Event listener for button that goes to first page + this.firstBtn!.addEventListener("click", debounce(() => { + this.goToFirst(); + }, 250)); + + // Event listener for button that goes to previous page + this.prevBtn!.addEventListener("click", debounce(() => { + this.goToPrev(); + }, 250)); + + // Event listener for button that goes to next page + this.nextBtn!.addEventListener("click", debounce(() => { + this.goToNext(); + }, 250)); + + // Event listener for button that goes to last page + this.lastBtn!.addEventListener("click", debounce(() => { + this.goToLast(); + }, 250)); + } - if (this.records != 0) { - this.trimStart = parseInt(tableBody!.rows[0].cells[0].innerHTML); - this.trimEnd = parseInt(tableBody!.rows[this.records - 1].cells[0].innerHTML); - } else { - return; - } - console.log("Num records: ", this.records, " start: ", this.trimStart, " end: ", this.trimEnd); + setSearchButton() { + // // Event listener for button that searches entered ID + this.searchBtn!.addEventListener("click", debounce(() => { + this.searchId(); + }, 250)); + } + + setResizeEvent() { + // Event listener for when user resizes the page + window.addEventListener("resize", debounce(() => { + this.resize(); + }, 150)); // Log window dimensions at most every 150ms } // Fetch headers and record count @@ -86,10 +120,10 @@ class State { throw new Error('Could not retrieve data'); }) .then(count => { - this.setRecordCount(count); + this.RECORDCOUNT = count; }) .catch((error) => { - console.log(error); + console.error(error); }); await fetch('/columns') @@ -100,21 +134,22 @@ class State { throw new Error('Could not retrieve data'); }) .then(count => { - this.setHeaders(count); + this.HEADERS = count; }) .catch((error) => { - console.log(error); + console.error(error); }); return true; } // Add rows to table - async addRows(start: number, end: number, isAppend: boolean) { + async addRows(start: number, end: number) { let table = document.getElementById("content-table"); let newTableBody = document.createElement("tbody"); - + let oldTableBody = table!.querySelector("tbody"); let link = "/records?from=" + start + "&to=" + end; + await fetch(link) .then(resp => { if (resp.ok) { @@ -126,66 +161,46 @@ class State { this.data = count; }) .catch((error) => { - console.log(error); + console.error(error); }); - // Append or prepend rows to table - if (isAppend) { - for (let row of this.data) { - let rowElement = document.createElement("tr"); + for (let row of this.data) { + let rowElement = document.createElement("tr"); - for (let cellText of row) { - let cellElement = document.createElement("td"); + for (let cellText of row) { + let cellElement = document.createElement("td"); - cellElement.textContent = cellText; - rowElement.appendChild(cellElement); // Append cells - } - newTableBody.appendChild(rowElement);// Append rows - } - } else { - // Reverse order of data and save in temp variable - let rowData: any; - rowData = []; - let k = 0; - for (let i = this.data.length - 1; i >= 0; i--) { - rowData[k] = this.data[i]; - k++; - } - - // Use temp variable to append rows to table in correct order - for (let row of rowData) { - let rowElement = document.createElement("tr"); - - for (let cellText of row) { - let cellElement = document.createElement("td"); - - cellElement.textContent = cellText; - rowElement.appendChild(cellElement); // Append cells - } - newTableBody.prepend(rowElement);// Prepend rows + cellElement.textContent = cellText; + rowElement.appendChild(cellElement); // Append cells to row } + newTableBody.appendChild(rowElement);// Append rows to tbody } - if (!table) + + // If table exists, replace the new tbody with the old one + if (!table) { + console.error("Table is undefined"); return; - table.replaceChild(newTableBody, this.tableBody!); + } else { + table.replaceChild(newTableBody, oldTableBody!); + } } // Delete rows from table deleteRows(newHeight: number, diff: number) { + let tableBod = this.contentTable!.querySelector('tbody'); let num = newHeight - 1; for (let i = num; i > (num + diff); i--) { - this.tableBody!.deleteRow(i); + tableBod!.deleteRow(i); } } - // Load json data into table function loadIntoTable(clearHeader: boolean) { // Display loader - $(".content").fadeOut(200); - $(".loader").fadeIn(200); + $(".content").fadeOut(230); + $(".loader").fadeIn(230); // UI "Aesthetic": update buttons this.firstBtn?.removeAttribute("disabled"); @@ -205,6 +220,7 @@ class State { this.pageInfo!.innerHTML = `

`; + // Add header only if 'clearHeader' is true if (clearHeader) { this.tableHead!.innerHTML = ""; let headerRow = document.createElement("tr"); @@ -216,22 +232,22 @@ class State { headerElement.textContent = headerText; headerRow.appendChild(headerElement); } - this.tableHead!.appendChild(headerRow) + this.tableHead!.appendChild(headerRow); } // Clear the table this.tableBody!.innerHTML = ""; // Add only records that must be displayed on table - this.addRows(this.trimStart, this.trimEnd, true); + this.addRows(this.trimStart, this.trimEnd); // Display content - $(".loader").fadeOut(200); - $(".content").fadeIn(200); + $(".loader").fadeOut(230); + $(".content").fadeIn(230); } + // Search entered ID searchId() { - this.setCurrentState(); let id = parseInt((this.inputBox).value); let numRecords = this.getRecordCount() - 1; @@ -252,14 +268,15 @@ class State { (document.getElementById('id-search')).value = 'Enter ID number'; } + // Set trim to start of data goToFirst() { this.trimStart = 0; this.trimEnd = this.trimStart + this.records - 1; this.loadIntoTable(false); } + // Set trim to previous data goToPrev() { - this.setCurrentState(); // If previous page is end of data && there are not enough records to fill window if ((this.trimStart - 1) - (this.records - 1) < 0) { this.trimStart = 0; @@ -271,8 +288,8 @@ class State { this.loadIntoTable(false); } + // Set trim to next data goToNext() { - this.setCurrentState(); // If next page is end of data && there are not enough records to fill window if ((this.getRecordCount() - 1) - (this.trimEnd + 1) < this.records) { this.trimEnd = this.getRecordCount() - 1; @@ -284,57 +301,43 @@ class State { this.loadIntoTable(false); } + // Set trim to end of data goToLast() { this.trimEnd = this.getRecordCount() - 1; this.trimStart = this.trimEnd - this.records + 1; this.loadIntoTable(false); } + // Add/remove rows from table based on resize event of the window async resize() { - this.setCurrentState(); // Calculate number rows to be added/deleted let newHeight = this.calculateRecords(); - console.log("records ", this.records, " vs numRows ", this.records); let diff = newHeight - this.records; let start = this.trimStart; let end = this.trimEnd + diff; if (diff < 0) { - // Delete rows from last page + // If screen is made smaller, call delete rows function with this.records (amount of rows that were on the screen) + // and diff (how many rows should be deleted) this.deleteRows(this.records, diff); this.trimEnd = this.trimEnd + diff; - } else if (diff > 0 && this.trimEnd == this.getRecordCount() - 1) { - // Prepend rows as last page gets bigger - // 'start' and 'end' only fetches the amount that should be prepended - end = this.RECORDCOUNT - 1; - start = this.trimStart - diff; - - await this.addRows(start, end, false); - - this.trimStart = this.trimStart - diff; } else if (diff > 0 && end >= this.getRecordCount()) { - // Appends remaining records until RECORDCOUNT - 1, - // then prepends the rest - let addEnd = (this.getRecordCount() - 1) - this.trimEnd; + // Prepend rows as last page gets bigger end = this.getRecordCount() - 1; - start = end - addEnd + 1; - this.addRows(start, end, true); - - let addTop = diff - addEnd; - end = this.trimStart - 1; - start = this.trimStart - addTop; + start = end - (newHeight - 1); + console.log("End reached, displaying record ", start, " to ", end); - await this.addRows(start, end, false); + await this.addRows(start, end); + this.trimStart = this.trimStart - diff; this.trimEnd = this.getRecordCount() - 1; - this.trimStart = this.trimStart - addTop } else if (diff > 0 && start <= this.getRecordCount() - 1) { // Add rows if end of data is not yet reached - this.addRows(start, end, true); + this.addRows(start, end); - this.trimEnd = this.trimEnd + diff + this.trimEnd = this.trimEnd + diff; } this.records = newHeight; diff --git a/style.css b/style.css index 0655219e..388295a6 100644 --- a/style.css +++ b/style.css @@ -117,7 +117,6 @@ h1 { .btn { color: #fdfdfd; - /* float: left; */ padding: 1rem; text-decoration: none; border: solid 1px #45474b;