From db055826c58f6c793d317fabda3f745d17680ca9 Mon Sep 17 00:00:00 2001 From: Jaco Briers Date: Fri, 21 Dec 2018 09:25:19 +0200 Subject: [PATCH 01/11] Update README.md --- README.md | 3 +- app.ts | 185 +++++++++++++++++++++++++++++++++++++++++++++++++ app_styles.css | 34 +++++++++ index.html | 4 +- package.json | 24 +++++++ server/env.bat | 0 6 files changed, 247 insertions(+), 3 deletions(-) create mode 100644 app.ts create mode 100644 app_styles.css create mode 100644 package.json mode change 100644 => 100755 server/env.bat diff --git a/README.md b/README.md index f1dfc490..77f42636 100644 --- a/README.md +++ b/README.md @@ -72,14 +72,13 @@ Once you are done and happy with your solution, submit your code for code review ## Pre-requisites 1. You need to have set up your development environment [as described here](https://imqssoftware.atlassian.net/wiki/display/AR/Dev+Environment). -1. You can use either Microsoft Visual Studio Pro or Microsoft Visual Studio Express for Web as IDE. +1. We suggest using VSCode, but you can use your IDE of choice. ## Getting Started These steps include just enough detail to guide you. Each step will require some additional research on your part: 1. Fork this GIT repository under your own GIT account 1. Start up the backend server: - Open console and change directory to `server` directory - - Run `env.bat` - Run `go run main.go` - Open up your browser and point it to [http://localhost:2050](http://localhost:2050). You should see "Hello" 1. Create the frontend project: diff --git a/app.ts b/app.ts new file mode 100644 index 00000000..c3b37797 --- /dev/null +++ b/app.ts @@ -0,0 +1,185 @@ +window.onload = () => { + + let numColumns: number; + let columns: any; + let recordCount: number; + let startIndex = 0; // Default value = 20; + let tableRecordCount = 20; // Default value = 20; + + // Canvas: + let canvas = document.createElement("div"); + canvas.id = "canvas"; + $("body").append(canvas); + + // Buttons and fields: + let searchbtn = document.createElement("button"); + searchbtn.innerText = "Search"; + + let nextbtn = document.createElement("button"); + nextbtn.innerText = "Next Page"; + + let prevbtn = document.createElement("button"); + prevbtn.innerText = "Previous Page"; + + let fromField = document.createElement("input"); + fromField.placeholder = "from"; + + // on clicks: + searchbtn.onclick = function() { + let from = parseInt(fromField.value, 10); + // validate field: + if (validate(from)) { + let end = 19; + startIndex = from; + if (recordCount < startIndex + 20) { + end = recordCount - startIndex - 1; + } + getRecords(from, startIndex + end); + } + }; + + nextbtn.onclick = function() { + let end = 19; + if (recordCount > startIndex + 20) { + startIndex += 20; + if (recordCount < startIndex + 20) { + end = recordCount - startIndex - 1; + } + getRecords(startIndex, startIndex + end); + } + }; + + prevbtn.onclick = function() { + if (startIndex >= 20) { + startIndex -= 20; + } else if (startIndex < 20) { + startIndex = 0; + } + getRecords(startIndex, startIndex+19); + }; + + $("#canvas").append(searchbtn, fromField, prevbtn, nextbtn); + + initiate(); + + /** + * Initiates the HTTP requests to obtain the records and column values necessary for the table. + */ + function initiate() { + // get number of records: + $.ajax({ + url: "http://localhost:2050/recordCount", + success: function (result) { + recordCount = parseInt(JSON.parse(result), 10); + // get columns: + $.ajax({ + url: "http://localhost:2050/columns", + success: function (result) { + columns = JSON.parse(result); + numColumns = getSize(columns); + // get first page of records and display them: + getRecords(0, 19); + }, + error: function (err) { + $("body").text("Error: " + err.status + " " + err.statusText); + } + }); + }, + error: function (err) { + $("body").text("Error: " + err.status + " " + err.statusText); + } + }); + } + + /** + * Generates a table populated with data, distrubuted evenly. + * @param data The data records retrieved from the server, structured as a 2D object array. + * @param columns An object array containing the column heading values. + */ + function generateTable(data: any, columns: any) { + $("table").remove(); // Remove previous table + let dataSize = getSize(data); + let table = document.createElement("table"); + let tbdy = document.createElement("tbody"); + table.appendChild(generateHeadings(columns)); + for (let i = 0; i < 20; i++){ + let tr = document.createElement("tr"); + for (let j = 0; j < numColumns; j++){ + let td = document.createElement("td"); + if (dataSize > i) + td.appendChild(document.createTextNode(data[i][j])); + tr.appendChild(td); + } + tbdy.appendChild(tr); + } + table.appendChild(tbdy); + canvas.appendChild(table); + } + + /** + * Finds the number of entries within a data set. + * @param data An array of data, type is unknown (any). + */ + function getSize(data: any) { + let i = 0; + let entry; + for (entry in data) { + i++; + } + return i; + } + + /** + * Sends out an HTTP request to retrieve data records, coupled with generating a table to display the records. + * @param from The ID value from which to start searching. + * @param to The ID value from which to stop searching. + */ + function getRecords(from: number, to: number) { + $.ajax({ + url: "http://localhost:2050/records", + data: {from: from, to: to}, + success: function (result) { + let data = JSON.parse(result); + generateTable(data, columns); + }, + error: function (err) { + $("body").text("Error: " + err.status + " " + err.statusText); + } + }); + } + + /** + * Generates and returns a "thead" object containing column headings. + * @param columns An object array containing the column heading values. + */ + function generateHeadings(columns: any) { + let thead = document.createElement("thead"); + let tr = document.createElement("tr"); + for (let j = 0; j < numColumns; j++) { + let td = document.createElement("td"); + td.appendChild(document.createTextNode(columns[j])); + tr.appendChild(td); + } + thead.appendChild(tr); + return thead; + } + + /** + * Validates that the field value is a number. + * @param from The ID value from which to start searching. + */ + function validate(from: number) { + if (isNaN(from)) { + alert("\"From\" field does not have a number value."); + return false; + } else if (from < 0) { + alert("\"From\" value cannot be negative."); + return false; + } else if (from > recordCount-1) { + alert("\"From\" value exceeds the record count."); + return false; + } + return true; + } + +} \ No newline at end of file diff --git a/app_styles.css b/app_styles.css new file mode 100644 index 00000000..a1368e8d --- /dev/null +++ b/app_styles.css @@ -0,0 +1,34 @@ +input, button { + display: inline; + padding: 1rem; +} + +#canvas { + width: 100vw; + height: 100vh; +} + +table { + border-collapse: collapse; + width: 100%; + height: 90%; +} + +td { + width: 9%; + padding: 0.7rem; + border-left: 1px darkgrey solid; +} + +tr:hover { + background-color: lightgrey; +} + +tr { + border: 1px darkgrey solid; +} + +html { + overflow: hidden; +} + diff --git a/index.html b/index.html index add5e736..87808aa3 100644 --- a/index.html +++ b/index.html @@ -3,10 +3,12 @@ JS Onboard Project + + -

Hello

+ diff --git a/package.json b/package.json new file mode 100644 index 00000000..a11e06c1 --- /dev/null +++ b/package.json @@ -0,0 +1,24 @@ +{ + "name": "onboard-javascript", + "version": "1.0.0", + "description": "Onboarding", + "main": "index.js", + "dependencies": { + "jquery": "^3.4.1" + }, + "devDependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build": "tsc" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/pierrehenrinortje/onboard-javascript.git" + }, + "author": "pierre", + "license": "ISC", + "bugs": { + "url": "https://github.com/pierrehenrinortje/onboard-javascript/issues" + }, + "homepage": "https://github.com/pierrehenrinortje/onboard-javascript#readme" +} diff --git a/server/env.bat b/server/env.bat old mode 100644 new mode 100755 From d1a4ab02ca689b6876f56bbfb4ffd98acf365fe1 Mon Sep 17 00:00:00 2001 From: Pierre Date: Mon, 13 Jan 2020 12:17:33 +0200 Subject: [PATCH 02/11] On window resize the table updates accordingly, order of data is not interrupted --- app.ts | 44 +++++++++++++++++++++++++++++++------------- app_styles.css | 6 ++++-- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/app.ts b/app.ts index c3b37797..404d741f 100644 --- a/app.ts +++ b/app.ts @@ -24,14 +24,23 @@ window.onload = () => { let fromField = document.createElement("input"); fromField.placeholder = "from"; + window.onresize = () => { + adjustTableRecordCount(); + let end = tableRecordCount - 1; + if (recordCount < startIndex + tableRecordCount) { + end = recordCount - startIndex - 1; + } + getRecords(startIndex, startIndex + end); + } + // on clicks: searchbtn.onclick = function() { let from = parseInt(fromField.value, 10); // validate field: if (validate(from)) { - let end = 19; + let end = tableRecordCount - 1; startIndex = from; - if (recordCount < startIndex + 20) { + if (recordCount < startIndex + tableRecordCount) { end = recordCount - startIndex - 1; } getRecords(from, startIndex + end); @@ -39,10 +48,10 @@ window.onload = () => { }; nextbtn.onclick = function() { - let end = 19; - if (recordCount > startIndex + 20) { - startIndex += 20; - if (recordCount < startIndex + 20) { + let end = tableRecordCount - 1; + if (recordCount > startIndex + tableRecordCount) { + startIndex += tableRecordCount; + if (recordCount < startIndex + tableRecordCount) { end = recordCount - startIndex - 1; } getRecords(startIndex, startIndex + end); @@ -50,15 +59,15 @@ window.onload = () => { }; prevbtn.onclick = function() { - if (startIndex >= 20) { - startIndex -= 20; - } else if (startIndex < 20) { + if (startIndex >= tableRecordCount) { + startIndex -= tableRecordCount; + } else if (startIndex < tableRecordCount) { startIndex = 0; } - getRecords(startIndex, startIndex+19); + getRecords(startIndex, startIndex + tableRecordCount - 1); }; - $("#canvas").append(searchbtn, fromField, prevbtn, nextbtn); + $("#canvas").append(fromField,searchbtn, prevbtn, nextbtn); initiate(); @@ -78,7 +87,8 @@ window.onload = () => { columns = JSON.parse(result); numColumns = getSize(columns); // get first page of records and display them: - getRecords(0, 19); + adjustTableRecordCount(); + getRecords(0, tableRecordCount - 1); }, error: function (err) { $("body").text("Error: " + err.status + " " + err.statusText); @@ -102,7 +112,7 @@ window.onload = () => { let table = document.createElement("table"); let tbdy = document.createElement("tbody"); table.appendChild(generateHeadings(columns)); - for (let i = 0; i < 20; i++){ + for (let i = 0; i < tableRecordCount; i++){ let tr = document.createElement("tr"); for (let j = 0; j < numColumns; j++){ let td = document.createElement("td"); @@ -182,4 +192,12 @@ window.onload = () => { return true; } + function adjustTableRecordCount() { + let height = window.innerHeight; + let fontSize = getComputedStyle(document.documentElement).fontSize + ""; + let rowHeight = parseFloat(fontSize)*2.5; + if (rowHeight !== undefined) + tableRecordCount = Math.trunc(height/rowHeight) - 4; + } + } \ No newline at end of file diff --git a/app_styles.css b/app_styles.css index a1368e8d..c17dd2f9 100644 --- a/app_styles.css +++ b/app_styles.css @@ -1,6 +1,6 @@ input, button { display: inline; - padding: 1rem; + padding: 0.5rem; } #canvas { @@ -12,11 +12,13 @@ table { border-collapse: collapse; width: 100%; height: 90%; + table-layout: fixed; + overflow: hidden; } td { width: 9%; - padding: 0.7rem; + height: 2.5rem; border-left: 1px darkgrey solid; } From be18911f691d6d2a754f7dd1afbe6b6e67662459 Mon Sep 17 00:00:00 2001 From: Pierre Date: Mon, 13 Jan 2020 13:35:34 +0200 Subject: [PATCH 03/11] changed window resize adjustment --- app.ts | 3 +++ app_styles.css | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app.ts b/app.ts index 404d741f..cb56f314 100644 --- a/app.ts +++ b/app.ts @@ -192,6 +192,9 @@ window.onload = () => { return true; } + /** + * Adjust the number of records shown in the table according to the window size. + */ function adjustTableRecordCount() { let height = window.innerHeight; let fontSize = getComputedStyle(document.documentElement).fontSize + ""; diff --git a/app_styles.css b/app_styles.css index c17dd2f9..9a863c17 100644 --- a/app_styles.css +++ b/app_styles.css @@ -14,11 +14,13 @@ table { height: 90%; table-layout: fixed; overflow: hidden; + font-size: 0.8rem; } td { width: 9%; - height: 2.5rem; + height: 2rem; + padding: 0.2rem; border-left: 1px darkgrey solid; } From 43c0c67f31dca33fdb9a13966d1ab4764e83b08f Mon Sep 17 00:00:00 2001 From: Pierre Date: Mon, 13 Jan 2020 14:06:27 +0200 Subject: [PATCH 04/11] Search of final page of records no longer displays blank cells --- app.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app.ts b/app.ts index cb56f314..9c3f2ed5 100644 --- a/app.ts +++ b/app.ts @@ -3,7 +3,7 @@ window.onload = () => { let numColumns: number; let columns: any; let recordCount: number; - let startIndex = 0; // Default value = 20; + let startIndex = 0; // Default value = 0; let tableRecordCount = 20; // Default value = 20; // Canvas: @@ -28,7 +28,7 @@ window.onload = () => { adjustTableRecordCount(); let end = tableRecordCount - 1; if (recordCount < startIndex + tableRecordCount) { - end = recordCount - startIndex - 1; + startIndex = recordCount - tableRecordCount; } getRecords(startIndex, startIndex + end); } @@ -41,9 +41,9 @@ window.onload = () => { let end = tableRecordCount - 1; startIndex = from; if (recordCount < startIndex + tableRecordCount) { - end = recordCount - startIndex - 1; + startIndex = recordCount - tableRecordCount; } - getRecords(from, startIndex + end); + getRecords(startIndex, startIndex + end); } }; @@ -52,7 +52,7 @@ window.onload = () => { if (recordCount > startIndex + tableRecordCount) { startIndex += tableRecordCount; if (recordCount < startIndex + tableRecordCount) { - end = recordCount - startIndex - 1; + startIndex = recordCount - tableRecordCount; } getRecords(startIndex, startIndex + end); } From 4b2adee3fea8e6d86725b78205675629aa863d8a Mon Sep 17 00:00:00 2001 From: Pierre Date: Mon, 13 Jan 2020 15:04:35 +0200 Subject: [PATCH 05/11] debounced the window resize to limit network traffic --- app.ts | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/app.ts b/app.ts index 9c3f2ed5..582ffd2d 100644 --- a/app.ts +++ b/app.ts @@ -5,6 +5,7 @@ window.onload = () => { let recordCount: number; let startIndex = 0; // Default value = 0; let tableRecordCount = 20; // Default value = 20; + let timer: number; // Canvas: let canvas = document.createElement("div"); @@ -25,13 +26,19 @@ window.onload = () => { fromField.placeholder = "from"; window.onresize = () => { - adjustTableRecordCount(); - let end = tableRecordCount - 1; - if (recordCount < startIndex + tableRecordCount) { - startIndex = recordCount - tableRecordCount; - } - getRecords(startIndex, startIndex + end); + let time = 500; + clearInterval(timer); + timer = setInterval(function () { + clearInterval(timer); + adjustTableRecordCount(); + let end = tableRecordCount - 1; + if (recordCount < startIndex + tableRecordCount) { + startIndex = recordCount - tableRecordCount; + } + getRecords(startIndex, startIndex + end); + }, time); } + // on clicks: searchbtn.onclick = function() { From 7278168c559c5d0c269cf1b8a841882a07f9c133 Mon Sep 17 00:00:00 2001 From: Pierre Date: Mon, 13 Jan 2020 16:58:46 +0200 Subject: [PATCH 06/11] Improved table responsiveness, fixed table cell resize issues --- app.ts | 9 ++++++--- app_styles.css | 1 - 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app.ts b/app.ts index 582ffd2d..7186bc1c 100644 --- a/app.ts +++ b/app.ts @@ -25,6 +25,7 @@ window.onload = () => { let fromField = document.createElement("input"); fromField.placeholder = "from"; + // Window resizing (using a debouncing method): window.onresize = () => { let time = 500; clearInterval(timer); @@ -39,7 +40,6 @@ window.onload = () => { }, time); } - // on clicks: searchbtn.onclick = function() { let from = parseInt(fromField.value, 10); @@ -206,8 +206,11 @@ window.onload = () => { let height = window.innerHeight; let fontSize = getComputedStyle(document.documentElement).fontSize + ""; let rowHeight = parseFloat(fontSize)*2.5; - if (rowHeight !== undefined) - tableRecordCount = Math.trunc(height/rowHeight) - 4; + if (rowHeight !== undefined){ + tableRecordCount = Math.trunc(height/rowHeight)-2; + if (tableRecordCount < 1) + tableRecordCount = 1; + } } } \ No newline at end of file diff --git a/app_styles.css b/app_styles.css index 9a863c17..1ca1873f 100644 --- a/app_styles.css +++ b/app_styles.css @@ -11,7 +11,6 @@ input, button { table { border-collapse: collapse; width: 100%; - height: 90%; table-layout: fixed; overflow: hidden; font-size: 0.8rem; From 163d9963f8efcf22d56faf6909837966d781f8ea Mon Sep 17 00:00:00 2001 From: Pierre Date: Tue, 14 Jan 2020 08:27:43 +0200 Subject: [PATCH 07/11] Code review submission --- app.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.ts b/app.ts index 7186bc1c..e37565e1 100644 --- a/app.ts +++ b/app.ts @@ -27,7 +27,7 @@ window.onload = () => { // Window resizing (using a debouncing method): window.onresize = () => { - let time = 500; + let time = 100; clearInterval(timer); timer = setInterval(function () { clearInterval(timer); From f59346aafc4eca2d288ef88c2c45a4bfd8f5f3e4 Mon Sep 17 00:00:00 2001 From: Pierre Date: Tue, 14 Jan 2020 11:00:30 +0200 Subject: [PATCH 08/11] fixed tab indents --- app.ts | 358 ++++++++++++++++++++++++------------------------- app_styles.css | 33 +++-- 2 files changed, 195 insertions(+), 196 deletions(-) diff --git a/app.ts b/app.ts index e37565e1..839358cb 100644 --- a/app.ts +++ b/app.ts @@ -1,216 +1,216 @@ window.onload = () => { - let numColumns: number; - let columns: any; - let recordCount: number; - let startIndex = 0; // Default value = 0; - let tableRecordCount = 20; // Default value = 20; - let timer: number; - - // Canvas: - let canvas = document.createElement("div"); - canvas.id = "canvas"; - $("body").append(canvas); - - // Buttons and fields: - let searchbtn = document.createElement("button"); - searchbtn.innerText = "Search"; - - let nextbtn = document.createElement("button"); - nextbtn.innerText = "Next Page"; - - let prevbtn = document.createElement("button"); - prevbtn.innerText = "Previous Page"; - - let fromField = document.createElement("input"); - fromField.placeholder = "from"; - - // Window resizing (using a debouncing method): - window.onresize = () => { - let time = 100; - clearInterval(timer); - timer = setInterval(function () { - clearInterval(timer); - adjustTableRecordCount(); - let end = tableRecordCount - 1; - if (recordCount < startIndex + tableRecordCount) { - startIndex = recordCount - tableRecordCount; - } - getRecords(startIndex, startIndex + end); - }, time); - } - - // on clicks: - searchbtn.onclick = function() { - let from = parseInt(fromField.value, 10); - // validate field: - if (validate(from)) { - let end = tableRecordCount - 1; - startIndex = from; - if (recordCount < startIndex + tableRecordCount) { - startIndex = recordCount - tableRecordCount; - } - getRecords(startIndex, startIndex + end); - } - }; - - nextbtn.onclick = function() { - let end = tableRecordCount - 1; - if (recordCount > startIndex + tableRecordCount) { - startIndex += tableRecordCount; - if (recordCount < startIndex + tableRecordCount) { - startIndex = recordCount - tableRecordCount; - } - getRecords(startIndex, startIndex + end); - } - }; - - prevbtn.onclick = function() { - if (startIndex >= tableRecordCount) { - startIndex -= tableRecordCount; - } else if (startIndex < tableRecordCount) { - startIndex = 0; - } - getRecords(startIndex, startIndex + tableRecordCount - 1); - }; - - $("#canvas").append(fromField,searchbtn, prevbtn, nextbtn); - - initiate(); + let numColumns: number; + let columns: any; + let recordCount: number; + let startIndex = 0; // Default value = 0; + let tableRecordCount = 20; // Default value = 20; + let timer: number; + + // Canvas: + let canvas = document.createElement("div"); + canvas.id = "canvas"; + $("body").append(canvas); + + // Buttons and fields: + let searchbtn = document.createElement("button"); + searchbtn.innerText = "Search"; + + let nextbtn = document.createElement("button"); + nextbtn.innerText = "Next Page"; + + let prevbtn = document.createElement("button"); + prevbtn.innerText = "Previous Page"; + + let fromField = document.createElement("input"); + fromField.placeholder = "from"; + + // Window resizing (using a debouncing method): + window.onresize = () => { + let time = 100; + clearInterval(timer); + timer = setInterval(function () { + clearInterval(timer); + adjustTableRecordCount(); + let end = tableRecordCount - 1; + if (recordCount < startIndex + tableRecordCount) { + startIndex = recordCount - tableRecordCount; + } + getRecords(startIndex, startIndex + end); + }, time); + } + + // on clicks: + searchbtn.onclick = function () { + let from = parseInt(fromField.value, 10); + // validate field: + if (validate(from)) { + let end = tableRecordCount - 1; + startIndex = from; + if (recordCount < startIndex + tableRecordCount) { + startIndex = recordCount - tableRecordCount; + } + getRecords(startIndex, startIndex + end); + } + }; + + nextbtn.onclick = function () { + let end = tableRecordCount - 1; + if (recordCount > startIndex + tableRecordCount) { + startIndex += tableRecordCount; + if (recordCount < startIndex + tableRecordCount) { + startIndex = recordCount - tableRecordCount; + } + getRecords(startIndex, startIndex + end); + } + }; + + prevbtn.onclick = function () { + if (startIndex >= tableRecordCount) { + startIndex -= tableRecordCount; + } else if (startIndex < tableRecordCount) { + startIndex = 0; + } + getRecords(startIndex, startIndex + tableRecordCount - 1); + }; + + $("#canvas").append(fromField, searchbtn, prevbtn, nextbtn); + + initiate(); /** * Initiates the HTTP requests to obtain the records and column values necessary for the table. */ - function initiate() { - // get number of records: - $.ajax({ - url: "http://localhost:2050/recordCount", - success: function (result) { - recordCount = parseInt(JSON.parse(result), 10); - // get columns: - $.ajax({ - url: "http://localhost:2050/columns", - success: function (result) { - columns = JSON.parse(result); - numColumns = getSize(columns); - // get first page of records and display them: - adjustTableRecordCount(); - getRecords(0, tableRecordCount - 1); - }, - error: function (err) { - $("body").text("Error: " + err.status + " " + err.statusText); - } - }); - }, - error: function (err) { - $("body").text("Error: " + err.status + " " + err.statusText); - } - }); - } + function initiate() { + // get number of records: + $.ajax({ + url: "http://localhost:2050/recordCount", + success: function (result) { + recordCount = parseInt(JSON.parse(result), 10); + // get columns: + $.ajax({ + url: "http://localhost:2050/columns", + success: function (result) { + columns = JSON.parse(result); + numColumns = getSize(columns); + // get first page of records and display them: + adjustTableRecordCount(); + getRecords(0, tableRecordCount - 1); + }, + error: function (err) { + $("body").text("Error: " + err.status + " " + err.statusText); + } + }); + }, + error: function (err) { + $("body").text("Error: " + err.status + " " + err.statusText); + } + }); + } /** * Generates a table populated with data, distrubuted evenly. * @param data The data records retrieved from the server, structured as a 2D object array. * @param columns An object array containing the column heading values. */ - function generateTable(data: any, columns: any) { - $("table").remove(); // Remove previous table - let dataSize = getSize(data); - let table = document.createElement("table"); - let tbdy = document.createElement("tbody"); - table.appendChild(generateHeadings(columns)); - for (let i = 0; i < tableRecordCount; i++){ - let tr = document.createElement("tr"); - for (let j = 0; j < numColumns; j++){ - let td = document.createElement("td"); - if (dataSize > i) - td.appendChild(document.createTextNode(data[i][j])); - tr.appendChild(td); - } - tbdy.appendChild(tr); - } - table.appendChild(tbdy); - canvas.appendChild(table); - } + function generateTable(data: any, columns: any) { + $("table").remove(); // Remove previous table + let dataSize = getSize(data); + let table = document.createElement("table"); + let tbdy = document.createElement("tbody"); + table.appendChild(generateHeadings(columns)); + for (let i = 0; i < tableRecordCount; i++) { + let tr = document.createElement("tr"); + for (let j = 0; j < numColumns; j++) { + let td = document.createElement("td"); + if (dataSize > i) + td.appendChild(document.createTextNode(data[i][j])); + tr.appendChild(td); + } + tbdy.appendChild(tr); + } + table.appendChild(tbdy); + canvas.appendChild(table); + } /** * Finds the number of entries within a data set. * @param data An array of data, type is unknown (any). */ - function getSize(data: any) { - let i = 0; - let entry; - for (entry in data) { - i++; - } - return i; - } + function getSize(data: any) { + let i = 0; + let entry; + for (entry in data) { + i++; + } + return i; + } /** * Sends out an HTTP request to retrieve data records, coupled with generating a table to display the records. * @param from The ID value from which to start searching. * @param to The ID value from which to stop searching. */ - function getRecords(from: number, to: number) { - $.ajax({ - url: "http://localhost:2050/records", - data: {from: from, to: to}, - success: function (result) { - let data = JSON.parse(result); - generateTable(data, columns); - }, - error: function (err) { - $("body").text("Error: " + err.status + " " + err.statusText); - } - }); - } + function getRecords(from: number, to: number) { + $.ajax({ + url: "http://localhost:2050/records", + data: { from: from, to: to }, + success: function (result) { + let data = JSON.parse(result); + generateTable(data, columns); + }, + error: function (err) { + $("body").text("Error: " + err.status + " " + err.statusText); + } + }); + } /** * Generates and returns a "thead" object containing column headings. * @param columns An object array containing the column heading values. */ - function generateHeadings(columns: any) { - let thead = document.createElement("thead"); - let tr = document.createElement("tr"); - for (let j = 0; j < numColumns; j++) { - let td = document.createElement("td"); - td.appendChild(document.createTextNode(columns[j])); - tr.appendChild(td); - } - thead.appendChild(tr); - return thead; - } + function generateHeadings(columns: any) { + let thead = document.createElement("thead"); + let tr = document.createElement("tr"); + for (let j = 0; j < numColumns; j++) { + let td = document.createElement("td"); + td.appendChild(document.createTextNode(columns[j])); + tr.appendChild(td); + } + thead.appendChild(tr); + return thead; + } /** * Validates that the field value is a number. * @param from The ID value from which to start searching. */ - function validate(from: number) { - if (isNaN(from)) { - alert("\"From\" field does not have a number value."); - return false; - } else if (from < 0) { - alert("\"From\" value cannot be negative."); - return false; - } else if (from > recordCount-1) { - alert("\"From\" value exceeds the record count."); - return false; - } - return true; - } + function validate(from: number) { + if (isNaN(from)) { + alert("\"From\" field does not have a number value."); + return false; + } else if (from < 0) { + alert("\"From\" value cannot be negative."); + return false; + } else if (from > recordCount - 1) { + alert("\"From\" value exceeds the record count."); + return false; + } + return true; + } /** * Adjust the number of records shown in the table according to the window size. */ - function adjustTableRecordCount() { - let height = window.innerHeight; - let fontSize = getComputedStyle(document.documentElement).fontSize + ""; - let rowHeight = parseFloat(fontSize)*2.5; - if (rowHeight !== undefined){ - tableRecordCount = Math.trunc(height/rowHeight)-2; - if (tableRecordCount < 1) - tableRecordCount = 1; - } - } - -} \ No newline at end of file + function adjustTableRecordCount() { + let height = window.innerHeight; + let fontSize = getComputedStyle(document.documentElement).fontSize + ""; + let rowHeight = parseFloat(fontSize) * 2.5; + if (rowHeight !== undefined) { + tableRecordCount = Math.trunc(height / rowHeight) - 2; + if (tableRecordCount < 1) + tableRecordCount = 1; + } + } + +} diff --git a/app_styles.css b/app_styles.css index 1ca1873f..b0ee2608 100644 --- a/app_styles.css +++ b/app_styles.css @@ -1,37 +1,36 @@ input, button { - display: inline; - padding: 0.5rem; + display: inline; + padding: 0.5rem; } #canvas { - width: 100vw; - height: 100vh; + width: 100vw; + height: 100vh; } table { - border-collapse: collapse; - width: 100%; - table-layout: fixed; - overflow: hidden; - font-size: 0.8rem; + border-collapse: collapse; + width: 100%; + table-layout: fixed; + overflow: hidden; + font-size: 0.8rem; } td { - width: 9%; - height: 2rem; - padding: 0.2rem; - border-left: 1px darkgrey solid; + width: 9%; + height: 2rem; + padding: 0.2rem; + border-left: 1px darkgrey solid; } tr:hover { - background-color: lightgrey; + background-color: lightgrey; } tr { - border: 1px darkgrey solid; + border: 1px darkgrey solid; } html { - overflow: hidden; + overflow: hidden; } - From 1afa832df6e1f8e357f7d90f72ae9b6e46c421c5 Mon Sep 17 00:00:00 2001 From: Pierre Date: Tue, 14 Jan 2020 11:18:59 +0200 Subject: [PATCH 09/11] Reworked the window onload function --- app.ts | 386 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 194 insertions(+), 192 deletions(-) diff --git a/app.ts b/app.ts index 839358cb..e2392c79 100644 --- a/app.ts +++ b/app.ts @@ -1,216 +1,218 @@ -window.onload = () => { - - let numColumns: number; - let columns: any; - let recordCount: number; - let startIndex = 0; // Default value = 0; - let tableRecordCount = 20; // Default value = 20; - let timer: number; - - // Canvas: - let canvas = document.createElement("div"); - canvas.id = "canvas"; - $("body").append(canvas); - - // Buttons and fields: - let searchbtn = document.createElement("button"); - searchbtn.innerText = "Search"; - - let nextbtn = document.createElement("button"); - nextbtn.innerText = "Next Page"; - - let prevbtn = document.createElement("button"); - prevbtn.innerText = "Previous Page"; - - let fromField = document.createElement("input"); - fromField.placeholder = "from"; - - // Window resizing (using a debouncing method): - window.onresize = () => { - let time = 100; - clearInterval(timer); - timer = setInterval(function () { - clearInterval(timer); - adjustTableRecordCount(); - let end = tableRecordCount - 1; - if (recordCount < startIndex + tableRecordCount) { - startIndex = recordCount - tableRecordCount; - } - getRecords(startIndex, startIndex + end); - }, time); - } - - // on clicks: - searchbtn.onclick = function () { - let from = parseInt(fromField.value, 10); - // validate field: - if (validate(from)) { - let end = tableRecordCount - 1; - startIndex = from; - if (recordCount < startIndex + tableRecordCount) { - startIndex = recordCount - tableRecordCount; - } - getRecords(startIndex, startIndex + end); - } - }; - - nextbtn.onclick = function () { +let numColumns: number; +let columns: any; +let recordCount: number; +let startIndex = 0; // Default value = 0; +let tableRecordCount = 20; // Default value = 20; +let timer: number; + +// Canvas: +let canvas = document.createElement("div"); + +// Buttons and fields: +let searchbtn = document.createElement("button"); +searchbtn.innerText = "Search"; + +let nextbtn = document.createElement("button"); +nextbtn.innerText = "Next Page"; + +let prevbtn = document.createElement("button"); +prevbtn.innerText = "Previous Page"; + +let fromField = document.createElement("input"); +fromField.placeholder = "from"; + +// Append fields and buttons to canvas +canvas.appendChild(fromField); +canvas.appendChild(searchbtn); +canvas.appendChild(prevbtn); +canvas.appendChild(nextbtn); + +// on clicks: +searchbtn.onclick = function () { + let from = parseInt(fromField.value, 10); + // validate field: + if (validate(from)) { let end = tableRecordCount - 1; - if (recordCount > startIndex + tableRecordCount) { - startIndex += tableRecordCount; - if (recordCount < startIndex + tableRecordCount) { - startIndex = recordCount - tableRecordCount; - } - getRecords(startIndex, startIndex + end); + startIndex = from; + if (recordCount < startIndex + tableRecordCount) { + startIndex = recordCount - tableRecordCount; } - }; - - prevbtn.onclick = function () { - if (startIndex >= tableRecordCount) { - startIndex -= tableRecordCount; - } else if (startIndex < tableRecordCount) { - startIndex = 0; + getRecords(startIndex, startIndex + end); + } +}; + +nextbtn.onclick = function () { + let end = tableRecordCount - 1; + if (recordCount > startIndex + tableRecordCount) { + startIndex += tableRecordCount; + if (recordCount < startIndex + tableRecordCount) { + startIndex = recordCount - tableRecordCount; } - getRecords(startIndex, startIndex + tableRecordCount - 1); - }; + getRecords(startIndex, startIndex + end); + } +}; - $("#canvas").append(fromField, searchbtn, prevbtn, nextbtn); +prevbtn.onclick = function () { + if (startIndex >= tableRecordCount) { + startIndex -= tableRecordCount; + } else if (startIndex < tableRecordCount) { + startIndex = 0; + } + getRecords(startIndex, startIndex + tableRecordCount - 1); +}; +// When the window page loads for the first time: +window.onload = () => { + $("body").append(canvas); initiate(); +} - /** - * Initiates the HTTP requests to obtain the records and column values necessary for the table. - */ - function initiate() { - // get number of records: - $.ajax({ - url: "http://localhost:2050/recordCount", - success: function (result) { - recordCount = parseInt(JSON.parse(result), 10); - // get columns: - $.ajax({ - url: "http://localhost:2050/columns", - success: function (result) { - columns = JSON.parse(result); - numColumns = getSize(columns); - // get first page of records and display them: - adjustTableRecordCount(); - getRecords(0, tableRecordCount - 1); - }, - error: function (err) { - $("body").text("Error: " + err.status + " " + err.statusText); - } - }); - }, - error: function (err) { - $("body").text("Error: " + err.status + " " + err.statusText); - } - }); - } - - /** - * Generates a table populated with data, distrubuted evenly. - * @param data The data records retrieved from the server, structured as a 2D object array. - * @param columns An object array containing the column heading values. - */ - function generateTable(data: any, columns: any) { - $("table").remove(); // Remove previous table - let dataSize = getSize(data); - let table = document.createElement("table"); - let tbdy = document.createElement("tbody"); - table.appendChild(generateHeadings(columns)); - for (let i = 0; i < tableRecordCount; i++) { - let tr = document.createElement("tr"); - for (let j = 0; j < numColumns; j++) { - let td = document.createElement("td"); - if (dataSize > i) - td.appendChild(document.createTextNode(data[i][j])); - tr.appendChild(td); - } - tbdy.appendChild(tr); +// Window resizing (using a debouncing method): +window.onresize = () => { + let time = 100; + clearInterval(timer); + timer = setInterval(function () { + clearInterval(timer); + adjustTableRecordCount(); + let end = tableRecordCount - 1; + if (recordCount < startIndex + tableRecordCount) { + startIndex = recordCount - tableRecordCount; } - table.appendChild(tbdy); - canvas.appendChild(table); - } + getRecords(startIndex, startIndex + end); + }, time); +} - /** - * Finds the number of entries within a data set. - * @param data An array of data, type is unknown (any). - */ - function getSize(data: any) { - let i = 0; - let entry; - for (entry in data) { - i++; +/** + * Initiates the HTTP requests to obtain the records and column values necessary for the table. + */ +function initiate() { + // get number of records: + $.ajax({ + url: "http://localhost:2050/recordCount", + success: function (result) { + recordCount = parseInt(JSON.parse(result), 10); + // get columns: + $.ajax({ + url: "http://localhost:2050/columns", + success: function (result) { + columns = JSON.parse(result); + numColumns = getSize(columns); + // get first page of records and display them: + adjustTableRecordCount(); + getRecords(0, tableRecordCount - 1); + }, + error: function (err) { + $("body").text("Error: " + err.status + " " + err.statusText); + } + }); + }, + error: function (err) { + $("body").text("Error: " + err.status + " " + err.statusText); } - return i; - } - - /** - * Sends out an HTTP request to retrieve data records, coupled with generating a table to display the records. - * @param from The ID value from which to start searching. - * @param to The ID value from which to stop searching. - */ - function getRecords(from: number, to: number) { - $.ajax({ - url: "http://localhost:2050/records", - data: { from: from, to: to }, - success: function (result) { - let data = JSON.parse(result); - generateTable(data, columns); - }, - error: function (err) { - $("body").text("Error: " + err.status + " " + err.statusText); - } - }); - } + }); +} - /** - * Generates and returns a "thead" object containing column headings. - * @param columns An object array containing the column heading values. - */ - function generateHeadings(columns: any) { - let thead = document.createElement("thead"); +/** + * Generates a table populated with data, distrubuted evenly. + * @param data The data records retrieved from the server, structured as a 2D object array. + * @param columns An object array containing the column heading values. + */ +function generateTable(data: any, columns: any) { + $("table").remove(); // Remove previous table + let dataSize = getSize(data); + let table = document.createElement("table"); + let tbdy = document.createElement("tbody"); + table.appendChild(generateHeadings(columns)); + for (let i = 0; i < tableRecordCount; i++) { let tr = document.createElement("tr"); for (let j = 0; j < numColumns; j++) { let td = document.createElement("td"); - td.appendChild(document.createTextNode(columns[j])); + if (dataSize > i) + td.appendChild(document.createTextNode(data[i][j])); tr.appendChild(td); } - thead.appendChild(tr); - return thead; + tbdy.appendChild(tr); } + table.appendChild(tbdy); + canvas.appendChild(table); +} - /** - * Validates that the field value is a number. - * @param from The ID value from which to start searching. - */ - function validate(from: number) { - if (isNaN(from)) { - alert("\"From\" field does not have a number value."); - return false; - } else if (from < 0) { - alert("\"From\" value cannot be negative."); - return false; - } else if (from > recordCount - 1) { - alert("\"From\" value exceeds the record count."); - return false; - } - return true; +/** + * Finds the number of entries within a data set. + * @param data An array of data, type is unknown (any). + */ +function getSize(data: any) { + let i = 0; + let entry; + for (entry in data) { + i++; } + return i; +} - /** - * Adjust the number of records shown in the table according to the window size. - */ - function adjustTableRecordCount() { - let height = window.innerHeight; - let fontSize = getComputedStyle(document.documentElement).fontSize + ""; - let rowHeight = parseFloat(fontSize) * 2.5; - if (rowHeight !== undefined) { - tableRecordCount = Math.trunc(height / rowHeight) - 2; - if (tableRecordCount < 1) - tableRecordCount = 1; +/** + * Sends out an HTTP request to retrieve data records, coupled with generating a table to display the records. + * @param from The ID value from which to start searching. + * @param to The ID value from which to stop searching. + */ +function getRecords(from: number, to: number) { + $.ajax({ + url: "http://localhost:2050/records", + data: { from: from, to: to }, + success: function (result) { + let data = JSON.parse(result); + generateTable(data, columns); + }, + error: function (err) { + $("body").text("Error: " + err.status + " " + err.statusText); } + }); +} + +/** + * Generates and returns a "thead" object containing column headings. + * @param columns An object array containing the column heading values. + */ +function generateHeadings(columns: any) { + let thead = document.createElement("thead"); + let tr = document.createElement("tr"); + for (let j = 0; j < numColumns; j++) { + let td = document.createElement("td"); + td.appendChild(document.createTextNode(columns[j])); + tr.appendChild(td); } + thead.appendChild(tr); + return thead; +} +/** + * Validates that the field value is a number. + * @param from The ID value from which to start searching. + */ +function validate(from: number) { + if (isNaN(from)) { + alert("\"From\" field does not have a number value."); + return false; + } else if (from < 0) { + alert("\"From\" value cannot be negative."); + return false; + } else if (from > recordCount - 1) { + alert("\"From\" value exceeds the record count."); + return false; + } + return true; +} + +/** + * Adjust the number of records shown in the table according to the window size. + */ +function adjustTableRecordCount() { + let height = window.innerHeight; + let fontSize = getComputedStyle(document.documentElement).fontSize + ""; + let rowHeight = parseFloat(fontSize) * 2.5; + if (rowHeight !== undefined) { + tableRecordCount = Math.trunc(height / rowHeight) - 2; + if (tableRecordCount < 1) + tableRecordCount = 1; + } } From 0dbb7635ffbe97a031fdf04e494343dad5214629 Mon Sep 17 00:00:00 2001 From: Pierre Date: Tue, 14 Jan 2020 11:44:57 +0200 Subject: [PATCH 10/11] Minor code fixes and improvements --- app.ts | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/app.ts b/app.ts index e2392c79..397a20c1 100644 --- a/app.ts +++ b/app.ts @@ -53,11 +53,7 @@ nextbtn.onclick = function () { }; prevbtn.onclick = function () { - if (startIndex >= tableRecordCount) { - startIndex -= tableRecordCount; - } else if (startIndex < tableRecordCount) { - startIndex = 0; - } + startIndex = startIndex >= tableRecordCount ? startIndex -= tableRecordCount : startIndex = 0; getRecords(startIndex, startIndex + tableRecordCount - 1); }; @@ -69,7 +65,7 @@ window.onload = () => { // Window resizing (using a debouncing method): window.onresize = () => { - let time = 100; + const time = 100; clearInterval(timer); timer = setInterval(function () { clearInterval(timer); @@ -85,7 +81,7 @@ window.onresize = () => { /** * Initiates the HTTP requests to obtain the records and column values necessary for the table. */ -function initiate() { +const initiate = () => { // get number of records: $.ajax({ url: "http://localhost:2050/recordCount", @@ -117,9 +113,8 @@ function initiate() { * @param data The data records retrieved from the server, structured as a 2D object array. * @param columns An object array containing the column heading values. */ -function generateTable(data: any, columns: any) { +const generateTable = (data: any, columns: any) => { $("table").remove(); // Remove previous table - let dataSize = getSize(data); let table = document.createElement("table"); let tbdy = document.createElement("tbody"); table.appendChild(generateHeadings(columns)); @@ -127,8 +122,7 @@ function generateTable(data: any, columns: any) { let tr = document.createElement("tr"); for (let j = 0; j < numColumns; j++) { let td = document.createElement("td"); - if (dataSize > i) - td.appendChild(document.createTextNode(data[i][j])); + td.appendChild(document.createTextNode(data[i][j])); tr.appendChild(td); } tbdy.appendChild(tr); @@ -141,10 +135,9 @@ function generateTable(data: any, columns: any) { * Finds the number of entries within a data set. * @param data An array of data, type is unknown (any). */ -function getSize(data: any) { +const getSize = (data: any) => { let i = 0; - let entry; - for (entry in data) { + for (let entry in data) { i++; } return i; @@ -155,7 +148,7 @@ function getSize(data: any) { * @param from The ID value from which to start searching. * @param to The ID value from which to stop searching. */ -function getRecords(from: number, to: number) { +const getRecords = (from: number, to: number) => { $.ajax({ url: "http://localhost:2050/records", data: { from: from, to: to }, @@ -173,7 +166,7 @@ function getRecords(from: number, to: number) { * Generates and returns a "thead" object containing column headings. * @param columns An object array containing the column heading values. */ -function generateHeadings(columns: any) { +const generateHeadings = (columns: any) => { let thead = document.createElement("thead"); let tr = document.createElement("tr"); for (let j = 0; j < numColumns; j++) { @@ -189,15 +182,15 @@ function generateHeadings(columns: any) { * Validates that the field value is a number. * @param from The ID value from which to start searching. */ -function validate(from: number) { +const validate = (from: number) => { if (isNaN(from)) { - alert("\"From\" field does not have a number value."); + alert('"From" field does not have a number value.'); return false; } else if (from < 0) { - alert("\"From\" value cannot be negative."); + alert('"From" value cannot be negative.'); return false; } else if (from > recordCount - 1) { - alert("\"From\" value exceeds the record count."); + alert('"From" value exceeds the record count.'); return false; } return true; @@ -206,13 +199,12 @@ function validate(from: number) { /** * Adjust the number of records shown in the table according to the window size. */ -function adjustTableRecordCount() { +const adjustTableRecordCount = () => { let height = window.innerHeight; let fontSize = getComputedStyle(document.documentElement).fontSize + ""; let rowHeight = parseFloat(fontSize) * 2.5; if (rowHeight !== undefined) { - tableRecordCount = Math.trunc(height / rowHeight) - 2; - if (tableRecordCount < 1) - tableRecordCount = 1; + const count = tableRecordCount = Math.trunc(height / rowHeight) - 2; + tableRecordCount = count >= 1 ? count : 1; } } From 047f25688800fc1bfd16f4bc0405d40a37be0268 Mon Sep 17 00:00:00 2001 From: Pierre Date: Tue, 14 Jan 2020 12:56:14 +0200 Subject: [PATCH 11/11] Table is no longer removed when refreshing table --- app.ts | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/app.ts b/app.ts index 397a20c1..3b7958ff 100644 --- a/app.ts +++ b/app.ts @@ -8,6 +8,13 @@ let timer: number; // Canvas: let canvas = document.createElement("div"); +// Table: +let table = document.createElement("table"); +let tbdy = document.createElement("tbody"); +let thead = document.createElement("thead"); +table.appendChild(thead); +table.appendChild(tbdy); + // Buttons and fields: let searchbtn = document.createElement("button"); searchbtn.innerText = "Search"; @@ -26,6 +33,7 @@ canvas.appendChild(fromField); canvas.appendChild(searchbtn); canvas.appendChild(prevbtn); canvas.appendChild(nextbtn); +canvas.appendChild(table); // on clicks: searchbtn.onclick = function () { @@ -93,6 +101,8 @@ const initiate = () => { success: function (result) { columns = JSON.parse(result); numColumns = getSize(columns); + // generate and append the headings to the table: + generateHeadings(columns); // get first page of records and display them: adjustTableRecordCount(); getRecords(0, tableRecordCount - 1); @@ -109,15 +119,12 @@ const initiate = () => { } /** - * Generates a table populated with data, distrubuted evenly. + * Populates the table with data, distrubuted evenly. * @param data The data records retrieved from the server, structured as a 2D object array. * @param columns An object array containing the column heading values. */ -const generateTable = (data: any, columns: any) => { - $("table").remove(); // Remove previous table - let table = document.createElement("table"); - let tbdy = document.createElement("tbody"); - table.appendChild(generateHeadings(columns)); +const fillTable = (data: any) => { + $("tbody").empty(); for (let i = 0; i < tableRecordCount; i++) { let tr = document.createElement("tr"); for (let j = 0; j < numColumns; j++) { @@ -127,8 +134,6 @@ const generateTable = (data: any, columns: any) => { } tbdy.appendChild(tr); } - table.appendChild(tbdy); - canvas.appendChild(table); } /** @@ -154,7 +159,7 @@ const getRecords = (from: number, to: number) => { data: { from: from, to: to }, success: function (result) { let data = JSON.parse(result); - generateTable(data, columns); + fillTable(data); }, error: function (err) { $("body").text("Error: " + err.status + " " + err.statusText); @@ -167,7 +172,6 @@ const getRecords = (from: number, to: number) => { * @param columns An object array containing the column heading values. */ const generateHeadings = (columns: any) => { - let thead = document.createElement("thead"); let tr = document.createElement("tr"); for (let j = 0; j < numColumns; j++) { let td = document.createElement("td"); @@ -175,7 +179,6 @@ const generateHeadings = (columns: any) => { tr.appendChild(td); } thead.appendChild(tr); - return thead; } /**