Fix max capacity check
This commit is contained in:
58
script.js
58
script.js
@@ -1,4 +1,13 @@
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// --- 0. CONSTANTS ---
|
||||
// Limits based on Version 40 (Byte Mode)
|
||||
const MAX_CAPACITY = {
|
||||
'L': 2950,
|
||||
'M': 2328,
|
||||
'Q': 1660,
|
||||
'H': 1270
|
||||
};
|
||||
|
||||
// --- 1. DOM REFERENCES ---
|
||||
const qrContainer = document.getElementById('qr-container');
|
||||
const downloadBtn = document.getElementById('btn-download');
|
||||
@@ -101,20 +110,18 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const blob = new Blob([textData]);
|
||||
const bytes = blob.size;
|
||||
|
||||
// Limits based on Version 40 (Byte Mode)
|
||||
const maxCapacityMap = { 'L': 2950, 'M': 2328, 'Q': 1660, 'H': 1270 };
|
||||
const maxBytes = maxCapacityMap[optEcc.value] || 1270;
|
||||
const maxBytes = MAX_CAPACITY[optEcc.value] || 1270;
|
||||
|
||||
const raw_usage = Math.round((bytes / maxBytes) * 100);
|
||||
const usage = Math.min(100, raw_usage);
|
||||
const rawUsage = Math.round((bytes / maxBytes) * 100);
|
||||
const usage = Math.min(100, rawUsage);
|
||||
|
||||
if (usage > 50) {
|
||||
capMeter.style.display = 'block';
|
||||
capBar.style.width = `${usage}%`;
|
||||
|
||||
capText.textContent = `${usage}% (${bytes} / ${maxBytes} B)`;
|
||||
|
||||
// Update Text Labels
|
||||
if (raw_usage <= 100) {
|
||||
if (bytes <= maxBytes) {
|
||||
capLabel.textContent = 'CAPACITY';
|
||||
} else {
|
||||
capLabel.textContent = 'OVER CAPACITY';
|
||||
@@ -126,8 +133,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
capText.style.color = 'red';
|
||||
capLabel.style.color = 'red';
|
||||
} else {
|
||||
// Normal Level: Remove inline styles.
|
||||
// This lets CSS var(--text-color) take over (Black in Light, White in Dark)
|
||||
// Normal Level: Let CSS variables handle it (Black/White)
|
||||
capBar.style.backgroundColor = '';
|
||||
capText.style.color = '';
|
||||
capLabel.style.color = '';
|
||||
@@ -165,7 +171,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
// 4. Handle Empty State
|
||||
if (!textData || textData.trim() === '') {
|
||||
// Only clear if we are the latest render
|
||||
if (mySeq === renderSeq) {
|
||||
qrContainer.innerHTML = '';
|
||||
downloadBtn.disabled = true;
|
||||
@@ -193,14 +198,13 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const modules = instance._oQRCode.modules;
|
||||
const svgString = generateSVGString(modules, size, colorDark, colorLight);
|
||||
|
||||
// SVG is instant, but check sequence just in case
|
||||
if (mySeq === renderSeq) {
|
||||
qrContainer.innerHTML = svgString;
|
||||
downloadBtn.disabled = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// PNG Mode (Async with Race Condition Protection)
|
||||
// PNG Mode
|
||||
const canvas = tempContainer.querySelector('canvas');
|
||||
if (canvas) {
|
||||
const dataUrl = canvas.toDataURL("image/png");
|
||||
@@ -212,7 +216,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
newImg.style.imageRendering = 'pixelated';
|
||||
newImg.src = dataUrl;
|
||||
|
||||
// Use decode() if available for seamless paint
|
||||
const ready = newImg.decode
|
||||
? newImg.decode()
|
||||
: new Promise((resolve, reject) => {
|
||||
@@ -221,15 +224,11 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
|
||||
ready.then(() => {
|
||||
// [CHECK] If a newer render started while we were decoding, ABORT.
|
||||
if (mySeq !== renderSeq) return;
|
||||
|
||||
qrContainer.replaceChildren(newImg);
|
||||
downloadBtn.disabled = false;
|
||||
}).catch(() => {
|
||||
// Even on error, respect the sequence
|
||||
if (mySeq !== renderSeq) return;
|
||||
// Fallback: Just shove it in
|
||||
qrContainer.replaceChildren(newImg);
|
||||
downloadBtn.disabled = false;
|
||||
});
|
||||
@@ -237,13 +236,12 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
// Error Handling (Sequence Check Not Strictly Needed here but good practice)
|
||||
if (mySeq !== renderSeq) return;
|
||||
|
||||
const blob = new Blob([textData]);
|
||||
const bytes = blob.size;
|
||||
const maxCapacityMap = { 'L': 2953, 'M': 2331, 'Q': 1663, 'H': 1273 };
|
||||
const maxBytes = maxCapacityMap[optEcc.value] || 1273;
|
||||
|
||||
const maxBytes = MAX_CAPACITY[optEcc.value] || 1270;
|
||||
|
||||
if (bytes >= maxBytes) {
|
||||
renderError("CAPACITY EXCEEDED", "REDUCE TEXT OR LOWER ECC LEVEL");
|
||||
@@ -265,16 +263,13 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
}
|
||||
|
||||
// --- 5. RESET LOGIC (Button Only) ---
|
||||
// --- 5. RESET LOGIC ---
|
||||
function resetApp() {
|
||||
// 1. Clear Content Inputs
|
||||
const inputs = document.querySelectorAll('.input-form input, .input-form textarea');
|
||||
inputs.forEach(el => el.value = '');
|
||||
|
||||
// 2. Reset Mode to Text
|
||||
modeSelector.value = 'text';
|
||||
|
||||
// 3. Reset Advanced Configuration to Defaults
|
||||
optEcc.value = 'H';
|
||||
optSize.value = '256';
|
||||
|
||||
@@ -284,25 +279,21 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
optBg.value = '#ffffff';
|
||||
hexBg.textContent = '#FFFFFF';
|
||||
|
||||
// Reset Format Radio to PNG
|
||||
for (const r of fmtRadios) {
|
||||
if (r.value === 'png') r.checked = true;
|
||||
}
|
||||
|
||||
// 4. Update UI Classes (Show Text Form)
|
||||
document.querySelectorAll('.input-form').forEach(f => f.classList.remove('active'));
|
||||
document.getElementById('form-text').classList.add('active');
|
||||
|
||||
// 5. Update Output
|
||||
handleUpdate(true);
|
||||
|
||||
// 6. Focus the first box
|
||||
const firstField = document.querySelector('#form-text textarea');
|
||||
if (firstField) firstField.focus();
|
||||
}
|
||||
|
||||
// --- 6. LISTENERS ---
|
||||
|
||||
// (Listeners remain the same)
|
||||
[optEcc, optSize, optFg, optBg].forEach(el => {
|
||||
el.addEventListener('input', () => handleUpdate(false));
|
||||
});
|
||||
@@ -325,7 +316,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
form.addEventListener('input', () => handleUpdate(false));
|
||||
});
|
||||
|
||||
// Clear Button
|
||||
if (clearBtn) {
|
||||
clearBtn.addEventListener('click', resetApp);
|
||||
}
|
||||
@@ -359,12 +349,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
});
|
||||
|
||||
// --- 7. STARTUP SEQUENCE (Browser Restore Friendly) ---
|
||||
|
||||
// Check what mode the browser remembered
|
||||
// --- 7. STARTUP SEQUENCE ---
|
||||
const initialMode = modeSelector.value;
|
||||
|
||||
// Force the correct form to show based on that mode
|
||||
document.querySelectorAll('.input-form').forEach(f => f.classList.remove('active'));
|
||||
const initialForm = document.getElementById(`form-${initialMode}`);
|
||||
if (initialForm) {
|
||||
@@ -372,7 +358,5 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const startField = initialForm.querySelector('input, textarea');
|
||||
if (startField) startField.focus();
|
||||
}
|
||||
|
||||
// Render whatever data the browser remembered
|
||||
handleUpdate(true);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user