diff --git a/app.ts b/app.ts
new file mode 100644
index 00000000..dee58363
--- /dev/null
+++ b/app.ts
@@ -0,0 +1,281 @@
+let fromParameter = 0;
+let recordCount: number;
+
+// Gets The 2nd paramater from the 1st parameter
+function getParameters(fromParameter: number): number {
+ let toParameter: number;
+ let noOfRows = getNoOfRows();
+
+ toParameter = fromParameter + noOfRows;
+ return toParameter;
+}
+
+// Gets the number of rows on the screen
+function getNoOfRows(): number {
+ const height = window.innerHeight;
+ let noOfRows = Math.floor(height / 40);
+ return noOfRows;
+}
+
+//// Functions To Create The HTML
+// Heading Row
+function createHeadingColumn(headingData: string) {
+ const heading: HTMLElement | null = document.getElementById("heading");
+
+ let headings = `
${headingData}
`;
+ if (heading !== null) {
+ heading.innerHTML += headings;
+ }
+}
+
+// Table Content
+function appendTableContent(contentData: string | string[]) {
+ const content: HTMLElement | null = document.getElementById("content");
+
+ let table = ``;
+ if (content !== null) {
+ content.innerHTML += table;
+ } else {
+ return alert("ERROR");
+ }
+
+ let row: HTMLElement | null = document.getElementById("row-" + contentData[0]);
+ for (let x of contentData) {
+ let rowCols = `${x}
`;
+ if (row !== null) {
+ row.innerHTML += rowCols;
+ }
+ }
+}
+
+//// Fetch Requests
+// Response Error Handling
+function handleErrors(response: Response) {
+ if (!response.ok) {
+ throw Error(response.statusText);
+ }
+ return response;
+}
+
+// Heading Row (Getting the columns data)
+function getHeadings(): Promise {
+ return fetch("http://localhost:2050/columns", {
+ method: "GET",
+ headers: { "Content-Type": "application/json" },
+ })
+ .then(handleErrors)
+ .then((response: Response) => response.json())
+ .then((headingData: string[]) => {
+ for (let heading of headingData) {
+ createHeadingColumn(heading);
+ }
+ })
+ .catch((error: Error) => {
+ console.log(error);
+ });
+}
+
+// Table Content (Getting the table's data)
+function getTable(): Promise {
+ const content: HTMLElement | null = document.getElementById("content");
+ let toParameter = getParameters(fromParameter);
+ const pageStats: HTMLElement | null = document.getElementById("pageStats");
+
+ // Clears Table
+ if (content !== null) {
+ content.innerHTML = "";
+ }
+
+ // Displays The Current Results Being Shown
+ let currentStats = `Showing results from ${fromParameter} to ${toParameter} out of ${recordCount} results.`;
+ if (pageStats !== null) {
+ pageStats.innerHTML = currentStats;
+ }
+
+ return fetch(`http://localhost:2050/records?from=${fromParameter}&to=${toParameter}`, {
+ method: "GET",
+ headers: { "Content-Type": "application/json" },
+ })
+ .then(handleErrors)
+ .then((res: Response) => res.json())
+ .then((contentData: string[]) => {
+ for (let x of contentData) {
+ appendTableContent(x);
+ }
+ })
+ .catch((error: Error) => {
+ console.log(error);
+ });
+}
+
+// Gets Total Of All Records
+function getRecordCount(): Promise {
+ return fetch("http://localhost:2050/recordCount", {
+ method: "GET",
+ headers: { "Content-Type": "application/json" },
+ })
+ .then(handleErrors)
+ .then((res: Response) => res.json())
+ .then((data: number) => {
+ recordCount = data;
+ })
+ .catch((error: Error) => {
+ console.log(error);
+ });
+}
+
+//// Debounce
+function debounce(fn: () => void, delay: number) {
+ let timer: number
+ return function () {
+ clearTimeout(timer);
+ timer = setTimeout(() => {
+ fn();
+ }, delay);
+ };
+}
+
+//// Sizing And Resizing
+function resizing() {
+ let end = fromParameter + getNoOfRows();
+ let toParameter: number;
+ let maxRecordsID = recordCount - 1;
+
+ if (end > maxRecordsID) {
+ toParameter = maxRecordsID;
+ fromParameter = toParameter - getNoOfRows();
+ }
+ getTable();
+}
+
+//// Navigation
+// Next
+class Next {
+ nextButton: HTMLElement | null;
+ nextTimer: number = 0;
+
+ constructor() {
+ this.nextButton = document.getElementById("next");
+
+ const nextDebounce = (fn: () => void, delay: number) => {
+ clearTimeout(this.nextTimer);
+ this.nextTimer = setTimeout(() => {
+ fn();
+ }, delay);
+ };
+
+ let next = () => {
+ let toParameter = getParameters(fromParameter);
+ let maxRecordsID = recordCount - 1;
+
+ if (toParameter === maxRecordsID) {
+ alert("You have reached the final page");
+ }
+
+ let nextAmount = toParameter - fromParameter + 1;
+ fromParameter = fromParameter + nextAmount;
+ toParameter = fromParameter + getNoOfRows();
+
+ let end = fromParameter + getNoOfRows();
+
+ if (end > maxRecordsID) {
+ toParameter = maxRecordsID;
+ fromParameter = toParameter - getNoOfRows();
+ }
+
+ nextDebounce(getTable, 500);
+ };
+
+ if (this.nextButton) {
+ this.nextButton.addEventListener("click", next);
+ }
+ }
+}
+
+// Previous
+class Prev {
+ prevButton: HTMLElement | null;
+ prevTimer: number = 0;
+
+ constructor() {
+ this.prevButton = document.getElementById("prev");
+
+ const prevDebounce = (fn: () => void, delay: number) => {
+ clearTimeout(this.prevTimer);
+ this.prevTimer = setTimeout(() => {
+ fn();
+ }, delay);
+ };
+
+ let prev = () => {
+ let toParameter = getParameters(fromParameter);
+
+ if (fromParameter === 0) {
+ alert("You Have Reached The First Page");
+ } else {
+ let prevAmount = toParameter - fromParameter + 1;
+
+ let intOne = fromParameter - prevAmount;
+
+ if (intOne < 0) {
+ fromParameter = 0;
+ } else {
+ fromParameter = intOne;
+ }
+
+ prevDebounce(getTable, 500);
+ }
+ };
+
+ if (this.prevButton) {
+ this.prevButton.addEventListener("click", prev);
+ }
+ }
+}
+
+// ID Jump
+function idJump() {
+ const input: HTMLInputElement | null = document.querySelector("input");
+ let toParameter = getParameters(fromParameter);
+ let currentID = fromParameter;
+ let search: string;
+ if (input) {
+ search = input.value;
+ } else {
+ return alert("ERROR!!!");
+ }
+ let end = parseInt(search) + getNoOfRows();
+ let maxRecordsID = recordCount - 1;
+
+ if (search !== "" && parseInt(search) <= maxRecordsID && parseInt(search) >= 0) {
+ if (end > maxRecordsID) {
+ toParameter = maxRecordsID;
+ fromParameter = toParameter - getNoOfRows();
+ } else {
+ fromParameter = parseInt(search);
+ toParameter = fromParameter + getNoOfRows();
+ }
+ } else if (search !== "") {
+ alert("Make Sure Your Desired ID Is Not A Negative Number Or Doesn't Exceed 999999");
+ fromParameter = currentID;
+ toParameter = fromParameter + getNoOfRows();
+ input.value = "";
+ }
+
+ getTable();
+}
+
+//// On Window Load
+window.onload = () => {
+ const next = new Next(); // next class
+ const prev = new Prev(); // prev class
+ window.addEventListener("input", debounce(idJump, 500));
+ window.addEventListener("resize", debounce(resizing, 500));
+ getRecordCount()
+ .then(() => {
+ return getHeadings();
+ })
+ .then(() => {
+ return getTable();
+ });
+};
diff --git a/index.html b/index.html
index add5e736..9da857c8 100644
--- a/index.html
+++ b/index.html
@@ -1,13 +1,30 @@
-
+
+
- JS Onboard Project
+
+
+
+ Onboarding JavaScript Task
+
+
- Hello
+
+
+
+
+
+
+
+
+
+
+
+
+
-
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 00000000..57a8346d
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,28 @@
+{
+ "name": "onboard-javascript",
+ "version": "1.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "@types/jquery": {
+ "version": "3.5.14",
+ "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.14.tgz",
+ "integrity": "sha512-X1gtMRMbziVQkErhTQmSe2jFwwENA/Zr+PprCkF63vFq+Yt5PZ4AlKqgmeNlwgn7dhsXEK888eIW2520EpC+xg==",
+ "dev": true,
+ "requires": {
+ "@types/sizzle": "*"
+ }
+ },
+ "@types/sizzle": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz",
+ "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==",
+ "dev": true
+ },
+ "typescript": {
+ "version": "4.6.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz",
+ "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw=="
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 00000000..5f167012
--- /dev/null
+++ b/package.json
@@ -0,0 +1,26 @@
+{
+ "name": "onboard-javascript",
+ "version": "1.0.0",
+ "description": "This is a JavaScript project for all new developers to complete before venturing into our web frontend codebase.",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "build": "tsc --build"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/Koumori97/onboard-javascript.git"
+ },
+ "author": "",
+ "license": "ISC",
+ "bugs": {
+ "url": "https://github.com/Koumori97/onboard-javascript/issues"
+ },
+ "homepage": "https://github.com/Koumori97/onboard-javascript#readme",
+ "dependencies": {
+ "typescript": "^4.6.3"
+ },
+ "devDependencies": {
+ "@types/jquery": "^3.5.14"
+ }
+}
diff --git a/style.css b/style.css
new file mode 100644
index 00000000..64c7b246
--- /dev/null
+++ b/style.css
@@ -0,0 +1,115 @@
+* {
+ padding: 0;
+ margin: 0;
+ box-sizing: border-box;
+ overflow-y: hidden;
+ overflow-x: hidden;
+}
+
+body {
+ height: 100vh;
+}
+
+/* Navigation */
+
+#nav {
+ background-color: #000;
+ display: flex;
+ flex-direction: row;
+ color: #fff;
+ height: 5%;
+ width: 100%;
+}
+
+#pageStats {
+ position: absolute;
+ left: 1%;
+ top: 1%;
+}
+
+#jumpID {
+ position: absolute;
+ left: 50%;
+ top: 1%;
+ transform: translate(-50%, -1%);
+}
+#jumpID input {
+ border: none;
+ margin-right: 20px;
+ padding: 7px 10px;
+ text-align: center;
+}
+
+#btns {
+ position: absolute;
+ right: 1%;
+ top: 1%;
+}
+#btns .next {
+ margin-left: 20px;
+}
+
+button {
+ border: none;
+ padding: 5px 10px;
+ border-radius: 10px;
+ width: 100px;
+ color: #000;
+ background-color: #fff;
+ cursor: pointer;
+ transition: all 0.3s;
+ transition-timing-function: ease-in-out;
+}
+button:hover {
+ letter-spacing: 1px;
+ color: #fff;
+ background-color: #000;
+ border: 1px solid #fff;
+}
+
+/* Headings */
+
+#heading {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ flex-direction: row;
+ width: 100%;
+ height: 10vh;
+}
+#headings {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 100%;
+ width: 100%;
+ font-size: 1em;
+ font-weight: bold;
+ border: 1px solid #000;
+}
+
+/* Table */
+#content {
+ display: flex;
+ flex-direction: column;
+ height: 85vh;
+ width: 100%;
+}
+.rows {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-direction: row;
+ height: 100%;
+ width: 100%;
+}
+.row_cols {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 100%;
+ width: 100%;
+ font-size: 1em;
+ border: 1px solid #000;
+ word-wrap: break-word;
+}