feat(alpha): introduce Computing:Box prototype alpha branding and assets
- Update README to reflect Computing:Box as the evolution of Bit:Box and CS:Box - Replace CS:Box logo references with Computing:Box branding - Add initial Bootstrap Studio design file for prototype layout - Include legacy CS:Box logo assets for reference and transition - Establish baseline assets for Prototype Alpha phase Signed-off-by: Alexander Lyall <alex@adcm.uk>
@@ -45,12 +45,10 @@ All commands are run from the root of the project, from a terminal:
|
|||||||
|
|
||||||
Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).
|
Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).
|
||||||
|
|
||||||
# This project has evolved to become Computing:Box Available at [www.computingbox.co.uk](https://www.computingbox.co.uk) and [www.computingbox.co.uk](https://www.computingbox.co.uk)
|
# Computing:Box
|
||||||
|
An evolution of Bit:Box & CS:Box to incorporate different elements of the UK Computing Curriculum
|
||||||
|
|
||||||
# CS:Box
|

|
||||||
An evolution of Bit:Box to incorporate different elements of the UK Computing Curriculum
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## Upcoming Features
|
## Upcoming Features
|
||||||
### Original Bit:Box Features (October 2024)
|
### Original Bit:Box Features (October 2024)
|
||||||
|
|||||||
BIN
assets/bootstrap/CSBox.bsdesign
Normal file
BIN
assets/img/CSBox-Logo.png
Normal file
|
After Width: | Height: | Size: 388 KiB |
1
assets/img/CSBox-Logo.svg
Normal file
|
After Width: | Height: | Size: 1.8 MiB |
BIN
assets/img/ComputingBox-Logo.png
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
assets/img/computingbox-concept-illustration.png
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
assets/screenshot/csbox-a-level-hexadecimal.jpeg
Normal file
|
After Width: | Height: | Size: 87 KiB |
BIN
assets/screenshot/csbox-and-gate.jpeg
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
assets/screenshot/csbox-gcse-hexadecimal.jpeg
Normal file
|
After Width: | Height: | Size: 73 KiB |
BIN
assets/screenshot/csbox-hex-colours.jpeg
Normal file
|
After Width: | Height: | Size: 124 KiB |
BIN
assets/screenshot/csbox-homepage.jpeg
Normal file
|
After Width: | Height: | Size: 141 KiB |
BIN
assets/screenshot/csbox-nand-gate.jpeg
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
assets/screenshot/csbox-nor-gate.jpeg
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
assets/screenshot/csbox-not-gate.jpeg
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
assets/screenshot/csbox-or-gate.jpeg
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
assets/screenshot/csbox-unsigned-binary.jpeg
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
assets/screenshot/csbox-xnor-gate.jpeg
Normal file
|
After Width: | Height: | Size: 57 KiB |
BIN
assets/screenshot/csbox-xor-gate.jpeg
Normal file
|
After Width: | Height: | Size: 55 KiB |
@@ -1,293 +1,326 @@
|
|||||||
---
|
---
|
||||||
let initialBits = 8;
|
const bitLabels = [128, 64, 32, 16, 8, 4, 2, 1];
|
||||||
---
|
---
|
||||||
|
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||||
<title>Binary | Computing:Box</title>
|
<title>Unsigned Binary | Computing:Box</title>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
:root{
|
:root{
|
||||||
--bg:#1f2027;
|
--bg: #1f2027;
|
||||||
--text:#e8e8ee;
|
--panel: #22242d;
|
||||||
--muted:#a9acb8;
|
--text: #e8e8ee;
|
||||||
--accent:#33ff7a;
|
--muted: #a9acb8;
|
||||||
--accent-dim:rgba(51,255,122,.2);
|
--accent: #33ff7a;
|
||||||
--line:rgba(255,255,255,.12);
|
--accent-dim: rgba(51,255,122,.15);
|
||||||
}
|
--line: rgba(255,255,255,.12);
|
||||||
|
}
|
||||||
|
|
||||||
@font-face{
|
/* DSEG7ClassicRegular font */
|
||||||
font-family:"DSEG7";
|
@font-face{
|
||||||
src:url("/fonts/DSEG7Classic-Regular.woff") format("woff"),
|
font-family: "DSEG7ClassicRegular";
|
||||||
url("/fonts/DSEG7Classic-Regular.ttf") format("truetype");
|
src:
|
||||||
}
|
url("/fonts/DSEG7Classic-Regular.ttf") format("truetype"),
|
||||||
|
url("/fonts/DSEG7Classic-Regular.woff") format("woff");
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
body{
|
body{
|
||||||
margin:0;
|
margin:0;
|
||||||
background:var(--bg);
|
font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
|
||||||
color:var(--text);
|
background: var(--bg);
|
||||||
font-family:system-ui,Segoe UI,Roboto,Arial;
|
color: var(--text);
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrap{
|
.wrap{
|
||||||
max-width:1200px;
|
max-width: 1200px;
|
||||||
margin:auto;
|
margin: 0 auto;
|
||||||
padding:32px 20px 60px;
|
padding: 32px 20px 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top{
|
||||||
|
display:grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: 22px;
|
||||||
|
align-items:start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.readout{
|
||||||
|
background: transparent;
|
||||||
text-align:center;
|
text-align:center;
|
||||||
}
|
padding: 10px 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
.label{
|
.label{
|
||||||
letter-spacing:.18em;
|
letter-spacing: .18em;
|
||||||
color:var(--muted);
|
font-weight: 700;
|
||||||
font-weight:700;
|
color: var(--muted);
|
||||||
}
|
text-transform: uppercase;
|
||||||
|
font-size: 16px;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.num{
|
/* All numbers use DSEG */
|
||||||
font-family:"DSEG7",monospace;
|
.num{
|
||||||
color:var(--accent);
|
font-family: "DSEG7ClassicRegular", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
||||||
text-shadow:0 0 18px var(--accent-dim);
|
font-weight: 400;
|
||||||
}
|
color: var(--accent);
|
||||||
|
text-shadow: 0 0 18px var(--accent-dim);
|
||||||
|
}
|
||||||
|
|
||||||
.den{
|
.value{
|
||||||
font-size:64px;
|
font-size: 64px;
|
||||||
}
|
line-height: 1.0;
|
||||||
|
margin: 6px 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
.bin{
|
.binary{
|
||||||
font-size:44px;
|
font-size: 44px;
|
||||||
letter-spacing:.12em;
|
letter-spacing: .12em;
|
||||||
margin-bottom:12px;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.controls{
|
/* Buttons now UNDER the readout */
|
||||||
|
.controls{
|
||||||
|
margin-top: 16px;
|
||||||
display:flex;
|
display:flex;
|
||||||
gap:10px;
|
gap: 12px;
|
||||||
justify-content:center;
|
justify-content:center;
|
||||||
flex-wrap:wrap;
|
flex-wrap:wrap;
|
||||||
margin:16px 0;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.btn{
|
.btn{
|
||||||
background:rgba(255,255,255,.08);
|
background: rgba(255,255,255,.06);
|
||||||
border:1px solid rgba(255,255,255,.15);
|
border: 1px solid rgba(255,255,255,.14);
|
||||||
color:#fff;
|
color: #fff;
|
||||||
padding:10px 14px;
|
padding: 12px 14px;
|
||||||
border-radius:12px;
|
border-radius: 12px;
|
||||||
cursor:pointer;
|
font-weight: 700;
|
||||||
font-weight:700;
|
cursor: pointer;
|
||||||
}
|
min-width: 160px;
|
||||||
|
}
|
||||||
|
.btn:active{ transform: translateY(1px); }
|
||||||
|
|
||||||
.panel{
|
.bits{
|
||||||
margin-top:20px;
|
margin-top: 34px;
|
||||||
display:flex;
|
padding-top: 26px;
|
||||||
gap:24px;
|
border-top: 1px solid var(--line);
|
||||||
justify-content:center;
|
display:grid;
|
||||||
flex-wrap:wrap;
|
grid-template-columns: repeat(8, 1fr);
|
||||||
}
|
gap: 18px;
|
||||||
|
align-items:end;
|
||||||
|
text-align:center;
|
||||||
|
}
|
||||||
|
|
||||||
.card{
|
.bit{
|
||||||
background:rgba(255,255,255,.04);
|
|
||||||
border:1px solid var(--line);
|
|
||||||
border-radius:14px;
|
|
||||||
padding:14px 16px;
|
|
||||||
min-width:220px;
|
|
||||||
text-align:left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card h4{
|
|
||||||
margin:0 0 8px;
|
|
||||||
font-size:13px;
|
|
||||||
letter-spacing:.14em;
|
|
||||||
color:var(--muted);
|
|
||||||
}
|
|
||||||
|
|
||||||
.bits{
|
|
||||||
margin-top:28px;
|
|
||||||
padding-top:24px;
|
|
||||||
border-top:1px solid var(--line);
|
|
||||||
display:flex;
|
|
||||||
justify-content:center;
|
|
||||||
gap:20px;
|
|
||||||
flex-wrap:wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bit{
|
|
||||||
display:flex;
|
display:flex;
|
||||||
flex-direction:column;
|
flex-direction:column;
|
||||||
align-items:center;
|
align-items:center;
|
||||||
gap:8px;
|
gap: 10px;
|
||||||
}
|
padding: 8px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
/* bulb */
|
.bitVal{
|
||||||
.bulb{
|
font-size: 34px;
|
||||||
width:22px;
|
color: var(--text);
|
||||||
height:22px;
|
opacity: .95;
|
||||||
border-radius:50%;
|
}
|
||||||
background:rgba(255,255,255,.08);
|
|
||||||
border:1px solid rgba(255,255,255,.12);
|
|
||||||
}
|
|
||||||
.bulb.on{
|
|
||||||
background:#ffd86b;
|
|
||||||
box-shadow:0 0 18px rgba(255,216,107,.7);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SAME SWITCH USED EVERYWHERE */
|
/* Bulb */
|
||||||
.switch{
|
.bulb{
|
||||||
position:relative;
|
width: 22px;
|
||||||
width:56px;
|
height: 22px;
|
||||||
height:32px;
|
border-radius: 50%;
|
||||||
}
|
background: rgba(255,255,255,.08);
|
||||||
.switch input{opacity:0;width:0;height:0;}
|
border: 1px solid rgba(255,255,255,.12);
|
||||||
.slider{
|
box-shadow: none;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
.bulb.on{
|
||||||
|
background: #ffd86b;
|
||||||
|
border-color: rgba(255,216,107,.7);
|
||||||
|
box-shadow: 0 0 18px rgba(255,216,107,.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Light switch */
|
||||||
|
.switch{
|
||||||
|
position: relative;
|
||||||
|
width: 56px;
|
||||||
|
height: 34px;
|
||||||
|
display:inline-block;
|
||||||
|
}
|
||||||
|
.switch input{
|
||||||
|
opacity:0;
|
||||||
|
width:0;
|
||||||
|
height:0;
|
||||||
|
}
|
||||||
|
.slider{
|
||||||
position:absolute;
|
position:absolute;
|
||||||
inset:0;
|
inset:0;
|
||||||
background:rgba(255,255,255,.15);
|
background: rgba(255,255,255,.10);
|
||||||
border-radius:999px;
|
border: 1px solid rgba(255,255,255,.14);
|
||||||
transition:.2s;
|
border-radius: 999px;
|
||||||
}
|
transition: .18s ease;
|
||||||
.slider::before{
|
}
|
||||||
|
.slider::before{
|
||||||
content:"";
|
content:"";
|
||||||
position:absolute;
|
position:absolute;
|
||||||
width:26px;
|
height: 28px;
|
||||||
height:26px;
|
width: 28px;
|
||||||
left:3px;
|
left: 3px;
|
||||||
top:3px;
|
top: 2px;
|
||||||
background:white;
|
background: rgba(255,255,255,.92);
|
||||||
border-radius:50%;
|
border-radius: 50%;
|
||||||
transition:.2s;
|
transition: .18s ease;
|
||||||
}
|
}
|
||||||
.switch input:checked + .slider{
|
.switch input:checked + .slider{
|
||||||
background:rgba(51,255,122,.4);
|
background: rgba(51,255,122,.20);
|
||||||
}
|
border-color: rgba(51,255,122,.55);
|
||||||
.switch input:checked + .slider::before{
|
}
|
||||||
transform:translateX(24px);
|
.switch input:checked + .slider::before{
|
||||||
background:var(--accent);
|
transform: translateX(22px);
|
||||||
}
|
background: var(--accent);
|
||||||
</style>
|
}
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
@media (max-width: 900px){
|
||||||
<main class="wrap">
|
.bits{ grid-template-columns: repeat(4, 1fr); }
|
||||||
|
.value{ font-size: 54px; }
|
||||||
|
.binary{ font-size: 36px; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
<div class="label">DENARY</div>
|
<body>
|
||||||
<div id="denary" class="num den">0</div>
|
<main class="wrap">
|
||||||
|
<section class="top">
|
||||||
|
<div class="readout">
|
||||||
|
<div class="label">Denary</div>
|
||||||
|
<div id="denaryNumber" class="value num">0</div>
|
||||||
|
|
||||||
<div class="label">BINARY</div>
|
<div class="label">Binary</div>
|
||||||
<div id="binary" class="num bin">00000000</div>
|
<div id="binaryNumber" class="value binary num">00000000</div>
|
||||||
|
|
||||||
<div class="controls">
|
<!-- Buttons moved HERE (underneath) -->
|
||||||
<button class="btn" id="customBinary">Custom Binary</button>
|
<div class="controls">
|
||||||
<button class="btn" id="customDenary">Custom Denary</button>
|
<button class="btn" id="btnCustomBinary" type="button">Custom Binary</button>
|
||||||
<button class="btn" id="shiftL">Left Shift</button>
|
<button class="btn" id="btnCustomDenary" type="button">Custom Denary</button>
|
||||||
<button class="btn" id="shiftR">Right Shift</button>
|
<button class="btn" id="btnShiftLeft" type="button">Left Shift</button>
|
||||||
</div>
|
<button class="btn" id="btnShiftRight" type="button">Right Shift</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<div class="panel">
|
<section class="bits" aria-label="Bit switches">
|
||||||
<div class="card">
|
{bitLabels.map((v) => (
|
||||||
<h4>MODE</h4>
|
<div class="bit">
|
||||||
Unsigned
|
<div class="bulb" id={`bulb-${v}`} aria-hidden="true"></div>
|
||||||
<label class="switch">
|
|
||||||
<input type="checkbox" id="mode">
|
<!-- bit place value is a number too -->
|
||||||
|
<div class="bitVal num">{v}</div>
|
||||||
|
|
||||||
|
<label class="switch" aria-label={`Toggle bit ${v}`}>
|
||||||
|
<input type="checkbox" data-bit={v} />
|
||||||
<span class="slider"></span>
|
<span class="slider"></span>
|
||||||
</label>
|
</label>
|
||||||
Two’s complement
|
|
||||||
</div>
|
</div>
|
||||||
|
))}
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
<div class="card">
|
<script type="module">
|
||||||
<h4>BIT WIDTH</h4>
|
const bitLabels = [128, 64, 32, 16, 8, 4, 2, 1];
|
||||||
<input id="bitCount" type="number" min="4" max="64" value="8"
|
const bits = new Map(bitLabels.map(v => [v, false]));
|
||||||
style="width:100%;padding:6px;border-radius:8px;border:none;">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<section class="bits" id="bits"></section>
|
function updateReadout(){
|
||||||
|
let denary = 0;
|
||||||
|
let binary = "";
|
||||||
|
|
||||||
</main>
|
for (const v of bitLabels){
|
||||||
|
const on = bits.get(v);
|
||||||
<script type="module">
|
if (on) denary += v;
|
||||||
let bits = 8;
|
binary += on ? "1" : "0";
|
||||||
let twos = false;
|
const bulb = document.getElementById(`bulb-${v}`);
|
||||||
let state = [];
|
if (bulb) bulb.classList.toggle("on", on);
|
||||||
|
|
||||||
const bitsEl = document.getElementById("bits");
|
|
||||||
|
|
||||||
function build(){
|
|
||||||
state = Array(bits).fill(false);
|
|
||||||
bitsEl.innerHTML = "";
|
|
||||||
for(let i=bits-1;i>=0;i--){
|
|
||||||
const val = 2**i;
|
|
||||||
const div = document.createElement("div");
|
|
||||||
div.className="bit";
|
|
||||||
div.innerHTML=`
|
|
||||||
<div class="bulb" id="b${i}"></div>
|
|
||||||
<div class="num">${val}</div>
|
|
||||||
<label class="switch">
|
|
||||||
<input type="checkbox" data-i="${i}">
|
|
||||||
<span class="slider"></span>
|
|
||||||
</label>`;
|
|
||||||
bitsEl.appendChild(div);
|
|
||||||
}
|
}
|
||||||
document.querySelectorAll('[data-i]').forEach(sw=>{
|
|
||||||
sw.onchange=()=>{state[sw.dataset.i]=sw.checked;update();}
|
|
||||||
});
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
function update(){
|
document.getElementById("denaryNumber").innerText = denary.toString();
|
||||||
let n=0;
|
document.getElementById("binaryNumber").innerText = binary;
|
||||||
state.forEach((on,i)=>{
|
}
|
||||||
if(on) n+=2**i;
|
|
||||||
document.getElementById(`b${i}`).classList.toggle("on",on);
|
function setFromBinary(bin){
|
||||||
|
const clean = bin.replace(/\s+/g, "");
|
||||||
|
if (!/^[01]+$/.test(clean)) return false;
|
||||||
|
|
||||||
|
const padded = clean.slice(-8).padStart(8, "0");
|
||||||
|
[...padded].forEach((ch, i) => {
|
||||||
|
const v = bitLabels[i];
|
||||||
|
const on = ch === "1";
|
||||||
|
bits.set(v, on);
|
||||||
|
const input = document.querySelector(`input[data-bit="${v}"]`);
|
||||||
|
if (input) input.checked = on;
|
||||||
});
|
});
|
||||||
|
|
||||||
if(twos && state[bits-1]) n-=2**bits;
|
updateReadout();
|
||||||
|
return true;
|
||||||
document.getElementById("denary").textContent=n;
|
|
||||||
document.getElementById("binary").textContent=
|
|
||||||
state.slice().reverse().map(b=>b?1:0).join("");
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById("mode").onchange=e=>{
|
|
||||||
twos=e.target.checked;
|
|
||||||
update();
|
|
||||||
};
|
|
||||||
|
|
||||||
document.getElementById("bitCount").onchange=e=>{
|
|
||||||
const v=Math.max(4,Math.min(64,Number(e.target.value)));
|
|
||||||
bits=v;
|
|
||||||
build();
|
|
||||||
};
|
|
||||||
|
|
||||||
document.getElementById("shiftL").onclick=()=>{
|
|
||||||
state.shift();state.push(false);update();
|
|
||||||
};
|
|
||||||
document.getElementById("shiftR").onclick=()=>{
|
|
||||||
state.pop();state.unshift(false);update();
|
|
||||||
};
|
|
||||||
|
|
||||||
document.getElementById("customBinary").onclick=()=>{
|
|
||||||
const v=prompt(`Enter ${bits}-bit binary`);
|
|
||||||
if(!v||!/^[01]+$/.test(v))return;
|
|
||||||
const p=v.padStart(bits,"0").slice(-bits);
|
|
||||||
state=p.split("").reverse().map(b=>b==="1");
|
|
||||||
build();
|
|
||||||
};
|
|
||||||
|
|
||||||
document.getElementById("customDenary").onclick=()=>{
|
|
||||||
const max=twos?(2**(bits-1)-1):(2**bits-1);
|
|
||||||
const min=twos?-(2**(bits-1)):0;
|
|
||||||
const n=Number(prompt(`Enter ${min} to ${max}`));
|
|
||||||
if(isNaN(n)||n<min||n>max)return;
|
|
||||||
let val=n<0?n+2**bits:n;
|
|
||||||
state=Array(bits).fill(false);
|
|
||||||
for(let i=0;i<bits;i++){
|
|
||||||
if(val>=2**i){state[i]=true;val-=2**i;}
|
|
||||||
}
|
}
|
||||||
build();
|
|
||||||
};
|
|
||||||
|
|
||||||
build();
|
function setFromDenary(n){
|
||||||
</script>
|
n = Number(n);
|
||||||
</body>
|
if (!Number.isInteger(n) || n < 0 || n > 255) return false;
|
||||||
|
|
||||||
|
for (const v of bitLabels){
|
||||||
|
const on = n >= v;
|
||||||
|
bits.set(v, on);
|
||||||
|
if (on) n -= v;
|
||||||
|
|
||||||
|
const input = document.querySelector(`input[data-bit="${v}"]`);
|
||||||
|
if (input) input.checked = on;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateReadout();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function shiftLeft(){
|
||||||
|
const bin = document.getElementById("binaryNumber").innerText;
|
||||||
|
setFromBinary(bin.slice(1) + "0");
|
||||||
|
}
|
||||||
|
|
||||||
|
function shiftRight(){
|
||||||
|
const bin = document.getElementById("binaryNumber").innerText;
|
||||||
|
setFromBinary("0" + bin.slice(0, -1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// switches
|
||||||
|
document.querySelectorAll('input[type="checkbox"][data-bit]').forEach(input => {
|
||||||
|
input.addEventListener("change", () => {
|
||||||
|
const v = Number(input.dataset.bit);
|
||||||
|
bits.set(v, input.checked);
|
||||||
|
updateReadout();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// buttons
|
||||||
|
document.getElementById("btnShiftLeft").addEventListener("click", shiftLeft);
|
||||||
|
document.getElementById("btnShiftRight").addEventListener("click", shiftRight);
|
||||||
|
|
||||||
|
document.getElementById("btnCustomBinary").addEventListener("click", () => {
|
||||||
|
const val = prompt("Enter an 8-bit binary number (e.g. 01011001):");
|
||||||
|
if (val === null) return;
|
||||||
|
if (!setFromBinary(val)) alert("Invalid input. Use only 0 and 1 (up to 8 digits).");
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById("btnCustomDenary").addEventListener("click", () => {
|
||||||
|
const val = prompt("Enter a denary number (0 to 255):");
|
||||||
|
if (val === null) return;
|
||||||
|
if (!setFromDenary(val)) alert("Invalid input. Enter an integer from 0 to 255.");
|
||||||
|
});
|
||||||
|
|
||||||
|
updateReadout();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||