Skip to content

Commit e637127

Browse files
committed
Updated intro animation
1 parent 3073a17 commit e637127

File tree

1 file changed

+94
-69
lines changed

1 file changed

+94
-69
lines changed

static/index.html

Lines changed: 94 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -835,6 +835,22 @@
835835
cursor: not-allowed;
836836
background: #6c757d !important;
837837
}
838+
839+
.textarea-wrapper {
840+
position: relative;
841+
}
842+
843+
.textarea-watermark {
844+
position: absolute;
845+
top: 12px;
846+
right: 12px;
847+
color: #ccc;
848+
font-size: 0.85em;
849+
pointer-events: none;
850+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
851+
font-style: italic;
852+
z-index: 1;
853+
}
838854
</style>
839855
</head>
840856
<body>
@@ -848,13 +864,16 @@ <h1>Random Number Validator</h1>
848864
<div class="help-text" style="margin-bottom: 8px;">
849865
Positive integers (commas, spaces, or newlines) or base64 • <a href="/static/poor-rng.html" style="color: #9fef00; text-decoration: none; border-bottom: 1px dashed #9fef00;">Generate test data</a>
850866
</div>
851-
<textarea
852-
id="numbers"
853-
name="numbers"
854-
rows="5"
855-
placeholder="Loading..."
856-
required
857-
></textarea>
867+
<div class="textarea-wrapper">
868+
<div id="exampleWatermark" class="textarea-watermark" style="display: none;">example</div>
869+
<textarea
870+
id="numbers"
871+
name="numbers"
872+
rows="5"
873+
placeholder="Loading..."
874+
required
875+
></textarea>
876+
</div>
858877

859878
<div style="display: flex; justify-content: space-between; align-items: center; margin-top: 10px;">
860879
<button type="submit">Validate Numbers</button>
@@ -1581,86 +1600,92 @@ <h1>Random Number Validator</h1>
15811600
updateInputStats();
15821601
validateInputRealtime();
15831602

1584-
// Flip-board animation for textbox
1603+
// Flip-board animation for textbox - all numbers visible, digits stabilize left to right
15851604
function startFlipBoardAnimation() {
15861605
const textarea = document.getElementById('numbers');
1587-
const targetCount = 25; // Generate 25 random 8-bit numbers
1588-
const numbers = [];
1606+
const watermark = document.getElementById('exampleWatermark');
1607+
const targetCount = 15;
1608+
1609+
// Show watermark
1610+
watermark.style.display = 'block';
15891611

1590-
// Generate random 8-bit numbers (0-255)
1612+
// Generate target numbers
1613+
const targetNumbers = [];
15911614
for (let i = 0; i < targetCount; i++) {
1592-
numbers.push(Math.floor(Math.random() * 256));
1615+
targetNumbers.push(Math.floor(Math.random() * 256));
15931616
}
15941617

1595-
let completedNumbers = [];
1596-
let currentIndex = 0;
1597-
1598-
function animateNumber(numberValue, callback) {
1599-
const targetStr = numberValue.toString();
1600-
const numDigits = targetStr.length;
1601-
1602-
// Start fast (15ms), gradually slow to 50ms based on progress
1603-
const baseInterval = Math.min(15 + currentIndex * 1.3, 50);
1604-
const cyclesPerDigit = 6; // How many flips before each digit settles
1605-
1606-
let currentDigitIndex = 0;
1607-
let cycleCount = 0;
1608-
let displayDigits = [];
1618+
// Create display state - array of digit arrays for each number
1619+
const displayState = targetNumbers.map(num => {
1620+
const targetStr = num.toString();
1621+
return targetStr.split('').map(() => Math.floor(Math.random() * 10).toString());
1622+
});
16091623

1610-
// Initialize with random digits
1611-
for (let i = 0; i < numDigits; i++) {
1612-
displayDigits.push(Math.floor(Math.random() * 10).toString());
1624+
// Build a flat list of digit positions in left-to-right order
1625+
const digitPositions = [];
1626+
for (let numIdx = 0; numIdx < targetNumbers.length; numIdx++) {
1627+
for (let digitIdx = 0; digitIdx < displayState[numIdx].length; digitIdx++) {
1628+
digitPositions.push({ numIdx, digitIdx });
16131629
}
1630+
}
16141631

1615-
const intervalId = setInterval(() => {
1616-
if (currentDigitIndex < numDigits) {
1617-
// Cycle all unsettled digits
1618-
for (let i = currentDigitIndex; i < numDigits; i++) {
1619-
displayDigits[i] = Math.floor(Math.random() * 10).toString();
1620-
}
1632+
let settledCount = 0;
1633+
const totalDigits = digitPositions.length;
16211634

1622-
// Update display
1623-
const currentDisplay = displayDigits.join('');
1624-
const fullText = [...completedNumbers, currentDisplay].join(', ');
1625-
textarea.value = fullText;
1635+
// Clear placeholder and show initial random state
1636+
textarea.placeholder = '';
1637+
textarea.value = displayState.map(digits => digits.join('')).join(', ');
1638+
1639+
// Animation loop - settle digits left to right
1640+
let frameCount = 0;
1641+
const intervalId = setInterval(() => {
1642+
// Update all unsettled digits with random values
1643+
for (let i = settledCount; i < digitPositions.length; i++) {
1644+
const { numIdx, digitIdx } = digitPositions[i];
1645+
displayState[numIdx][digitIdx] = Math.floor(Math.random() * 10).toString();
1646+
}
16261647

1627-
cycleCount++;
1648+
// Settle digits slower - about every 2 frames to reach ~2 seconds total
1649+
frameCount++;
1650+
if (frameCount % 2 === 0 && settledCount < totalDigits) {
1651+
const { numIdx, digitIdx } = digitPositions[settledCount];
1652+
const targetStr = targetNumbers[numIdx].toString();
1653+
displayState[numIdx][digitIdx] = targetStr[digitIdx];
1654+
settledCount++;
1655+
}
16281656

1629-
// After enough cycles, settle this digit
1630-
if (cycleCount >= cyclesPerDigit) {
1631-
displayDigits[currentDigitIndex] = targetStr[currentDigitIndex];
1632-
currentDigitIndex++;
1633-
cycleCount = 0;
1634-
}
1635-
} else {
1636-
// All digits settled
1637-
clearInterval(intervalId);
1638-
completedNumbers.push(numberValue);
1639-
textarea.value = completedNumbers.join(', ');
1640-
callback();
1641-
}
1642-
}, baseInterval);
1643-
}
1657+
// Update display
1658+
textarea.value = displayState.map(digits => digits.join('')).join(', ');
16441659

1645-
function animateNext() {
1646-
if (currentIndex >= numbers.length) {
1647-
// Animation complete - update stats
1660+
// Check if complete
1661+
if (settledCount >= totalDigits) {
1662+
clearInterval(intervalId);
16481663
updateInputStats();
1649-
return;
16501664
}
1665+
}, 25); // Run at ~40fps for smooth animation
1666+
}
16511667

1652-
animateNumber(numbers[currentIndex], () => {
1653-
currentIndex++;
1654-
// Shorter pauses as we progress (faster overall)
1655-
const pause = Math.max(30, 150 - currentIndex * 3);
1656-
setTimeout(animateNext, pause);
1657-
});
1668+
// Clear textbox and hide watermark when user clicks in it
1669+
let hasCleared = false;
1670+
document.getElementById('numbers').addEventListener('focus', function() {
1671+
if (!hasCleared) {
1672+
this.value = '';
1673+
const watermark = document.getElementById('exampleWatermark');
1674+
if (watermark) {
1675+
watermark.style.display = 'none';
1676+
}
1677+
hasCleared = true;
1678+
updateInputStats();
16581679
}
1680+
});
16591681

1660-
// Clear placeholder and start animation
1661-
textarea.placeholder = '';
1662-
animateNext();
1663-
}
1682+
// Also hide watermark when user starts typing
1683+
document.getElementById('numbers').addEventListener('input', function() {
1684+
const watermark = document.getElementById('exampleWatermark');
1685+
if (watermark) {
1686+
watermark.style.display = 'none';
1687+
}
1688+
});
16641689

16651690
// Check for pending test data from other pages (e.g., poor-rng generator)
16661691
window.addEventListener('DOMContentLoaded', () => {

0 commit comments

Comments
 (0)