Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions app.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
body{
overflow: hidden;
font-family: Verdana, Geneva, sans-serif;
text-align: center;
margin: 4px;
}
table.gridtable{
width: 100%;
font-size:12px;
color:#333333;
border-color: #D7D7D7;
border-collapse: collapse;
}
table.gridtable th {
border-width: 0.5px;
height: 32px;
border-style: solid;
border-color: #D7D7D7;
background-color: #D3EFFF;
}
table.gridtable td {
border-width: 0.5px;
height: 32px;
border-style: solid;
border-color: #D7D7D7;
background-color: #ffffff;
}
table.gridtable td:hover{
background-color: #f1f1f1;
}
.footer{
height: 48px;
left: 50%;
transform: translateX(-50%);
position: absolute;
bottom: 4px;
user-select: none;
}
a{
color: black;
padding: 8px;
text-decoration: none;
transition: background-color .3s;
}
/* Add a grey background color on mouse-over */
a:hover:not(.active) {background-color: #D8E9F2;}
/* search field */
#search{
display: inline-block;
width: 84px;
font-size: 12px;
padding: 8px;
border: 1px solid #ddd;
}
.loader{
position: absolute;
left: 46.5%;
top: 40%;
border: 16px solid #f3f3f3;
border-radius: 50%;
border-top: 16px solid #3498db;
width: 120px;
height: 120px;
animation: spin 2s linear infinite;
}
140 changes: 140 additions & 0 deletions app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
let firstIndex: number, lastIndex: number; // stores the indices of the first and last rows in the table
let recordCount: number; // stores the number of records in the database
let table, columns, thead, tbody, headRow; // stores column headers
let resizeTimer; // stores time since last window resize

// builds the grid table from the column headers and row data
function buildTable(rows) {

// initialise table
table = document.createElement("table");
table.className = "gridtable";
thead = document.createElement("thead");
tbody = document.createElement("tbody");
headRow = document.createElement("tr");

// build column headers
for (const header of columns) {
let th = document.createElement("th");
th.appendChild(document.createTextNode(header));
headRow.appendChild(th);
};
thead.appendChild(headRow);
table.appendChild(thead);

// create rows
for (const el of rows) {
let tr = document.createElement("tr");
for (let o in el) {
let td = document.createElement("td");
td.appendChild(document.createTextNode(el[o]))
tr.appendChild(td);
}
tbody.appendChild(tr);
}
table.appendChild(tbody);

// builds footer elements (buttons, search field)
document.getElementById("footer").innerHTML = `<a onclick="goPrevious()">&laquo;</a>
<a onclick="goNext()">&raquo;</a>
<input type="text" id="search" onkeyup="search(event)" placeholder="Enter ID...">`;

document.getElementById("loader").remove();

return table;
}

// filters rows by user input ID
function search(e) {
let input = $("#search").val().toString();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It isn't a problem here, but when working in the codebase for our other projects, you will need to use more specific div IDs since they are in a "global namespace" of sorts and could conflict with the naming of existing divs.

let $table = $("tbody tr").toArray();

for (const record of $table) {
let td = record.getElementsByTagName("td")[0];
record.style.display = "block";
if (td) {
let val = td.innerText || td.textContent;
record.style.display = val.indexOf(input) > -1 ? "" : "none";
}
}

// if record doesn't exist on current page, query database and display results
if (e.which == 13) {
loadPage(parseInt(input));
}
}

// load the previous page
function goPrevious() {
let numRows = calculateRows();
if (lastIndex >= numRows) {
loadPage(firstIndex - numRows);
}
}

// load the next page
function goNext() {
if (lastIndex < recordCount - 1) {
loadPage(lastIndex + 1);
}
}

// loads the columns and rows to be displayed based on index of the first row
function loadPage(start: number) {
firstIndex = start;
lastIndex = calculateRows();

// clear table
document.getElementById("content").innerHTML = "";
document.getElementById("footer").innerHTML = "";

// check bounds
if (firstIndex < 0) firstIndex = 0;
if (lastIndex >= recordCount) lastIndex = recordCount - 1;
if (firstIndex >= recordCount) {
firstIndex = recordCount - calculateRows();
}

// create loader
let loader = document.createElement("loader");
document.getElementById("content").appendChild(loader);
loader.innerHTML = `<div class="loader" id="loader"></div>`;

// inner function to fetch rows from server and invoke table build function
$.get("http://localhost:2050/records?from=" + firstIndex + "&to=" + lastIndex, function (rows) {
document.getElementById("content").appendChild(buildTable(JSON.parse(rows)));
});
}

// determines the number of rows to display based on the window height
function calculateRows() {
let x = (window.innerHeight - document.getElementById("footer").offsetHeight - document.getElementById("tableHeading").offsetHeight - 64) / 37;
return Math.floor(x);
}

window.onload = function () {
// hide browser scroll bar
document.body.style.overflow = "hidden";

// get record count
$.get("http://localhost:2050/recordCount", function (numRecords) {

// get column headers from server
$.get("http://localhost:2050/columns", function (cols) {
columns = JSON.parse(cols);

// load the first page
loadPage(0);
recordCount = JSON.parse(numRecords);
});
});
}

// updates the table display when the window is resized
// debounce function to reduce frequency of queries made
window.onresize = () => {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function () {
loadPage(firstIndex);
}, 250);
}
21 changes: 13 additions & 8 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
<!DOCTYPE html>
<html>
<!DOCTYPE html>

<html lang="en">

<head>
<title>JS Onboard Project</title>
<script type="text/javascript" charset="utf-8" src="third_party/jquery-2.0.3.min.js"></script>
<meta charset="utf-8" />
<title>TEST</title>
<link rel="stylesheet" href="app.css" type="text/css" />
<script src="app.js"></script>
<script src="third_party/jquery-2.0.3.min.js"></script>
</head>

<body>
<p>Hello</p>
<h1 id="tableHeading">Table Heading</h1>
<div id="content"></div>
<div class="footer" id="footer"></div>
</body>

</html>

</html>