OCR-Viewer (#1)

Co-authored-by: nathan <nathan.kehler@gmail.com>
Reviewed-on: #1
This commit is contained in:
2026-05-19 22:03:28 +00:00
parent 727f4fcc57
commit 330b703539
104 changed files with 144649 additions and 2 deletions

View File

@@ -0,0 +1,187 @@
PART 1 — HTML (p44-ocr-viewer.html)
Remove the Edit button:
html<button id="btn-edit" class="tb-btn" title="Toggle edit mode">Edit</button>
Remove the correction dot (no longer needed without edit mode state):
html<div id="correction-dot" title="This page has been edited"></div>
Remove #text-output div — the textarea replaces it permanently:
html<div id="text-output" style="display:none;"></div>
The #editor-wrap should now be visible by default — remove style="display:none;" from it:
html<div id="editor-wrap">
<div id="line-numbers"></div>
<textarea id="text-editor" aria-label="OCR text editor" wrap="soft"></textarea>
</div>
PART 2 — CSS (p44-ocr-viewer.css)
Remove rules for:
#correction-dot
#text-output
#text-output.done-readonly
#btn-edit
Ensure #editor-wrap fills the panel body — update its rule to:
css#editor-wrap {
display: flex;
flex: 1;
min-height: 0;
overflow: hidden;
}
Ensure #text-panel-body is always a flex column:
css#text-panel-body {
display: flex;
flex-direction: column;
flex: 1;
min-height: 0;
overflow: hidden;
}
PART 3 — JS (p44-ocr-viewer.js)
3a — Remove DOM refs
Remove:
javascriptconst btnEdit = document.getElementById('btn-edit');
const correctionDot = document.getElementById('correction-dot');
const textOutput = document.getElementById('text-output');
Remove from state object:
javascripteditMode: false,
3b — Remove enterEditMode() and exitEditMode() entirely
Delete both functions completely.
3c — Remove btnEdit event listener
javascriptbtnEdit.addEventListener('click', () => {
if (state.editMode) exitEditMode();
else enterEditMode();
});
3d — Replace showOCRPage(pageNum)
Replace the entire function body with:
javascriptfunction showOCRPage(pageNum) {
textEditor.dataset.page = pageNum;
if (!Object.keys(state.ocrPages).length) {
textEditor.value = '';
ocrSyncLabel.textContent = '';
return;
}
const content = state.ocrPages[pageNum];
if (!content) {
textEditor.value = 'No OCR text for page ' + pageNum + '.';
ocrSyncLabel.textContent = 'page ' + pageNum + ' — no data';
updateLineNumbers();
return;
}
const corr = state.corrections && state.corrections[pageNum];
const editText = corr
? (currentRole === 'pass2'
? (corr.pass2 || corr.pass1 || corr.original || content)
: (corr.pass1 || corr.original || content))
: content;
textEditor.value = editText;
textEditor.scrollTop = 0;
ocrSyncLabel.textContent = 'page ' + pageNum;
updateLineNumbers();
updateFlagButtons(pageNum);
updateCorrectionIndicator(pageNum);
// Snapshot original on first visit
if (!state.corrections[pageNum] || !state.corrections[pageNum].original) {
if (!state.corrections[pageNum]) state.corrections[pageNum] = {};
state.corrections[pageNum].original = content.trim();
}
// Pass 1 done-page lock
const doneBanner = document.getElementById('done-banner');
const isDonePage = currentRole === 'pass1' && state.flags[pageNum] === 'done';
if (isDonePage) {
textEditor.readOnly = true;
textEditor.style.opacity = '0.55';
doneBanner.innerHTML = '✓ <strong>Done</strong> — submitted to Pass 2 queue. This page is locked.';
doneBanner.style.display = 'flex';
} else {
textEditor.readOnly = false;
textEditor.style.opacity = '';
doneBanner.style.display = 'none';
}
if (currentRole === 'pass2') {
updatePass2NavButtons();
if (state.ocrOverlay) showOCROverlay(pageNum);
showPass2RevertBar(pageNum);
}
}
3e — Replace saveCurrentPage()
This function replaces the save logic that was inside exitEditMode(). Add it as a new function:
javascriptfunction saveCurrentPage() {
const pageNum = parseInt(textEditor.dataset.page, 10);
if (!pageNum) return;
const editedText = textEditor.value.trim();
const passKey = currentRole === 'pass2' ? 'pass2' : 'pass1';
const originalText = (state.corrections[pageNum] && state.corrections[pageNum].original)
|| (state.ocrPages[pageNum] || '').trim();
if (!state.corrections[pageNum]) state.corrections[pageNum] = {};
state.corrections[pageNum].original = state.corrections[pageNum].original || originalText;
if (editedText && editedText !== originalText) {
state.corrections[pageNum][passKey] = editedText;
} else {
delete state.corrections[pageNum][passKey];
}
if (!state.corrections[pageNum].pass1 && !state.corrections[pageNum].pass2) {
delete state.corrections[pageNum];
}
postCorrection(pageNum, state.corrections[pageNum] || null);
updateCorrectionIndicator(pageNum);
}
3f — Update goToPage()
Replace:
javascriptfunction goToPage(n) {
if (state.editMode) exitEditMode();
if (state.ocrOverlay) showOCROverlay(n);
...
}
With:
javascriptfunction goToPage(n) {
saveCurrentPage();
if (state.ocrOverlay) showOCROverlay(n);
...
}
3g — Update updateCorrectionIndicator()
This function currently shows/hides correctionDot. Replace its entire body with:
javascriptfunction updateCorrectionIndicator(pageNum) {
const corr = state.corrections && state.corrections[pageNum];
const hasEdit = corr && (corr.pass1 || corr.pass2);
ocrSyncLabel.style.color = hasEdit ? 'var(--gold)' : 'var(--gold-dim)';
}
3h — Update updateFlagButtons(pageNum)
Remove all references to btnEdit — specifically remove:
javascript btnEdit.disabled = isDone;
btnEdit.style.opacity = isDone ? '0.35' : '';
3i — Keyboard handler
Remove from the keydown handler:
javascript if (state.editMode) return;
Replace with — skip shortcuts only when typing in the page number input:
javascript const tag = document.activeElement && document.activeElement.tagName;
if (tag === 'INPUT' && document.activeElement.id === 'page-input') return;
if (tag === 'TEXTAREA') return;
Remove from the keydown handler:
javascript case 'Escape':
if (state.editMode) { exitEditMode(); }
break;
3j — Remove showPass2ChangeSummary()
This was called from enterEditMode() which no longer exists. Remove the call if it appears anywhere else. The function itself can stay for now as it does no harm, but it should not be called automatically.
VERIFICATION CHECKLIST:
Page loads in Pass 1: textarea immediately visible and editable, no Edit button
Page loads in Pass 2: textarea immediately visible and editable, no Edit button
Typing in textarea and navigating away: changes saved automatically via saveCurrentPage()
Pass 1 Done page: textarea is readOnly, visually dimmed, done banner shows
Pass 1 Done page: navigating away and back still shows locked state
Line numbers update as user types
OCR toggle (Pass 2): left panel shows original OCR, right panel textarea unaffected
No references to state.editMode, enterEditMode, exitEditMode, btnEdit anywhere in the file
Revert bar still works in Pass 2 — reverts load text into textarea directly