improve styling, sort dices

This commit is contained in:
2025-11-07 22:14:42 +01:00
parent 1919dad1bf
commit 25254b04dd
2 changed files with 299 additions and 36 deletions
+136 -22
View File
@@ -23,6 +23,9 @@ class Dice {
} }
fromText(value) { fromText(value) {
if (!value) {
return;
}
const result = value.match(localeData && localeData['regex'] || dice_regex); const result = value.match(localeData && localeData['regex'] || dice_regex);
if (result) { if (result) {
if (result[1]) { if (result[1]) {
@@ -51,7 +54,7 @@ class DiceHistoryEntry {
} }
const default_sides = [4, 6, 8, 10, 12, 20, 100]; const default_sides = [4, 6, 8, 10, 12, 20, 100];
const default_colors = ["#de324c", "#f4895f", "#f8e16f", "#95cf92", "#369acc", "#9656a2", "#6c584c"]; const default_colors = ["#de324c", "#f4895f", "#d8b400ff", "#95cf92", "#369acc", "#9656a2", "#6c584c"];
const dice_regex = new RegExp("(\\d+)?[D|d](\\d+)([\\+|\\-]\\d+)?(\\[(.+)\\])?"); const dice_regex = new RegExp("(\\d+)?[D|d](\\d+)([\\+|\\-]\\d+)?(\\[(.+)\\])?");
@@ -209,7 +212,6 @@ function renderHistory() {
} }
if (redoHistory.length) { if (redoHistory.length) {
console.log(redoHistory);
document.getElementById('history-redo-button').classList.remove("disabled"); document.getElementById('history-redo-button').classList.remove("disabled");
} else { } else {
document.getElementById('history-redo-button').classList.add("disabled"); document.getElementById('history-redo-button').classList.add("disabled");
@@ -217,13 +219,42 @@ function renderHistory() {
history.forEach((entry) => { history.forEach((entry) => {
if (entry.result) { if (entry.result) {
// Create main history entry container
const historyEntry = document.createElement("div");
historyEntry.classList.add("history-entry");
// Create header section
const entryHeader = document.createElement("div");
entryHeader.classList.add("history-entry-header");
// Create dice label section
const diceLabelContainer = document.createElement("div"); const diceLabelContainer = document.createElement("div");
diceLabelContainer.classList.add("label"); diceLabelContainer.classList.add("label");
if (entry.dices) { if (entry.dices) {
entry.dices.forEach((diceData, i) => { entry.dices.forEach((diceData, i) => {
const dice = new Dice(diceData.sides, diceData.addition, diceData.count, diceData.color); const dice = new Dice(diceData.sides, diceData.addition, diceData.count, diceData.color);
// Add dice icon
const diceIcon = document.createElement("span");
diceIcon.classList.add("dice-icon");
if (default_sides.indexOf(dice.sides) != -1) {
diceIcon.style.maskImage = `url(./assets/dices/${dice.sides}.svg)`;
} else {
diceIcon.style.maskImage = "url(./assets/dices/custom.svg)";
}
diceIcon.style.color = dice.color;
// revert b/w on dark-mode
if (darkMode) {
if (["#000", "#000000", "black", "rgb(0,0,0)", "rgb(0, 0, 0)"].indexOf(dice.color) != -1) {
diceIcon.style.color = "#fff";
} else if (["#fff", "#ffffff", "white", "rgb(255,255,255)", "rgb(255, 255, 255)"].indexOf(dice.color) != -1) {
diceIcon.style.color = "#000";
}
}
diceLabelContainer.appendChild(diceIcon);
const diceLabel = document.createElement("label"); const diceLabel = document.createElement("label");
diceLabel.innerHTML = dice.toText() + (i == entry.dices.length - 1 ? ": " : ""); diceLabel.innerHTML = dice.toText();
diceLabel.style.color = dice.color; diceLabel.style.color = dice.color;
// revert b/w on dark-mode // revert b/w on dark-mode
if (darkMode) { if (darkMode) {
@@ -234,6 +265,7 @@ function renderHistory() {
} }
} }
diceLabelContainer.appendChild(diceLabel); diceLabelContainer.appendChild(diceLabel);
if (i < entry.dices.length - 1) { if (i < entry.dices.length - 1) {
const diceLabelAdd = document.createElement("span"); const diceLabelAdd = document.createElement("span");
diceLabelAdd.innerHTML = "&nbsp;+&nbsp;"; diceLabelAdd.innerHTML = "&nbsp;+&nbsp;";
@@ -241,48 +273,130 @@ function renderHistory() {
} }
}) })
} }
historyContainer.appendChild(diceLabelContainer);
// Create result display
const diceResult = document.createElement("span"); const diceResult = document.createElement("div");
diceResult.classList.add("result"); diceResult.classList.add("result");
diceResult.innerText = entry.result; diceResult.innerText = entry.result;
historyContainer.appendChild(diceResult);
const diceFormulaContainer = document.createElement("span"); entryHeader.appendChild(diceLabelContainer);
diceFormulaContainer.classList.add("formula-container");
historyContainer.appendChild(diceFormulaContainer);
if (entry.formula) { // Only show result in header if there's no formula
const diceFormulaEqual = document.createElement("span"); if (!entry.formula) {
diceFormulaEqual.innerText = " = "; entryHeader.appendChild(diceResult);
diceFormulaContainer.appendChild(diceFormulaEqual);
const diceFormula = document.createElement("span");
diceFormula.classList.add("formula");
diceFormula.innerText = entry.formula;
diceFormulaContainer.appendChild(diceFormula);
} }
const diceTime = document.createElement("span"); // Create time display
const diceTime = document.createElement("div");
diceTime.classList.add("time"); diceTime.classList.add("time");
historyContainer.appendChild(diceTime);
if (entry.time) { if (entry.time) {
entry.time.locale(locale); entry.time.locale(locale);
diceTime.innerText = entry.time.fromNow(); diceTime.innerText = entry.time.fromNow();
diceTime.title = entry.time.format("LLLL"); diceTime.title = entry.time.format("LLLL");
} }
entryHeader.appendChild(diceTime);
historyEntry.appendChild(entryHeader);
// Create details section if formula exists
if (entry.formula) {
const entryDetails = document.createElement("div");
entryDetails.classList.add("history-entry-details");
const diceFormulaContainer = document.createElement("div");
diceFormulaContainer.classList.add("formula-container");
const diceFormulaResult = document.createElement("span");
diceFormulaResult.classList.add("result");
diceFormulaResult.innerText = entry.result;
const diceFormulaEqual = document.createElement("span");
diceFormulaEqual.innerText = " = ";
diceFormulaContainer.appendChild(diceFormulaResult);
diceFormulaContainer.appendChild(diceFormulaEqual);
const diceFormula = document.createElement("span");
diceFormula.classList.add("formula");
// If we have dices, show colored breakdown
if (entry.dices && entry.dices.length >= 1) {
// Parse the formula to show which dice contributed what
const formulaParts = entry.formula.split(" + ");
let partIndex = 0;
// Create a mapping of which dice contributes which parts
let dicePartMapping = [];
entry.dices.forEach(dice => {
for (let i = 0; i < dice.count; i++) {
if (partIndex < formulaParts.length && !isNaN(parseInt(formulaParts[partIndex]))) {
dicePartMapping.push({
partIndex: partIndex,
dice: dice
});
partIndex++;
}
}
});
formulaParts.forEach((part, index) => {
const mapping = dicePartMapping.find(m => m.partIndex === index);
if (mapping) {
// This part comes from a dice roll
const partSpan = document.createElement("span");
partSpan.innerText = part;
partSpan.style.color = mapping.dice.color;
// revert b/w on dark-mode
if (darkMode) {
if (["#000", "#000000", "black", "rgb(0,0,0)", "rgb(0, 0, 0)"].indexOf(mapping.dice.color) != -1) {
partSpan.style.color = "#fff";
} else if (["#fff", "#ffffff", "white", "rgb(255,255,255)", "rgb(255, 255, 255)"].indexOf(mapping.dice.color) != -1) {
partSpan.style.color = "#000";
}
}
diceFormula.appendChild(partSpan);
} else {
// This is an addition value (modifier)
const partSpan = document.createElement("span");
partSpan.innerText = part;
diceFormula.appendChild(partSpan);
}
if (index < formulaParts.length - 1) {
const plusSpan = document.createElement("span");
plusSpan.innerText = " + ";
diceFormula.appendChild(plusSpan);
}
});
} else {
// Fallback to plain text
diceFormula.innerText = entry.formula;
}
diceFormulaContainer.appendChild(diceFormula);
entryDetails.appendChild(diceFormulaContainer);
historyEntry.appendChild(entryDetails);
}
historyContainer.appendChild(historyEntry);
} else { } else {
// Add separator for different roll sessions
historyContainer.appendChild(document.createElement("hr")); historyContainer.appendChild(document.createElement("hr"));
} }
}) })
} }
function formula(dice) { function formula(dice) {
let rolls = [];
for (let index = 0; index < dice.count; index++) {
rolls.push(Math.floor(Math.random() * dice.sides + 1));
}
rolls.sort((a, b) => b - a);
let formula = ""; let formula = "";
for (let index = 0; index < dice.count; index++) { for (let index = 0; index < dice.count; index++) {
formula += Math.floor(Math.random() * dice.sides + 1); formula += rolls[index];
if (index < dice.count - 1) { if (index < dice.count - 1) {
formula += " + "; formula += " + ";
} }
+163 -14
View File
@@ -210,6 +210,9 @@ body {
align-items: center; align-items: center;
row-gap: 1em; row-gap: 1em;
grid-template-columns: auto; grid-template-columns: auto;
width: 100%;
max-width: 100%;
box-sizing: border-box;
} }
.form-container .actions { .form-container .actions {
@@ -261,45 +264,114 @@ body {
} }
.history { .history {
display: grid;
grid-template-columns: repeat(4, auto);
width: 100%; width: 100%;
margin-top: 1.5em; margin-top: 1.5em;
margin-bottom: 0.5em; margin-bottom: 0.5em;
row-gap: 0.3em; display: flex;
column-gap: 0.3em; flex-direction: column;
gap: 0.8em;
} }
.history hr { .history hr {
width: 100%; width: 100%;
grid-column: span 4; margin: 0.5em 0;
border: none;
border-top: 1px solid #ccc;
}
.history-entry {
background: #fff;
border: 0.15em solid #000;
padding: 1em;
transition: all 0.2s ease;
position: relative;
overflow: hidden;
}
.history-entry:hover {
background: #f1f3f4;
}
.history-entry-header {
display: flex;
align-items: flex-start;
margin-bottom: 0.5em;
flex-wrap: wrap;
gap: 0.5em;
}
.history-entry-header .label {
flex: 1;
min-width: 0;
}
.history-entry-header .result {
flex: 0 0 auto;
margin: 0 1em;
}
.history-entry-header .time {
flex: 0 0 auto;
margin-left: auto;
min-width: 8em;
text-align: right;
} }
.history .label { .history .label {
font-size: 1.2em; font-size: 1.1em;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
align-items: center;
gap: 0.3em;
} }
.history .result { .history .result {
text-align: center; font-size: 1.8em;
font-size: 1.2em;
font-weight: bold; font-weight: bold;
color: #2c3e50;
text-align: center;
min-width: 3em;
}
.history .time {
font-size: 0.9em;
color: #6c757d;
text-align: right;
opacity: 0.8;
}
.history-entry-details {
margin-top: 0.5em;
padding-top: 0.5em;
border-top: 0.1em solid #000;
} }
.history .formula-container { .history .formula-container {
display: flex; display: flex;
margin: 0 0.5em; align-items: center;
font-size: 0.95em;
color: #495057;
} }
.history .formula-container .formula { .history .formula-container .formula {
display: flex; margin-left: 0.5em;
margin: 0 0.5em; font-family: 'Courier New', Courier, monospace;
font-size: 1.3em;
background: #f1f3f4;
padding: 0.2em 0.5em;
border: 0.1em solid #000;
} }
.history .time { .dice-icon {
text-align: right; display: inline-block;
width: 1.2em;
height: 1.2em;
background-color: currentColor;
mask-size: contain;
mask-repeat: no-repeat;
mask-position: center;
margin-right: 0.2em;
vertical-align: middle;
} }
button { button {
@@ -366,6 +438,37 @@ body.dark .form select {
border-color: #fff; border-color: #fff;
} }
body.dark .history-entry {
background: #000;
border-color: #fff;
}
body.dark .history .result {
color: #e9ecef;
}
body.dark .history .time {
color: #adb5bd;
}
body.dark .history .formula-container {
color: #adb5bd;
}
body.dark .history .formula-container .formula {
background: #2d3436;
color: #ddd;
border-color: #fff;
}
body.dark .history hr {
border-top-color: #fff;
}
body.dark .history-entry-details {
border-top-color: #fff;
}
@media screen and (max-width: 767px) { @media screen and (max-width: 767px) {
.dices { .dices {
font-size: 0.65em; font-size: 0.65em;
@@ -381,4 +484,50 @@ body.dark .form select {
min-width: auto; min-width: auto;
width: 100%; width: 100%;
} }
.history-entry {
padding: 0.8em;
}
.history-entry-header {
flex-wrap: wrap;
align-items: flex-start;
gap: 0.5em;
}
.history-entry-header .label {
flex: 0 1 auto;
min-width: 0;
}
.history-entry-header .result {
flex: 0 0 auto;
margin: 0;
}
.history-entry-header .time {
flex: 0 0 auto;
min-width: 6em;
margin-left: auto;
text-align: right;
}
.history .result {
font-size: 1.5em;
align-self: center;
}
.history .time {
align-self: center;
font-size: 0.8em;
}
.history .label {
font-size: 1em;
}
.dice-icon {
width: 1em;
height: 1em;
}
} }