visual_test.html 8.78 KiB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>D-SI Units Visual Test & Documentation</title>
<style>
body {
font-family: sans-serif;
margin: 20px;
line-height: 1.6;
}
h1, h2, h3 {
color: #333;
}
table {
border-collapse: collapse;
width: 100%;
margin-bottom: 40px;
}
th, td {
border: 1px solid #ccc;
padding: 8px;
text-align: left;
vertical-align: top;
}
th {
background-color: #eee;
}
pre {
margin: 0;
font-family: monospace;
background: #f8f8f8;
padding: 4px;
}
.dsi-invalid {
color: red;
font-weight: bold;
}
.dsi-error {
color: orange;
}
.dsi-fraction {
display: inline-block;
text-align: center;
vertical-align: middle;
}
.dsi-numerator {
display: block;
border-bottom: 1px solid #000;
padding: 0 2px;
line-height: 1.2;
}
.dsi-denom {
display: block;
padding: 0 2px;
line-height: 1.2;
}
.dsi-root {
display: inline-flex;
align-items: flex-start;
}
.dsi-root-symbol {
font-size: 1.2em;
padding-right: 2px;
}
.dsi-root-content {
border-top: 1px solid #000;
display: inline-block;
padding-top: 2px;
}
.dsi-mul {
padding: 0 2px;
}
.dsi-unit-wrapper {}
#documentation {
margin-bottom: 40px;
padding: 10px;
border: 1px solid #ccc;
background-color: #fafafa;
}
.doc-table {
margin-bottom: 20px;
}
.doc-table th {
background-color: #ddd;
}
/* Styles for our custom auto-complete input */
dsi-unit-input {
display: block;
margin-bottom: 40px;
}
.autocomplete-item.selected {
background-color: #bde4ff;
}
</style>
</head>
<body>
<h1>D-SI Units Visual Test & Documentation</h1>
<div id="documentation">
<h2>How D-SI Units Are Composed</h2>
<p>
D-SI units are represented as strings where each component is preceded by a backslash (<code>\</code>).
A basic D-SI unit string is composed of:
</p>
<ul>
<li>An <strong>optional prefix</strong> (e.g. <code>\kilo</code> for 10³, <code>\milli</code> for 10⁻³),</li>
<li>A <strong>base unit</strong> (e.g. <code>\metre</code>, <code>\second</code>),</li>
<li>An optional exponent specified with <code>\tothe{...}</code> (e.g. <code>\metre\tothe{2}</code> for square metre),
with fractional exponents like 0.5, 0.333333, or 0.25 rendered as square, cube, or fourth roots respectively.</li>
<li>An optional fraction operator <code>\per</code> is used to combine units into a fraction (e.g. <code>\metre\per\second</code> for metres per second).</li>
</ul>
<p>
Use the auto-complete input below to type a D-SI string. After typing a backslash and at least one letter,
suggestions will appear based on the allowed tokens. When the field loses focus, the rendered unit is shown (while
the raw string is preserved for further editing when focused again). External suggestion lists can also be provided.
</p>
</div>
<!-- New auto-complete input component -->
<h2>Interactive D-SI Input</h2>
<dsi-unit-input suggestions-list="kilo,mega,milli,metre,second,per,tothe"></dsi-unit-input>
<h2>Allowed Prefixes</h2>
<table id="prefixes-table" class="doc-table">
<thead>
<tr>
<th>Prefix Name</th>
<th>Symbol</th>
</tr>
</thead>
<tbody></tbody>
</table>
<h2>Allowed Units</h2>
<table id="units-table" class="doc-table">
<thead>
<tr>
<th>Unit Name</th>
<th>Symbol</th>
</tr>
</thead>
<tbody></tbody>
</table>
<h2>Example D-SI Strings</h2>
<h3>Valid D-SI Strings</h3>
<table id="valid-table">
<thead>
<tr>
<th>Raw D-SI String</th>
<th>Rendered Output</th>
</tr>
</thead>
<tbody></tbody>
</table>
<h3>Invalid D-SI Strings</h3>
<table id="invalid-table">
<thead>
<tr>
<th>Raw D-SI String</th>
<th>Rendered Output</th>
<th>Warnings</th>
</tr>
</thead>
<tbody></tbody>
</table>
<!-- Existing interactive section (button controlled) -->
<h2>Interactive Renderer (Button Controlled)</h2>
<div id="interactiveSection">
<label for="dsiInput">Enter D-SI string:</label>
<input type="text" id="dsiInput" placeholder="e.g. \metre\tothe{0.333333}">
<button id="renderBtn">Render</button>
<div id="interactiveResult"></div>
</div>
<script type="module">
import { dsiPrefixesHTML, dsiUnitsHTML } from "../src/unitStrings.js";
import { DSIUnit } from "../src/dsiUnit.js";
import "../src/dsiUnitInput.js";
// Populate Allowed Prefixes table.
const prefixesTbody = document.getElementById('prefixes-table').querySelector('tbody');
Object.keys(dsiPrefixesHTML).sort().forEach(prefix => {
const tr = document.createElement('tr');
const tdName = document.createElement('td');
tdName.textContent = prefix;
const tdSymbol = document.createElement('td');
tdSymbol.textContent = dsiPrefixesHTML[prefix];
tr.appendChild(tdName);
tr.appendChild(tdSymbol);
prefixesTbody.appendChild(tr);
});
// Populate Allowed Units table.
const unitsTbody = document.getElementById('units-table').querySelector('tbody');
Object.keys(dsiUnitsHTML).sort().forEach(unit => {
const tr = document.createElement('tr');
const tdName = document.createElement('td');
tdName.textContent = unit;
const tdSymbol = document.createElement('td');
tdSymbol.textContent = dsiUnitsHTML[unit];
tr.appendChild(tdName);
tr.appendChild(tdSymbol);
unitsTbody.appendChild(tr);
});
// Example D-SI strings.
const validDSI = [
'\\metre',
'\\metre\\tothe{2}',
'\\metre\\tothe{0.5}',
'\\mega\\metre\\per\\second\\tothe{2}',
'\\kilo\\metre\\per\\hour',
'\\metre\\per\\second',
'\\metre\\tothe{0.333333}', // Cube root
'\\metre\\tothe{0.25}' // Fourth root
];
const invalidDSI = [
'\\foo',
'\\milli\\tothe{2}',
'\\metre\\per',
'\\\\metre\\per\\second'
];
function renderDSI(rawStr) {
try {
const dsi = new DSIUnit(rawStr);
return {
html: dsi.toHTML(),
warnings: dsi.warnings
};
} catch (error) {
return {
html: `<span style="color:red;">Error: ${error.message}</span>`,
warnings: [error.message]
};
}
}
function populateTable(tableId, dsiStrings) {
const tbody = document.getElementById(tableId).querySelector('tbody');
dsiStrings.forEach(rawStr => {
const result = renderDSI(rawStr);
const tr = document.createElement('tr');
const tdRaw = document.createElement('td');
tdRaw.innerHTML = `<pre>${rawStr}</pre>`;
tr.appendChild(tdRaw);
const tdRendered = document.createElement('td');
tdRendered.innerHTML = result.html;
tr.appendChild(tdRendered);
if (tableId === 'invalid-table') {
const tdWarnings = document.createElement('td');
tdWarnings.innerHTML = result.warnings.join('<br>');
tr.appendChild(tdWarnings);
}
tbody.appendChild(tr);
});
}
populateTable('valid-table', validDSI);
populateTable('invalid-table', invalidDSI);
// Button-controlled interactive section.
const renderBtn = document.getElementById('renderBtn');
renderBtn.addEventListener('click', () => {
const inputStr = document.getElementById('dsiInput').value;
try {
const unit = new DSIUnit(inputStr);
const renderedHTML = unit.toHTML();
let warningsHTML = "";
if (unit.warnings.length > 0) {
warningsHTML = `<div id="warningText">Warnings: ${unit.warnings.join("; ")}</div>`;
}
document.getElementById('interactiveResult').innerHTML = renderedHTML + warningsHTML;
} catch (err) {
document.getElementById('interactiveResult').innerHTML = `<span style="color:red;">Error: ${err.message}</span>`;
}
});
</script>
</body>
</html>