From 603dff79d6dbefdc7c02b67138c0d69c0e0f6901 Mon Sep 17 00:00:00 2001 From: David Lee Date: Mon, 9 Nov 2020 20:43:02 -0500 Subject: [PATCH 1/2] Frontend loin/logout page of Sneaker Inventory login.js added logout.js added index.html modified for login/logout dropdown menu --- web/index.html | 10 +++++++--- web/js/components/login.js | 32 ++++++++++++++++++++++++++++++++ web/js/components/logout.js | 14 ++++++++++++++ 3 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 web/js/components/login.js create mode 100644 web/js/components/logout.js diff --git a/web/index.html b/web/index.html index 250ca64..d72b59a 100644 --- a/web/index.html +++ b/web/index.html @@ -28,8 +28,8 @@
Account
Register
- Log On
- Log Off + Log In
+ Log out
@@ -46,10 +47,15 @@ + + + + + @@ -59,9 +65,10 @@ myRoutes['#/'] = home; // page reload will run function home myRoutes['#/home'] = home; // function home - myRoutes['#/register'] = register; // function register - myRoutes['#/login'] = login; // function login + myRoutes['#/register'] = registerForm; // function register + myRoutes['#/login'] = loginForm; // function login myRoutes['#/logout'] = logout; // function logout + myRoutes['#/sneakerInventory'] = sneakerInventory; // function sneakerInventory // routeFw returns an object that has private and public diff --git a/web/js/components/loginForm.js b/web/js/components/loginForm.js new file mode 100644 index 0000000..02812a3 --- /dev/null +++ b/web/js/components/loginForm.js @@ -0,0 +1,43 @@ +function loginForm () { + + var accountDiv = document.createElement("div"); + accountDiv.classList.add("account"); + + //create break line element + var br = document.createElement("br"); + + //create a form + var form = document.createElement("form"); + form.setAttribute("method", "post"); + form.setAttribute("action", "submit.php"); + + //create an input element for User ID + var id = document.createElement("input"); + id.setAttribute("type", "text"); + id.setAttribute("name", "id"); + id.setAttribute("placeholder", "User ID"); + id.setAttribute("required","true"); + + //create an input element for Password + var password = document.createElement("input"); + password.setAttribute("type", "password"); + password.setAttribute("name", "password"); + password.setAttribute("placeholder", "Password"); + password.setAttribute("required","true"); + + //create a submit button + var loginButton = document.createElement("input"); + loginButton.setAttribute("type", "submit"); + loginButton.setAttribute("value", "Log in"); + + form.appendChild(id); + form.appendChild(br.cloneNode()); + form.appendChild(password); + form.appendChild(br.cloneNode()); + form.appendChild(loginButton); + + accountDiv.appendChild(form); + + return accountDiv; + +} \ No newline at end of file diff --git a/web/js/components/registerForm.js b/web/js/components/registerForm.js new file mode 100644 index 0000000..348cc71 --- /dev/null +++ b/web/js/components/registerForm.js @@ -0,0 +1,56 @@ +function registerForm () { + + var accountDiv = document.createElement("div"); + accountDiv.classList.add("account"); + + //create break line element + var br = document.createElement("br"); + + //create a form + var form = document.createElement("form"); + form.setAttribute("method", "post"); + form.setAttribute("action", "submit.php"); + + //create an input element for User ID + var id = document.createElement("input"); + id.setAttribute("type", "text"); + id.setAttribute("name", "id"); + id.setAttribute("placeholder", "User ID"); + id.setAttribute("required","true"); + id.setAttribute("maxlength","15"); + + //create an input element for Password + var password = document.createElement("input"); + password.setAttribute("type", "password"); + password.setAttribute("name", "password"); + password.setAttribute("placeholder", "Password"); + password.setAttribute("required","true"); + password.setAttribute("maxlength","15"); + + //create an input element for Confirm Password + var confirmPassword = document.createElement("input"); + confirmPassword.setAttribute("type", "password"); + confirmPassword.setAttribute("name", "confirmPassword"); + confirmPassword.setAttribute("placeholder", "Confirm Password"); + confirmPassword.setAttribute("required","true"); + confirmPassword.setAttribute("maxlength","15"); + + + //create a submit button + var registerButton = document.createElement("input"); + registerButton.setAttribute("type", "submit"); + registerButton.setAttribute("value", "Register"); + + form.appendChild(id); + form.appendChild(br.cloneNode()); + form.appendChild(password); + form.appendChild(br.cloneNode()); + form.appendChild(confirmPassword); + form.appendChild(br.cloneNode()); + form.appendChild(registerButton); + + accountDiv.appendChild(form); + + return accountDiv; + +} \ No newline at end of file diff --git a/web/js/components/sneakerInventory.js b/web/js/components/sneakerInventory.js new file mode 100644 index 0000000..0995abd --- /dev/null +++ b/web/js/components/sneakerInventory.js @@ -0,0 +1,29 @@ +function sneakerInventory() { + var clickSortContainer = document.createElement("div"); + clickSortContainer.classList.add("clickSort"); + ajax("json/inventory.json", processSneakerInventory, clickSortContainer); + + function processSneakerInventory (list) { + + var inventoryList = []; + for (var i=0; i "; + inventoryList[i].currentValue = list[i].currentValue; + inventoryList[i].releaseDate = list[i].releaseDate; + inventoryList[i].webUserId = list[i].webUserId; + } + + var params = { + list: inventoryList, + sortOrderPropName: "sneakerName", + sortIcon: "icon/sortUpDown16.png", + title: "Sneaker Inventory" + } + + var myClickSort = makeClickSort(params); + clickSortContainer.appendChild(myClickSort); + } + return clickSortContainer; +} \ No newline at end of file diff --git a/web/js/reusable/ajax.js b/web/js/reusable/ajax.js new file mode 100644 index 0000000..938dc20 --- /dev/null +++ b/web/js/reusable/ajax.js @@ -0,0 +1,45 @@ +function ajax(url, successCallBackFn, errorEle) { + + var httpReq; + if (window.XMLHttpRequest) { + httpReq = new XMLHttpRequest(); //For Firefox, Safari, Opera + } else if (window.ActiveXObject) { + httpReq = new ActiveXObject("Microsoft.XMLHTTP"); //For IE 5+ + } else { + alert('ajax not supported'); + } + + console.log("ready to get content " + url); + httpReq.open("GET", url); // specify which page you want to get + + + httpReq.onreadystatechange = function () { + //console.log("in ajax, ready state is " + httpReq.readyState); + + if (httpReq.readyState === 4) { // 4 means that the data transfer is complete + console.log("in ajax, status is " + httpReq.status); + + if (httpReq.status === 200) { // 200 means file found (unlike 404 which means not found) + console.log("in ajax, js object printed next"); + + var obj = JSON.parse(httpReq.responseText); + console.log(obj); + + // Here we call back whichever function wanted us to make the AJAX call. + successCallBackFn(obj); + + } else { // error, file not found + + // One input parameter to this ajax function is a DOM element designed to hold any possible error message. + // Populate it with as much information as we know about the error. + errorEle.innerHTML = "Error " + httpReq.status + "-" + httpReq.statusText + + " while attempting to read '" + url + "'"; + } + } + }; // end of anonymous callback function definition + + httpReq.send(null); // initiate ajax call + console.log("call initiated"); + + +} // end function ajax \ No newline at end of file diff --git a/web/js/reusable/makeClickSort.js b/web/js/reusable/makeClickSort.js new file mode 100644 index 0000000..0ffd3f1 --- /dev/null +++ b/web/js/reusable/makeClickSort.js @@ -0,0 +1,329 @@ +function makeClickSort (params) { + + var list = params.list || {}; + var sortIcon = params.sortIcon || {}; + var sortOrderPropName = params.sortOrderPropName || {}; + var title = params.title || {}; + + function jsSort(list, byProperty) { + + + list.sort(// takes in one parameter -- a function that compares two elements in the list... + + function (q, z) { // in line anonymous fn to compare list elements: + // return positive (if first bigger), 0 if equal, negative otherwise. + + var qVal = convert(q[byProperty]); + var zVal = convert(z[byProperty]); + + var c = 0; + if (qVal > zVal) { + c = 1; + } else if (qVal < zVal) { + c = -1; + } + console.log("comparing " + qVal + " to " + zVal + " is " + c); + return c; + } // end of the anonymous comparison function + ); + + // check the string to see what type it is, then return that string converted to the right type + // so as to get the sort order correct. + function convert(s) { + + if (!s || s.length === 0) { + //console.log("s is null or empty string"); + return -1; + } + + // a string that holds a date returns true for isNaN(strDate) (it's not a number) + // And it returns false for isNaN(Date.parse(strDate)) + var parsedDate = Date.parse(s); + if (isNaN(s) && !isNaN(parsedDate)) { + //console.log(s + " is a Date "); + return parsedDate; + } else { + var tmp = s; + console.log("tmp is " + tmp); + tmp = tmp.replace("$", ""); // remove dollar signs + tmp = tmp.replace(",", ""); // remove commas + if (isNaN(tmp)) { // if not a number, return what was passed in + //console.log(s + " is a string - convert to uppercase for sorting purposes"); + return s.toUpperCase(); + } else { + //console.log(tmp + " is a number"); + return Number(tmp); + } + } + } // convert + + } // jsSort + + function jsSortReverse(list, byProperty) { + + + list.sort(// takes in one parameter -- a function that compares two elements in the list... + + function (q, z) { // in line anonymous fn to compare list elements: + + var qVal = convert(q[byProperty]); + var zVal = convert(z[byProperty]); + + var c = 0; + if (qVal < zVal) { + c = 1; + } else if (qVal > zVal) { + c = -1; + } + console.log("comparing " + qVal + " to " + zVal + " is " + c); + return c; + } // end of the anonymous comparison function + ); + + // check the string to see what type it is, then return that string converted to the right type + // so as to get the sort order correct. + function convert(s) { + + if (!s || s.length === 0) { + //console.log("s is null or empty string"); + return -1; + } + + // a string that holds a date returns true for isNaN(strDate) (it's not a number) + // And it returns false for isNaN(Date.parse(strDate)) + var parsedDate = Date.parse(s); + if (isNaN(s) && !isNaN(parsedDate)) { + //console.log(s + " is a Date "); + return parsedDate; + } else { + var tmp = s; + console.log("tmp is " + tmp); + tmp = tmp.replace("$", ""); // remove dollar signs + tmp = tmp.replace(",", ""); // remove commas + if (isNaN(tmp)) { // if not a number, return what was passed in + //console.log(s + " is a string - convert to uppercase for sorting purposes"); + return s.toUpperCase(); + } else { + //console.log(tmp + " is a number"); + return Number(tmp); + } + } + } // convert + + } // jsSort + + function addToRow(eleType, row, data, align) { + var ele = document.createElement(eleType); + ele.innerHTML = data; + ele.style.textAlign = align; + row.appendChild(ele); + return ele; // future code may need a reference to this dom object + } + + function alignment(val) { + + // check if date + var parsedDate = Date.parse(val); + if (isNaN(val) && (!isNaN(parsedDate))) { + return "center"; + } + + // check if image + if (val.includes(".png") || val.includes(".jpg")) { + console.log('is center'); + return "center"; + } + + // check if numeric (remove $ and , and then check if numeric) + var possibleNum = val.replace("$", ""); + possibleNum = possibleNum.replace(",", ""); + if (isNaN(possibleNum)) { + console.log("not a num - left"); + return "left"; + } + + return "right"; // it's a number + + } // alignment + + function prettyColumnHeading(propName) { + + if (propName.length === 0) { + return ""; + } + + // capitalize first letter + var newHdg = propName.charAt(0).toUpperCase(); + // iterate through all characters, inserting space before any capital letters. + for (var i = 1; i < propName.length; i++) { + if (propName.charAt(i) < "a") { + newHdg += " "; + } + newHdg += propName.charAt(i); + } + + return newHdg; + } // prettyColumnHeading + + function addTableHead (table, list) { + + // Create a thead element, place it in table, then + // fill up the thead with td elements that are column headers + // (populated by the field names from the first object in list). + var tableHead = document.createElement("thead"); + table.appendChild(tableHead); + + var tableHeadRow = document.createElement("tr"); + tableHead.appendChild(tableHeadRow); + + // create one column header per property - column header will show the property name. + var obj = list[0]; + for (var prop in obj) { + + console.log("setting the sort onclick for column " + prop); + var iconProp ="" + prettyColumnHeading(prop); + var colHead = addToRow("th", tableHeadRow, iconProp, alignment(obj[prop])); + + // place the property name right into the DOM element that is the "th" + // Because later when the "th" is clicked "prop" will be the last property + // (cause this for loop would have already completed). + colHead.sortPropName = prop; + colHead.onclick = function () { + + console.log("ready to sort by " + this.sortPropName); + + addTableBody(table, list, this.sortPropName); + }; + } + } + + + // sort 'list' by 'sortOrderPropName', remove the tbody from 'table' (if there is one), + // then build a new tbody (from the sorted list) and insert that tbody into the table. + function addTableBody (table, list, sortOrderPropName) { + + // remove old tbody element if there is one (else you'll get sorted rows added to end of what's there). + var oldBody = table.getElementsByTagName("tbody"); + if (oldBody[0]) { + console.log("ready to remove oldBody"); + table.removeChild(oldBody[0]); + } + + if(table.forward){ + + jsSortReverse(list, sortOrderPropName); + table.forward = false; + }else if(!table.forward){ + + jsSort(list, sortOrderPropName); + table.forward = true; + } + + //jsSort(list, sortOrderPropName); + + // Add one row (to HTML table) per element in the array. + // Each array element has a list of properties that will become + // td elements (Table Data, a cell) in the HTML table. + var tableBody = document.createElement("tbody"); + table.appendChild(tableBody); + + for (var i in list) { + var tableRow = document.createElement("tr"); + tableBody.appendChild(tableRow); + + // create one table data content matching the property name + var obj = list[i]; + for (var prop in obj) { + addToRow("td", tableRow, obj[prop], alignment(obj[prop])); + } + } + + } // addTableBody + + // return true if any property of obj contains searchKey. Else return false. + function isToShow(obj, searchKey) { + if (!searchKey || searchKey.length === 0) { + return true; // show the object if searchKey is empty + } + var searchKeyUpper = searchKey.toUpperCase(); + for (var prop in obj) { + var propVal = obj[prop]; // associative array, using property name as if index. + console.log("checking if " + searchKeyUpper + " is in " + propVal); + var propValUpper = propVal.toUpperCase(); + if (propValUpper.includes(searchKeyUpper)) { + + // do not say it's a hit if it's an image tag + // that can have a really long URL in its src attribute. + if (!propValUpper.includes(" content matching the property name + var obj = objList[i]; + for (var prop in obj) { + addToRow("td", tableRow, obj[prop], alignment(obj[prop])); + } + + } else { + console.log("not adding row " + i + " to the HTML table"); + } + } // for loop + + // remove old tbody element if there is one (else you'll get sorted rows added to end of what's there). + var oldBody = table.getElementsByTagName("tbody"); + if (oldBody[0]) { + console.log("ready to remove oldBody"); + table.removeChild(oldBody[0]); + } + table.appendChild(tableBody); + + } // RefreshTableBody + + var returnDiv = document.createElement("div"); + + var h2 = document.createElement("h2"); + h2.innerHTML = title; + returnDiv.appendChild(h2); + var filterTitle = document.createElement("h5"); + h2.appendChild(filterTitle); + var searchInput = document.createElement("input"); + returnDiv.appendChild(searchInput); + + returnDiv.classList.add("clickSort"); + + var newTable = document.createElement("table"); + returnDiv.appendChild(newTable); + + addTableHead (newTable, list); + addTableBody (newTable, list, sortOrderPropName); + + RefreshTableBody(searchInput.value, newTable, list); + + searchInput.onkeyup = function () { + console.log("search filter changed to " + searchInput.value); + RefreshTableBody(searchInput.value, newTable, list); + }; + + // this can be injected into the content area by other code + return returnDiv; +} \ No newline at end of file diff --git a/web/json/inventory.json b/web/json/inventory.json new file mode 100644 index 0000000..101724b --- /dev/null +++ b/web/json/inventory.json @@ -0,0 +1,63 @@ +[ + { + "sneakerName": "Jordan 1 Retro High Zoom White Racer Blue", + "sneakerSku": "CK6637-104", + "image": "pics/Jordan1ZoomRacerBlue.jpg", + "retailPrice": "175.00", + "releaseDate": "2020-03-14", + "currentValue": "489.00", + "quantity": "1", + "webUserId": "1" + }, + { + "sneakerName": "Jordan 1 Retro High Court Purple White", + "sneakerSku": "555088-500", + "image": "pics/Jordan1CourtPurple.jpg", + "retailPrice": "170.00", + "releaseDate": "2020-04-11", + "currentValue": "315.00", + "quantity": "1", + "webUserId": "2" + }, + { + "sneakerName": "Jordan 1 Retro High Royal Toe", + "sneakerSku": "555088-041", + "image": "pics/Jordan1RoyalToe.jpg", + "retailPrice": "170.00", + "releaseDate": "2020-05-09", + "currentValue": "319.00", + "quantity": "1", + "webUserId": "1" + }, + { + "sneakerName": "Jordan 1 Retro High Tie Dye", + "sneakerSku": "CD0461-100", + "image": "pics/Jordan1TieDye.jpg", + "retailPrice": "170.00", + "releaseDate": "2020-06-26", + "currentValue": "279.00", + "quantity": "1", + "webUserId": "4" + }, + { + "sneakerName": "Jordan 1 Retro High Satin Snake Chicago", + "sneakerSku": "CD0461-016", + "image": "pics/Jordan1SatinSnakeChicago.jpg", + "retailPrice": "170.00", + "releaseDate": "2020-08-06", + "currentValue": "283.00", + "quantity": "1", + "webUserId": "1" + }, + { + "sneakerName": "Jordan 1 Retro High Tokyo Bio Hack", + "sneakerSku": "555088-201", + "image": "pics/Jordan1BioHack.jpg", + "retailPrice": "170.00", + "releaseDate": "2020-09-04", + "currentValue": "292.00", + "quantity": "1", + "webUserId": "1" + } + +] \ No newline at end of file diff --git a/web/pics/Jordan1BioHack.jpg b/web/pics/Jordan1BioHack.jpg new file mode 100644 index 0000000000000000000000000000000000000000..eddc2c8217397acfaec523805a18702be43c4a84 GIT binary patch literal 3281 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 L_5WQV$CLjB-T(gd literal 0 HcmV?d00001 diff --git a/web/pics/Jordan1CourtPurple.jpg b/web/pics/Jordan1CourtPurple.jpg new file mode 100644 index 0000000000000000000000000000000000000000..65457c232fa192bbb0fd639862ca14b6664793ee GIT binary patch literal 3467 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 literal 0 HcmV?d00001 diff --git a/web/pics/Jordan1RoyalToe.jpg b/web/pics/Jordan1RoyalToe.jpg new file mode 100644 index 0000000000000000000000000000000000000000..765212c865d625d89f9f388407f1e75c8d91de59 GIT binary patch literal 4710 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 L%>$;8i|_vfd9dNr literal 0 HcmV?d00001 diff --git a/web/pics/Jordan1SatinSnakeChicago.jpg b/web/pics/Jordan1SatinSnakeChicago.jpg new file mode 100644 index 0000000000000000000000000000000000000000..73725377a585756f0c934549960b245226db66ed GIT binary patch literal 6023 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 Crs<*p literal 0 HcmV?d00001 diff --git a/web/pics/Jordan1TieDye.jpg b/web/pics/Jordan1TieDye.jpg new file mode 100644 index 0000000000000000000000000000000000000000..20ecbf920b7782de43e53731a620f801421f0c67 GIT binary patch literal 3828 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 O_3snYzYb7G)Bgo*H5R7; literal 0 HcmV?d00001 diff --git a/web/pics/Jordan1ZoomRacerBlue.jpg b/web/pics/Jordan1ZoomRacerBlue.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5be0351a672bee226d55b7e664451d2161c8a12c GIT binary patch literal 2658 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 tag in any element classed "clickSort" */ + padding: 0.25rem; + background-color: #DDEEEE; + font-size:1rem; +} + +.clickSort th { /* applies to any tag in any element classed "clickSort" */ + padding:0.25rem; + padding-top:0.5rem; + background-color: #AABBCC; + font-weight: bold; + font-size:1.1rem; + white-space: nowrap; /* do not want multi word column headings (or sort icon) to wrap */ +} + +.clickSort tbody img{ + width: 150px; /* auto makes left and right margins the same, means centered */ +} \ No newline at end of file