You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
365 lines
16 KiB
365 lines
16 KiB
<!doctype html>
|
|
<html>
|
|
<head>
|
|
<title>Orna Tools - atr0phy.net</title>
|
|
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" contents="width=device-width, initial-scale=1">
|
|
|
|
<!-- <link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}"> -->
|
|
|
|
<!-- UIkit CSS -->
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/uikit@3.2.4/dist/css/uikit.min.css" />
|
|
|
|
<!-- UIkit JS -->
|
|
<script src="https://cdn.jsdelivr.net/npm/uikit@3.2.4/dist/js/uikit.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/uikit@3.2.4/dist/js/uikit-icons.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/combine/npm/tablesort@5.2.0,npm/tablesort@5.2.0/src/sorts/tablesort.number.min.js"></script>
|
|
</head>
|
|
<body>
|
|
<nav class="uk-navbar-container" uk-navbar>
|
|
<div class="uk-navbar-center">
|
|
<a href="" class="uk-navbar-item uk-logo">Orna Tools - Equipment Combinations</a>
|
|
</div>
|
|
</nav>
|
|
<div class="uk-container">
|
|
<div id="help-container" class="uk-padding-large uk-text-center uk-text-muted uk-margin-large-left uk-margin-large-right">
|
|
<div>Use the three tabs to input your options for each equipment slot (head/chest/leg). Click the calculate button to populate a table with possible combinations. Click on the column headers to sort results.<br/><br/><strong>Ctrl+Enter</strong> adds a new row to existing table, or use the green <strong>+</strong> to input additional items.</div>
|
|
</div>
|
|
<div id="equipment-container" class="uk-padding-large">
|
|
<ul class="uk-flex-center" uk-tab>
|
|
<li class="uk-active" tbl="head-table"><a href="">Head</a></li>
|
|
<li tbl="chest-table"><a href="">Chest</a></li>
|
|
<li tbl="leg-table"><a href="">Leg</a></li>
|
|
</ul>
|
|
<ul class="uk-switcher">
|
|
{% for slot in ["Head", "Chest", "Leg"] %}
|
|
<li>
|
|
<div class="uk-padding-large uk-padding-remove-vertical">
|
|
<table id="{{ slot | lower }}-table" class="uk-table">
|
|
<caption>{{ slot }} Gear</caption>
|
|
<thead>
|
|
<tr>
|
|
<th class="uk-table-shrink"></th>
|
|
<th class="uk-table-expand">Item Name</th>
|
|
<th class="uk-table-shrink">Defense</th>
|
|
<th class="uk-table-shrink">Resistance</th>
|
|
<th class="uk-table-shring"></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>1</td>
|
|
<td><input type="text" class="uk-input" autocomplete="off"/></td>
|
|
<td><input type="text" class="uk-input" autocomplete="off"/></td>
|
|
<td><input type="text" class="uk-input" autocomplete="off"/></td>
|
|
<td><a class="uk-icon-button del-row-button" uk-icon="icon:minus-circle;ratio:1"></a></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<div class="uk-text-center">
|
|
<a id="{{ slot | lower }}-button" class="uk-icon-button add-row-button" uk-icon="icon:plus-circle;ratio:2"></a>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
{% endfor %}
|
|
</ul>
|
|
</div>
|
|
<div class="uk-text-center uk-margin-bottom">
|
|
<button id="clear-button" class="uk-button uk-button-danger">Clear</button>
|
|
<button id="calculate-button" class="uk-button uk-button-primary">Calculate</button>
|
|
</div>
|
|
|
|
<div id="results-panel" class="uk-section uk-overflow-auto" hidden>
|
|
<hr class="uk-divider-icon" />
|
|
<table id="results-table" class="uk-table uk-table-divider uk-table-striped uk-table-hover">
|
|
<thead>
|
|
<th data-sort-default>Total</th>
|
|
<th>Defense</th>
|
|
<th>Resistance</th>
|
|
<th class="uk-table-expand" data-sort-method='none'>Head</th>
|
|
<th class="uk-table-expand" data-sort-method='none'>Chest</th>
|
|
<th class="uk-table-expand" data-sort-method='none'>Legs</th>
|
|
</thead>
|
|
<tbody></tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Footer -->
|
|
<footer class="uk-text-center uk-margin-large-top uk-margin-small-bottom">
|
|
© <script>document.write(new Date().getFullYear());</script> by <a href="http://binaryatrocity.name">binaryatrocity</a>
|
|
|
|
|
Created for the <span class="uk-text-success">Legends of Palisma</span> Kingdom
|
|
|
|
|
<a href="http://playorna.com">OrnaRPG</a>
|
|
</footer>
|
|
</div>
|
|
</body>
|
|
<script>
|
|
// Support adding rows to the equipment tables
|
|
function addEquipmentTableRow(findByQuery=false) {
|
|
let input_element = document.createElement("input");
|
|
input_element.className="uk-input";
|
|
input_element.type = "text";
|
|
|
|
// Create the delete button
|
|
let delete_button = document.createElement("a");
|
|
delete_button.className="uk-icon-button del-row-button";
|
|
delete_button.setAttribute("uk-icon", "icon:minus-circle;ratio:1");
|
|
delete_button.addEventListener("click", deleteEquipmentTableRow, false);
|
|
|
|
// If called manually, find specific table, otherwise determine based on event element
|
|
let tbody = findByQuery ? document.querySelector(findByQuery) : this.parentElement.previousElementSibling.children[2];
|
|
let new_row = tbody.insertRow(-1);
|
|
|
|
// Append all of the child cells needed
|
|
new_row.insertCell(0).appendChild(delete_button);
|
|
new_row.insertCell(0).appendChild(input_element.cloneNode());
|
|
new_row.insertCell(0).appendChild(input_element.cloneNode());
|
|
new_row.insertCell(0).appendChild(input_element.cloneNode());
|
|
new_row.insertCell(0).appendChild(document.createTextNode(tbody.children.length))
|
|
|
|
if(findByQuery) {
|
|
// If this was a hotkey, then focus the new field
|
|
new_row.children[1].firstChild.focus();
|
|
}
|
|
}
|
|
|
|
// Support deleting rows from the equipment table
|
|
function deleteEquipmentTableRow() {
|
|
this.parentElement.parentElement.remove();
|
|
}
|
|
|
|
// Process results and display table
|
|
function processEquipmentResults(results) {
|
|
var results_tbody = document.querySelector("table#results-table > tbody");
|
|
for(result of results) {
|
|
let new_row = results_tbody.insertRow(-1);
|
|
|
|
// Append all of the child cells
|
|
new_row.insertCell(0).appendChild(document.createTextNode(result['eq'][2]));
|
|
new_row.insertCell(0).appendChild(document.createTextNode(result['eq'][1]));
|
|
new_row.insertCell(0).appendChild(document.createTextNode(result['eq'][0]));
|
|
new_row.insertCell(0).appendChild(document.createTextNode(result['res']));
|
|
new_row.insertCell(0).appendChild(document.createTextNode(result['def']));
|
|
new_row.insertCell(0).appendChild(document.createTextNode(result['def'] + result['res']));
|
|
}
|
|
|
|
table_sort.refresh();
|
|
document.querySelector("div#results-panel").hidden = false;
|
|
|
|
results_tbody.scrollIntoView();
|
|
}
|
|
|
|
// Send data to backend
|
|
function calculateEquipment() {
|
|
let data = gatherEquipmentData();
|
|
|
|
// Store data in localStorage
|
|
localStorage.setItem('eq_data', JSON.stringify(data));
|
|
|
|
// Clear out existing table rows
|
|
for(let row of document.querySelectorAll("table#results-table > tbody > tr")) {
|
|
row.remove();
|
|
}
|
|
|
|
fetch('/results', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(data)
|
|
}).then((response) => response.json()).then((data) => {
|
|
processEquipmentResults(data);
|
|
}).catch((error) => {
|
|
console.log(error);
|
|
alert("There was a problem...");
|
|
});
|
|
}
|
|
|
|
function gatherEquipmentData() {
|
|
var eq_head = [], eq_chest = [], eq_legs = [];
|
|
|
|
// Gather head gear
|
|
for(let row of document.querySelectorAll("table#head-table > tbody > tr")) {
|
|
eq_head.push([
|
|
row.children[1].firstChild.value,
|
|
parseInt(row.children[2].firstChild.value) || 0,
|
|
parseInt(row.children[3].firstChild.value) || 0
|
|
]);
|
|
}
|
|
|
|
// Gather chest gear
|
|
for(let row of document.querySelectorAll("table#chest-table > tbody > tr")) {
|
|
eq_chest.push([
|
|
row.children[1].firstChild.value,
|
|
parseInt(row.children[2].firstChild.value) || 0,
|
|
parseInt(row.children[3].firstChild.value) || 0
|
|
]);
|
|
}
|
|
|
|
// Gather leg gear
|
|
for(let row of document.querySelectorAll("table#leg-table > tbody > tr")) {
|
|
eq_legs.push([
|
|
row.children[1].firstChild.value,
|
|
parseInt(row.children[2].firstChild.value) || 0,
|
|
parseInt(row.children[3].firstChild.value) || 0
|
|
]);
|
|
}
|
|
|
|
let data = {
|
|
"head": eq_head,
|
|
"chest": eq_chest,
|
|
"legs": eq_legs
|
|
};
|
|
|
|
return data;
|
|
}
|
|
|
|
function clearExistingData() {
|
|
localStorage.clear();
|
|
|
|
// Clear out existing table rows
|
|
for(let row of document.querySelectorAll("table > tbody > tr")) {
|
|
row.remove();
|
|
}
|
|
}
|
|
|
|
function loadExistingData() {
|
|
var data = localStorage.getItem('eq_data');
|
|
|
|
function appendToTable(eq, table_id) {
|
|
let input_element = document.createElement("input");
|
|
input_element.className="uk-input";
|
|
input_element.type = "text";
|
|
input_element.autocomplete = "off";
|
|
|
|
// Create the delete button
|
|
let delete_button = document.createElement("a");
|
|
delete_button.className="uk-icon-button del-row-button";
|
|
delete_button.setAttribute("uk-icon", "icon:minus-circle;ratio:1");
|
|
delete_button.addEventListener("click", deleteEquipmentTableRow, false);
|
|
|
|
let query = "table#" + table_id + " > tbody";
|
|
let tbody = document.querySelector(query);
|
|
let new_row = tbody.insertRow(-1);
|
|
|
|
// Append all of the child cells needed
|
|
new_row.insertCell(0).appendChild(delete_button);
|
|
input_element.value = eq[2];
|
|
new_row.insertCell(0).appendChild(input_element.cloneNode());
|
|
input_element.value = eq[1];
|
|
new_row.insertCell(0).appendChild(input_element.cloneNode());
|
|
input_element.value = eq[0];
|
|
new_row.insertCell(0).appendChild(input_element.cloneNode());
|
|
new_row.insertCell(0).appendChild(document.createTextNode(tbody.children.length))
|
|
}
|
|
|
|
if(data) {
|
|
data = JSON.parse(data);
|
|
|
|
// Remove existing rows from all tables
|
|
clearExistingData();
|
|
|
|
// Populate new rows in all eq tables
|
|
for(let hg of data['head']) {
|
|
appendToTable(hg, "head-table");
|
|
}
|
|
for(let cg of data['chest']) {
|
|
appendToTable(cg, "chest-table");
|
|
}
|
|
for(let lg of data['legs']) {
|
|
appendToTable(lg, "leg-table");
|
|
}
|
|
}
|
|
}
|
|
|
|
function confirmDataCleanse() {
|
|
if(confirm("Are you sure you want to clear all existing data?")) {
|
|
clearExistingData();
|
|
}
|
|
}
|
|
|
|
function listenForHotkeys(e) {
|
|
if(e.ctrlKey && e.which == 13) {
|
|
// Determine the active tab
|
|
let tbl_id = "table#" + document.querySelector(".uk-active").getAttribute("tbl") + " > tbody";
|
|
addEquipmentTableRow(tbl_id);
|
|
}
|
|
}
|
|
|
|
// Add event listeners to our table buttons
|
|
const add_row_buttons = document.querySelectorAll("a.add-row-button");
|
|
for(let button of add_row_buttons) {
|
|
button.addEventListener("click", addEquipmentTableRow, false);
|
|
}
|
|
const del_row_buttons = document.querySelectorAll("a.del-row-button");
|
|
for(let button of del_row_buttons) {
|
|
button.addEventListener("click", deleteEquipmentTableRow, false);
|
|
}
|
|
|
|
// Add event listener to Calculate button, call backend
|
|
document.querySelector("#calculate-button").addEventListener("click", calculateEquipment, false);
|
|
document.querySelector("#clear-button").addEventListener("click", confirmDataCleanse, false);
|
|
|
|
// Enable sorting for our results table
|
|
var table_sort = new Tablesort(document.querySelector("table#results-table"), {descending: true});
|
|
|
|
// Configure keyboard hotkeys
|
|
document.onkeyup = listenForHotkeys;
|
|
|
|
// Load any existing data from LocalStorage
|
|
loadExistingData();
|
|
</script>
|
|
<style type="text/css">
|
|
table:not(#results-table) > tbody > tr > td:first-child {
|
|
color: #999;
|
|
}
|
|
|
|
div > a.add-row-button {
|
|
color: #32d296;
|
|
}
|
|
|
|
table a.del-row-button {
|
|
color: #f0506e;
|
|
}
|
|
|
|
table#results-table > tbody > tr > td:first-child {
|
|
font-weight: bold;
|
|
color: #6c9f12;
|
|
}
|
|
|
|
/* Result Table from Tablesort.css */
|
|
th:not(.no-sort) {
|
|
cursor: pointer;
|
|
}
|
|
|
|
th[role=columnheader]:not(.no-sort):after {
|
|
content: '';
|
|
float: right;
|
|
margin-top: 7px;
|
|
border-width: 0 4px 4px;
|
|
border-style: solid;
|
|
border-color: #404040 transparent;
|
|
visibility: hidden;
|
|
opacity: 0;
|
|
-ms-user-select: none;
|
|
-webkit-user-select: none;
|
|
-moz-user-select: none;
|
|
user-select: none;
|
|
}
|
|
|
|
th[aria-sort=ascending]:not(.no-sort):after {
|
|
border-bottom: none;
|
|
border-width: 4px 4px 0;
|
|
}
|
|
|
|
th[aria-sort]:not(.no-sort):after {
|
|
visibility: visible;
|
|
opacity: 0.4;
|
|
}
|
|
|
|
th[role=columnheader]:not(.no-sort):hover:after {
|
|
visibility: visible;
|
|
opacity: 1;
|
|
}
|
|
</style>
|
|
</html>
|