Skip to content

Instantly share code, notes, and snippets.

@batazo
Last active June 8, 2021 20:03
Show Gist options
  • Select an option

  • Save batazo/242a21bc078f624aadf2dbee5cc32149 to your computer and use it in GitHub Desktop.

Select an option

Save batazo/242a21bc078f624aadf2dbee5cc32149 to your computer and use it in GitHub Desktop.
UserSystem-Dashboard (Frontend for UserSystem Backend)
input {
padding: 5px;
background: #30302d14;
outline: none;
font-size: 18px;
border-radius: 8px;
box-shadow: inset 2px 2px 7px -1px grey;
}
button {
outline: none;
}
input:focus {
outline: none;
}
.hidden {
display: none;
}
#container {
border: black 1px solid;
padding: 10px;
border-radius: 6px;
box-shadow: 4px 4px 40px -10px grey;
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Safari */
-khtml-user-select: none; /* Konqueror HTML */
-moz-user-select: none; /* Old versions of Firefox */
-ms-user-select: none; /* Internet Explorer/Edge */
user-select: none; /* Non-prefixed version, currently
supported by Chrome, Edge, Opera and Firefox */
}
#loadingContainer {
text-align: center;
}
.errorBox {
margin-top: 5px;
padding: 3px;
background: #f7c8c8;
width: 97%;
heigth: 20px;
border: red 1px solid;
border-radius: 3px;
color: red;
}
.progressBox {
background: #d6eaf8;
margin-bottom: 10px;
color: blue;
border: blue 1px solid;
padding: 5px;
border-radius: 3px;
}
.successBox {
background: #97ec57;
margin-top: 10px;
color: green;
border: green 1px solid;
padding: 5px;
border-radius: 3px;
}
.conwidth {
width: 97%;
}
.actionbuttons {
padding-top: 15px;
padding-bottom: 15px;
padding-left: 30px;
padding-right: 30px;
font-size: 20px;
background: #0040ffb3;
color: white;
border-radius: 7px;
border: none;
box-shadow: 4px 4px 4px 0px grey;
}
.actionbuttons:active {
transform: translateY(4px);
background: #0040ffdb;
box-shadow: 4px 0px 4px -1px grey;
}
.actionbuttons:focus {
background: grey;
}
.actionbuttons:hover {
background: #0040ffdb;
}
.buttoncontainer {
width: 100%;
text-align: center;
}
.linkbuttons {
padding-top: 15px;
padding-bottom: 15px;
padding-left: 30px;
padding-right: 30px;
font-size: 16px;
background: #ff0000ad;
color: white;
border-radius: 7px;
border: none;
box-shadow: 4px 4px 4px 0px grey;
}
.linkbuttons:active {
transform: translateY(4px);
background: #ff0000cc;
box-shadow: 4px 0px 4px -1px grey;
}
.linkbuttons:hover {
background: #ff0000cc;
}
<html>
<head>
<title>USER DASBOARD</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="dashboard.css">
</head>
<body>
<!-- START -->
<div id="container">
<div id="loadingContainer">
<svg xmlns="http://www.w3.org/2000/svg" width="300" viewBox="0 0 300 300" enable-background="new 0 0 300 300" class="dfm-load">
<style type="text/css">
<![CDATA[
svg.dfm-load .c1,
svg.dfm-load .c2,
svg.dfm-load .c3 {
-webkit-animation: dfmload 1s infinite ease;
animation: dfmload 1s infinite ease;
-webkit-transform-origin: center;
transform-origin: center;
}
svg.dfm-load .c2 {
-webkit-animation-delay: .2s;
animation-delay: .2s;
}
svg.dfm-load .c3 {
-webkit-animation-delay: .4s;
animation-delay: .4s;
}
@-webkit-keyframes dfmload {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
10% {
opacity: .25;
}
50% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
opacity: 1;
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes dfmload {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
10% {
opacity: .25;
}
40% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
opacity: 1;
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
]]>
</style>
<g class="c3">
<path fill="#4d79ff" d="m206.672 101.133c2.957 4.104 2.957 9.339-.695 13.217-2.052 1.357-3.878 2.052-6.14 2.052-2.294 0-5.009-1.131-6.835-2.731-10.244-11.844-25.95-17.984-43.046-17.984-17.305 0-32.801 6.14-42.819 17.984-3.409 3.652-9.129 3.878-12.975.695-4.088-3.878-4.339-9.113-.695-13.217 13.67-15.027 33.949-24.14 56.489-24.14 22.088-.009 43.046 9.096 56.716 24.124z" />
<circle cx="150" cy="150" r="64.886" fill="none" />
</g>
<g class="c2">
<path fill="#4d79ff" d="m149.948 64.235c-24.593 0-46.455 9.113-61.514 24.835-3.878 3.878-9.784 4.104-13.201.452-3.409-3.409-3.409-9.566 0-13.201 18.21-18.905 45.34-29.618 74.716-29.618 29.141 0 56.715 10.697 74.926 29.618 2.957 3.636 2.957 9.792-.444 13.201-2.052 2.052-4.339 2.731-6.617 2.731s-5.001-.695-6.593-3.183c-14.357-15.722-36.898-24.835-61.273-24.835z" />
<circle cx="150" cy="150" r="96.191" fill="none" />
</g>
<g class="c1">
<path fill="#4d79ff" d="m60.658 64.461c-3.636-3.636-3.878-9.339-.226-12.975 20.707-22.783 54.203-35.758 89.509-35.758s67.865 12.991 89.743 35.758c3.636 3.652 3.175 9.339-.452 12.975-1.6 1.6-3.878 2.505-6.156 2.505-2.488 0-4.557-.905-6.609-2.731-18.226-19.358-46.229-30.054-76.517-30.054-30.087 0-58.525 10.697-76.525 30.054-3.202 3.644-9.124 3.644-12.767.226z" />
<circle cx="150" cy="150" r="125" fill="none" />
</g>
</svg>
</div>
<div id="formsDiv" class="hidden">
<form id="loginForm" name="loginForm" action="">
<h2>LOGIN</h2>
<label for="nameField"><strong>Username:</strong></label></br>
<input type="text" id="nameField" class="conwidth" name="nameField" autocomplete="on" required>
<div id="errorBoxName" class="errorBox hidden"></div>
<p>
<label for="passField"><strong>Password</strong> (8 characters minimum):</label></br>
<input type="password" id="passField" class="conwidth" name="passField" autocomplete="on" minlength="8" required>
<div id="errorBoxPass" class="errorBox hidden"></div>
</p>
<p>
<input type="checkbox" id="stayloggedcheck" name="stayloggedcheck">
<label for="stayloggedcheck">I want to stay logged in</label>
</p>
<p>
<div class="buttoncontainer">
<div id="loginProgressBox" class="progressBox hidden">Login in progress ...<img src="https://bzozoo.github.io/UserSystem/public/Frontends/img/load.webp" width=18px /></div>
<input class="actionbuttons" type="button" id="submitButton" name="submitButton" value="LOGIN">
</div>
</p>
<div id="errorBoxCommon" class="errorBox hidden"></div>
</form>
<br>
<hr>
<form id="regForm" name="regForm" autocomplete="off" action="">
<h2>REGISTER</h2>
<label for="regNameField"><strong>Username:</strong></label></br>
<input type="text" id="regNameField" class="conwidth" name="regNameField" autocomplete="new-password" required>
<div id="errorBoxRegName" class="errorBox hidden"></div>
<p>
<label for="regPassField"><strong>Password</strong> (8 characters minimum):</label></br>
<input type="password" id="regPassField" class="conwidth" name="regPassField" autocomplete="new-password" minlength="8" required>
<div id="errorBoxRegPass" class="errorBox hidden"></div>
</p>
<p>
<label for="regConfirmPassField"><strong>Confirm Password</strong> (8 characters minimum):</label></br>
<input type="password" id="regConfirmPassField" class="conwidth" name="regConfirmPassField" autocomplete="new-password" minlength="8" required>
<div id="errorBoxRegConfirmPass" class="errorBox hidden"></div>
</p>
<p>
<div class="buttoncontainer">
<p>* By pressing the registration button, you agree that <u>we will record your IP address</u> for security reasons. </p>
<div id="regProgressBox" class="progressBox hidden">Registration in progress ...<img src="https://bzozoo.github.io/UserSystem/public/Frontends/img/load.webp" width=18px /></div>
<input class="actionbuttons" type="button" id="regSubmitButton" name="regSubmitButton" value="REGISTER">
<div id="regSuccessBox" class="successBox hidden">Registration success! You can Log In! </div>
<div id="errorBoxReg" class="errorBox hidden"></div>
</div>
</p>
</form>
</div>
<div id="profileCOntainer" class="hidden">
<!-- USER NOT LOGGED IN -->
</div>
</div>
<!-- Mobile devtools NOW DISABLED
<script src="//cdn.jsdelivr.net/npm/eruda"></script>
<script>eruda.init();</script>
-->
<!-- STOP -->
<script src="dashboard.js"></script>
</body>
</html>
let version = 'v23-dev';
console.log(version)
//API Endpoints
const loginEndpoint = "https://usersystem.mysqhost.tk/api/login";
const regEndpoint = "https://usersystem.mysqhost.tk/api/register";
const memberEndpointJWT = "https://usersystem.mysqhost.tk/api/user";
const memberEndpointSes = "https://usersystem.mysqhost.tk/api/userprofile";
const userScoreEndpoint = "https://usersystem.mysqhost.tk/api/userscore";
//constanes and variables
const errorBoxes = document.querySelectorAll(".errorBox");
const successBoxes = document.querySelectorAll(".successBox");
const regSuccessBox = document.querySelector("#regSuccessBox");
const inputBoxes = document.querySelectorAll("#container input");
const defaultAvatar = 'https://raw.githubusercontent.com/bzozoo/UserSystem/main/public/Frontends/img/avatar.png';
let storedConnectionResponse;
let storedLoginDatas; //Used in: loginProcess()
let storedRegisterDatas; //Used in: registerProcess()
let getAutHeader;
let identifier;
let loadCounter = 0;
///INITIALIZATION
init();
function init() {
checkIdentifiers()
if (checkUserCookiesExist()) {
userLoggedIn();
} else {
userLogOut();
}
}
///INITIALIZATION END
// Connections
//Main connection
async function connection(url, options) {
const response = await fetch(url, options);
storedConnectionResponse = response
console.log('Actual response.status changed to ', storedConnectionResponse.status)
let getAutHeaderAll = response.headers.get("authorization");
getAutHeader = getAutHeaderAll
? getAutHeaderAll.slice(7, getAutHeaderAll.length)
: false;
let responsedjson = await response.json();
return responsedjson;
}
async function connectForLogin() {
var formData = new FormData();
formData.append("nameField", nameField.value);
formData.append("passField", passField.value);
let options = {
method: "POST",
credentials: "include",
mode: "cors",
body: formData
};
return await connection(loginEndpoint, options);
}
async function connectForRegister() {
var formData = new FormData();
formData.append("reguser", regNameField.value);
formData.append("regpwd", regPassField.value);
let options = {
method: "POST",
credentials: "include",
mode: "cors",
body: formData
};
return await connection(regEndpoint, options);
}
async function connectForUserDatas() {
checkIdentifiers()
let postKEY = (identifier.Mode === 'UTOK')? 'jwtKEY' : 'sessid'
let endpointForMember = (identifier.Mode === 'UTOK')? memberEndpointJWT : memberEndpointSes
console.log('Identifier methods :')
console.log(identifier.Type, postKEY, endpointForMember)
let formData = new FormData();
formData.append(postKEY, identifier.Value);
let options = {
method: "POST",
body: formData,
credentials: "include",
mode: "cors",
cache: "no-cache"
};
return await connection(endpointForMember, options);
}
// Connections END
//PROCESSES
async function loginProcess() {
let checkedLoginDatas = checkLoginInputDatas();
if (checkedLoginDatas) {
submitButton.disabled = true;
loginProgressBox.classList.remove("hidden");
try {
storedLoginDatas = await connectForLogin();
} catch (error) {
console.error("Catch error" + error);
storedLoginDatas = false;
submitButton.disabled = false;
loginProgressBox.classList.add("hidden");
errorBoxCommon.innerHTML = "Server connection error";
errorBoxCommon.classList.remove("hidden");
}
console.log(storedLoginDatas);
if (storedLoginDatas) {
console.log("We got login datas..");
submitButton.disabled = false;
loginProgressBox.classList.add("hidden");
if (storedLoginDatas.Login === "Failed" || storedConnectionResponse.status === 401) {
console.log("Login failed");
showLoginFail();
}
if (storedLoginDatas.Login === "Success" || storedConnectionResponse.status === 200) {
console.log("Login Success");
createUserCookies();
removeAllMessages()
init();
}
}
}
}
async function registerProcess() {
console.log("Register process function...");
let checkRegData = checkRegInputDatas();
if (checkRegData) {
console.log("Register input datas are okey...");
regSubmitButton.disabled = true;
regProgressBox.classList.remove("hidden");
try {
storedRegisterDatas = await connectForRegister();
} catch (error) {
console.error("Catch error" + error);
regSubmitButton.disabled = false;
storedRegisterDatas = false;
regProgressBox.classList.add("hidden");
errorBoxReg.innerHTML = "Server connection error";
errorBoxReg.classList.remove("hidden");
}
if (storedRegisterDatas) {
console.log("We got reg responses: ");
console.log(storedRegisterDatas)
regSubmitButton.disabled = false;
regProgressBox.classList.add("hidden");
regFormMessages(storedRegisterDatas);
}
}
}
//PROCESSES END
// CHECKERS
//Login input checker and error message render. Used in: registerProcess()
function checkLoginInputDatas() {
if (nameField.value === "") {
errorBoxName.innerHTML = "Name is empty";
errorBoxName.classList.remove("hidden");
}
if (passField.value === "") {
errorBoxPass.innerHTML = "Password is empty";
errorBoxPass.classList.remove("hidden");
}
if (passField.value.length < 8) {
errorBoxPass.innerHTML = "The password must be 8 characters long ";
errorBoxPass.classList.remove("hidden");
}
if(passField.value != "" && nameField.value != "" && passField.value.length >= 8){
return true;
}
}
function checkRegInputDatas() {
if (regPassField.value.length < 8) {
errorBoxRegPass.innerHTML = "The register password must be 8 characters long";
errorBoxRegPass.classList.remove("hidden");
}
if (regPassField.value != regConfirmPassField.value) {
errorBoxRegConfirmPass.innerHTML = "The passwords do not match ";
errorBoxRegConfirmPass.classList.remove("hidden");
}
if (regNameField.value === "") {
errorBoxRegName.innerHTML = "Name field is empty";
errorBoxRegName.classList.remove("hidden");
}
if (regPassField.value === "") {
errorBoxRegPass.innerHTML = "Password field is empty";
errorBoxRegPass.classList.remove("hidden");
}
if (regConfirmPassField.value === "") {
errorBoxRegConfirmPass.innerHTML = "Confirm Password field is empty";
errorBoxRegConfirmPass.classList.remove("hidden");
}
if (
regPassField.value === regConfirmPassField.value &&
regNameField.value != "" &&
regPassField.value != "" &&
regPassField.value.length >= 8
) {
return true;
}
}
function checkUserCookiesExist() {
if (((document.cookie.indexOf("una=") === -1 || getCookie('una') === undefined) && sessionStorage.getItem('una') === null && localStorage.getItem('una') === null) ||
!checkIdentifiers()
) {
return false;
} else {
console.log("User cookies exist.");
return true;
}
}
//Check and set identifier
function checkIdentifiers(){
identifier = false
if(document.cookie.indexOf("UTOK=") >= 10 || getCookie('UTOK') != undefined){
identifier = {'Type':'Cookie', 'Mode':'UTOK', 'Value': getCookie('UTOK')}
} else if((localStorage.getItem("UTOK") != null)){
identifier = {'Type':'localStorage', 'Mode':'UTOK', 'Value': localStorage.getItem("UTOK")}
} else if((sessionStorage.getItem("UTOK") != null)){
identifier = {'Type':'sessionStorage', 'Mode':'UTOK', 'Value': sessionStorage.getItem("UTOK")}
} else if(document.cookie.indexOf("ses=") >= 10 || getCookie('ses') != undefined){
identifier = {'Type':'Cookie', 'Mode':'ses', 'Value': getCookie('ses')}
} else if((localStorage.getItem("ses") != null)){
identifier = {'Type':'localStorage', 'Mode':'ses', 'Value': localStorage.getItem("ses")}
} else if((sessionStorage.getItem("ses") != null)){
identifier = {'Type':'sessionStorage', 'Mode':'ses', 'Value': sessionStorage.getItem("ses")}
}
return identifier
}
// CHECKERS END
//RENDER helpers
//Used in: userLoggedIn(), init()
function userLogOut() {
console.log(identifier)
profileCOntainer.classList.add("hidden");
loadingContainer.classList.add("hidden");
profileCOntainer.innerHTML = "";
deleteUserCookies();
formsDiv.classList.remove("hidden");
if(loadCounter != 1){console.log("User logged out ...")}
}
//Used in: loginProcess(), init()
async function userLoggedIn() {
let profile = await connectForUserDatas();
console.log("User Profile Datas : ");
console.log(profile);
if (profile.User === "DoesnotExist" && profile.UserName === "Failed") {
errorBoxCommon.innerHTML = "User session expired! Login again";
errorBoxCommon.classList.remove("hidden");
profile = false;
userLogOut();
return;
}
if (profile) {
formsDiv.classList.add("hidden");
loadingContainer.classList.add("hidden");
regSuccessBox.classList.add("hidden");
profileCOntainer.innerHTML = `
<h1>WELCOME HERE <red style="color: red"><b> ${profile.UserName} </b></red> !</h1>
<p><img src="${(profile.UserAvatar != null || profile.UserAvatar === 'undefined')?profile.UserAvatar:defaultAvatar}" title="${profile.UserName}'s avatar" alt="avatar" width="250" height="250"/></p>
<p><b>Registed At :</b> ${profile.UserRegistredAt.replace(/-/g, ". ").splice(12, '.')}</p><!-- Splice helper!! -->
<p><b>Logined At :</b> ${new Date(profile.CreatedTimeStamp * 1000).toLocaleString()}</p>
<p><b>Login will be expired At :</b> ${new Date(profile.ExpiredTimeStamp * 1000).toLocaleString()}</p>
<p><b>User Score :</b> ${profile.UserScore}</p>
<p><a target="_blank" href="https://codepen.io/bzozoo/full/VwmKOVj">
<button class="linkbuttons">SCORE TABLE</button></a></p>
<p><div class="buttoncontainer">
<input class="actionbuttons" id="logoutButton" name="logoutButton" type="button" value="LOGOUT" onclick="userLogOut()">
</div>
</p>`;
profileCOntainer.classList.remove("hidden");
console.log('Profile Container was generated')
}
}
function showLoginFail() {
errorBoxCommon.innerHTML = "Wrong username or password";
errorBoxCommon.classList.remove("hidden");
}
function removeAllMessages() {
errorBoxes.forEach(function (errorBox) {
errorBox.innerHTML = "";
errorBox.classList.add("hidden");
});
successBoxes.forEach(function (successBox) {
successBox.classList.add("hidden");
});
console.log('All error messages was deleted')
}
//Userd in: registerProcess()
function regFormMessages(storedRegDatas){
if(storedRegDatas){
if(storedConnectionResponse.status === 409 || storedRegDatas.Registration === "Failed"){
let userexistMessage = (storedRegDatas.UserExisted === "YES")? 'User already exist!' : 'Something wrong!';
let regErrorMessage = 'Registration failed!'
errorBoxReg.innerHTML = userexistMessage + ' ' + regErrorMessage
errorBoxReg.classList.remove("hidden");
regProgressBox.classList.add("hidden");
regSuccessBox.classList.add("hidden");
}
if (storedConnectionResponse.status === 201 && storedRegDatas.UserExisted === "NO" && storedRegDatas.Registration === "Success"){
console.log("Registration success!");
regSuccessBox.innerHTML = 'Registration Success! You can login!'
errorBoxReg.classList.add("hidden");
regSuccessBox.classList.remove("hidden");
regProgressBox.classList.add("hidden");
}
}
}
//RENDER helpers END
//Cookie handlers
function createUserCookies() {
let stayloggedcheck = document.querySelector("#stayloggedcheck");
var now = new Date();
var time = now.getTime();
var expireTime = time + 30 * 24 * 60 * 60 *1000;
now.setTime(expireTime);
let expiration = stayloggedcheck.checked
? `expires=${now.toUTCString()};`
: "";
console.log(`Cookie expirations : ${expiration}`);
//Create cookies
document.cookie = `una=${storedLoginDatas.UserName}; ${expiration} path=/; SameSite=None; Secure`;
document.cookie = `UTOK=${storedLoginDatas.UTOK}; ${expiration} path=/; SameSite=None; Secure`;
document.cookie = `ses=${storedLoginDatas.SessionId}; ${expiration} path=/; SameSite=None; Secure`;
if(stayloggedcheck.checked){
document.cookie = `sescrea=${time}; ${expiration} path=/; SameSite=None; Secure`;
document.cookie = `sesexp=${expiration}; ${expiration} path=/; SameSite=None; Secure`;
}
//Save to sessionStorage
if(!stayloggedcheck.checked){
sessionStorage.setItem('una', storedLoginDatas.UserName)
sessionStorage.setItem('UTOK', storedLoginDatas.UTOK)
sessionStorage.setItem('ses', storedLoginDatas.SessionId)
sessionStorage.setItem('ses-exp', expireTime)
}
//Save to localStorage
if(stayloggedcheck.checked){
localStorage.setItem('una', storedLoginDatas.UserName)
localStorage.setItem('UTOK', storedLoginDatas.UTOK)
localStorage.setItem('ses', storedLoginDatas.SessionId)
localStorage.setItem('ses-crea', time)
localStorage.setItem('ses-exp', expireTime)
}
}
//Used in: userLogOut()
function deleteUserCookies() {
//Cookies
document.cookie = `PHPSESSID=deleted; path=/; expires=Thu, 01 Jan 1970 00:00:01 GMT; SameSite=None; Secure`;
document.cookie = `una=deleted; path=/; expires=Thu, 01 Jan 1970 00:00:01 GMT; SameSite=None; Secure`;
document.cookie = `UTOK=deleted; path=/; expires=Thu, 01 Jan 1970 00:00:01 GMT; SameSite=None; Secure`;
document.cookie = `ses=deleted; path=/; expires=Thu, 01 Jan 1970 00:00:01 GMT; SameSite=None; Secure`;
//sessionStorage-s
sessionStorage.removeItem('una')
sessionStorage.removeItem('UTOK')
sessionStorage.removeItem('ses')
//localStorage -s
localStorage.removeItem('una')
localStorage.removeItem('UTOK')
localStorage.removeItem('ses')
localStorage.removeItem('ses-crea')
localStorage.removeItem('ses-exp')
//Identifier init
identifier = false
loadCounter += 1
if(loadCounter != 1){console.log('All user cookies was deleted!')}
}
function getCookie(name) {
const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`);
if (parts.length === 2) return parts.pop().split(";").shift();
}
//Cookie handlers END
//GENERAL helpers
// String splice helper
if (String.prototype.splice === undefined) {
/**
* Splices text within a string.
* @param {int} offset The position to insert the text at (before)
* @param {string} text The text to insert
* @param {int} [removeCount=0] An optional number of characters to overwrite
* @returns {string} A modified string containing the spliced text.
*/
String.prototype.splice = function(offset, text, removeCount=0) {
let calculatedOffset = offset < 0 ? this.length + offset : offset;
return this.substring(0, calculatedOffset) +
text + this.substring(calculatedOffset + removeCount);
};
}
function elementChildren(element) {
var childNodes = element.childNodes,
children = [],
i = childNodes.length;
while (i--) {
if (childNodes[i].nodeType == 1) {
children.unshift(childNodes[i]);
}
}
return children;
}
//GENERAL helpers END
// TEST functions
function reqListener() {
console.log(this.responseText);
}
function getMemberX() {
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", reqListener);
oReq.open("GET", memberEndpoint);
oReq.withCredentials = true;
oReq.send();
}
function loadXMLDoc(theURL) {
if (window.XMLHttpRequest) {
// code for IE7+, Firefox, Chrome, Opera, Safari, SeaMonkey
xmlhttp = new XMLHttpRequest();
} else {
// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
alert(xmlhttp.responseText);
}
};
xmlhttp.open("GET", theURL, false);
xmlhttp.send();
}
// TEST functions END
//EVENT listeners
inputBoxes.forEach(function (inputBox) {
inputBox.addEventListener("input", removeAllMessages);
});
submitButton.addEventListener("click", loginProcess);
regSubmitButton.addEventListener("click", registerProcess);
//EVENT listeners END
<html>
<head>
<title>SCDORE TABLE - Fetch API</title>
<style>
#scoreTable {
font-family: arial, sans-serif;
font-size: 20px;
border-collapse: collapse;
width: 100%;
}
#scoreTable td, #scoreTable th {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
#scoreTable tr:nth-child(odd) {
background: #ccffcc;
}
#scoreTable tr:nth-child(even) {
background-color: #e6ffe6;
}
#scoreTable th {
padding-top: 12px;
padding-bottom: 12px;
text-align: left;
background-color: #4CAF50;
color: white;
cursor: pointer;
}
#scoreTable tr:hover {background-color: #ddd;}
</style>
</head>
<body>
<table id="scoreTable">
<tbody>
<!-- Scores -->
<tr>
<th> Name </th>
<th> Score </th>
</tr>
<!-- Js added scores -->
</tbody>
</table>
<script>
const scoreTable = document.querySelector("#scoreTable");
const url = "https://usersystem.mysqhost.tk/api/userscore";
let actualUser = "Bzozoo";
let storedDatas;
let dataByScore;
function init(url){
console.log(`Init script from : ${url}`)
fetch(url, { method: "GET", mode: "cors", cache: "no-cache" })
.then((response) => response.json())
.then((data) => getData(data))
.catch((error) => serverError(error))
}
init(url)
function serverError(error){
console.log(error)
printErrorToHTML(scoreTable.tBodies[0], error)
}
function printErrorToHTML(where, what){
removeErrorRow()
where.innerHTML += `
<tr id="errorRow">
<td> SERVER CONNECTION ERROR </td>
<td> ${what} <br><button onclick="init('${url}')">Please refresh page</button></td>
</tr>`;
}
function removeErrorRow(){
let errorRow = document.querySelector("#errorRow");
if(errorRow){ errorRow.remove()}
}
function getData(data) {
storedDatas = data;
console.log(storedDatas);
dataByScore = storedDatas.slice(0);
dataByScore.sort(function (a, b) {
return b.UserScore - a.UserScore;
});
console.log("Data by Score");
console.log(dataByScore);
printDataToHTML(scoreTable.tBodies[0], dataByScore);
}
function printDataToHTML(where, what) {
removeErrorRow()
what.forEach(function (element) {
where.innerHTML += `
<tr>
<td> ${element.UserName} </td>
<td> ${element.UserScore} </td>
</tr>`;
});
sortTable()
}
function getUserScoreByName(name) {
let z;
storedDatas.forEach(function (element) {
if (element.UserName === name) {
z = element.UserScore;
}
});
return z;
}
function sortTable() {
const getCellValue = (tr, idx) =>
tr.children[idx].innerText || tr.children[idx].textContent;
const comparer = (idx, asc) => (a, b) =>
((v1, v2) =>
v1 !== "" && v2 !== "" && !isNaN(v1) && !isNaN(v2)
? v1 - v2
: v1.toString().localeCompare(v2))(
getCellValue(asc ? a : b, idx),
getCellValue(asc ? b : a, idx)
);
// do the work...
document.querySelectorAll("th").forEach((th) =>
th.addEventListener("click", () => {
const table = th.closest("table");
Array.from(table.querySelectorAll("tr:nth-child(n+2)"))
.sort(
comparer(
Array.from(th.parentNode.children).indexOf(th),
(this.asc = !this.asc)
)
)
.forEach((tr) => table.appendChild(tr));
})
);
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment