I am an amatuer at javascript/html/css programing. I developed a java backend and I am in the process of developing a convenient frontend webui for it. I want to display buttons in a tree format. All has been successful accept two things: 1) I cannot get the spacing on my buttons to work. I am trying to attempt even spacing between buttons on each line. 2) I cannot get an element by a property ID even using onload. Inspecting the page shows the element and the ID. Apologies if my code is sloppy.
Image removed because everyone seems to focus on it for the wrong reason.
getTree();
addButtons();
window.onload = function() {
let canvas = document.getElementById("canvas");
let ctx = canvas.getContext('2d');
ctx.beginPath();
canvas_arrow(ctx, document.getElementById("rank1").x,
document.getElementById("rank1").y,
document.getElementById("rank2").x,
document.getElementById("rank2").y);
ctx.strokeStyle = '#ffffff';
ctx.stroke();
};
function addButtons() {
fetch('/api/tree').then(async(response) => {
await response.json().then(result => {
let i = 0;
result.forEach(function(item) {
let section = document.getElementById("rankButtons");
let element = document.createElement("button");
if (i !== item["tier"]) {
section.appendChild(document.createElement("br"));
section.appendChild(document.createElement("br"));
i = item["tier"];
}
element.id = item["rankID"];
element.value = item["rankName"];
element.name = "rankButton";
element.textContent = item["rankName"];
section.appendChild(element);
});
})
}).catch(error => {
console.log(error)
})
}
function canvas_arrow(context, fromX, fromY, toX, toY) {
let headLength = 10; // length of head in pixels
let dx = toX - fromX;
let dy = toY - fromY;
let angle = Math.atan2(dy, dx);
context.moveTo(fromX, fromY);
context.lineTo(toX, toY);
context.lineTo(toX - headLength * Math.cos(angle - Math.PI / 6), toY - headLength * Math.sin(angle - Math.PI / 6));
context.moveTo(toX, toY);
context.lineTo(toX - headLength * Math.cos(angle + Math.PI / 6), toY - headLength * Math.sin(angle + Math.PI / 6));
}
.header img {
float: left;
width: 100px;
height: 100px;
background: #555;
}
body {
color: white;
opacity: 1;
}
table,
th,
td {
border: 2px solid white;
opacity: 1;
margin: auto;
text-align: center;
width: 80%;
table-layout: fixed;
}
td {
white-space: pre;
padding: 5px;
}
button {
background: linear-gradient(to bottom right, #CC0033, #3300CC);
padding: 5px;
-webkit-border-radius: 0px;
-moz-border-radius: 0px;
resize: none;
border: 1px solid #30273a;
box-shadow: 0 0 10px #8d78a5;
border-radius: 15px 15px 15px 15px;
z-index: 2;
position: relative;
}
#content {
margin: 100px auto 0;
width: 750px;
max-width: 80%;
padding: 0 0 40px;
text-align: center;
position: relative;
}
#viewport {
height: 100%;
width: 100%;
position: relative;
}
tree.html
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<details>
<summary style="text-align: center; font-size: 20px">Available Ranks</summary>
<pre v-pre="true" class="prismjs line-numbers" style="text-align: center">
<table id="ranks" class="table table-striped" style="font-size:12px"></table>
</pre>
</details>
<canvas id="canvas" width="400" height="500" style="border:1px solid #000000;">
<div id="content">
<div id="rankButtons"></div>
</div>
Here it is again because the other guy edited it out...
<!DOCTYPE html>
<html lang="en" style="background-color: black">
<head>
<div class="header">
<img src="./RDQ-512-Logo.jpg" alt="logo">
</div>
<meta charset="UTF-8">
<title id="title">Rank Up Tree</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<link rel="stylesheet" href="tree.css">
</head>
<body>
<details>
<summary style="text-align: center; font-size: 20px">Available Ranks</summary>
<pre v-pre="true" class="prismjs line-numbers" style="text-align: center">
<table id="ranks" class="table table-striped" style="font-size:12px"></table>
</pre>
</details>
<canvas id="canvas" width="400" height="500" style="border:1px solid #000000;">
</canvas>
<div id="content">
<div id="rankButtons"></div>
</div>
<script src="tree.js"></script>
</body>
</html>
function addButtons() {
fetch('/api/tree').then(async(response) => {
await response.json().then(result => {
let i = 0;
result.forEach(function(item) {
let section = document.getElementById("rankButtons");
let element = document.createElement("button");
if (i !== item["tier"]) {
section.appendChild(document.createElement("br"));
section.appendChild(document.createElement("br"));
i = item["tier"];
}
element.id = item["rankID"];
element.value = item["rankName"];
element.name = "rankButton";
element.textContent = item["rankName"];
section.appendChild(element);
});
})
return true
}).catch(error => {
console.log(error)
})
}
Async functions are designed to be easy to read.
Surely the top only needs to be:
async function addButtons(){
const response = await fetch('/api/tree');
const result = await response.json();
let i=0;
// ... etc
}
addButtons
anywhereYou say this is your entire front-end code. Well that doesn't call addButtons.
You seem to be trying in your onLoad
to access elements with ID=rank1
etc, which seem to be being created by addButtons
.
Therefore did you want to run addButtons
first?
If so, since addButtons
is asynchronous, you should await
it. (I have added a return true
to the function as a reminder that it will return a promise.)
window.onload = async function() {
await addButtons()
let canvas = document.getElementById("canvas");
let ctx = canvas.getContext('2d');
ctx.beginPath();
canvas_arrow(ctx, document.getElementById("rank1").x,
document.getElementById("rank1").y,
document.getElementById("rank2").x,
document.getElementById("rank2").y);
ctx.strokeStyle = '#ffffff';
ctx.stroke();
};