510 lines
29 KiB
HTML
510 lines
29 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>{{ document.document_id }}</title>
|
|
<link rel="stylesheet" href="/static/app.css">
|
|
</head>
|
|
<body>
|
|
<div class="app-shell" id="app-shell">
|
|
{% include "partials/sidebar.html" %}
|
|
|
|
<main class="main">
|
|
{% if error == "line_count_mismatch" %}
|
|
<div class="error-box">
|
|
Could not save reviewed OCR because line count did not match OCR layout.
|
|
Expected {{ error_expected }}, got {{ error_actual }}.
|
|
</div>
|
|
{% elif error == "save_ocr_corrected_failed" %}
|
|
<div class="error-box">
|
|
Could not save OCR-corrected PDF. Check that reviewed OCR line count matches raw OCR line count.
|
|
</div>
|
|
{% elif error == "rerun_ocr_failed" %}
|
|
<div class="error-box">OCR rerun failed.</div>
|
|
{% elif error == "save_field_enriched_failed" %}
|
|
<div class="error-box">Could not save field-enriched PDF.</div>
|
|
{% endif %}
|
|
|
|
<div class="detail-sticky-header">
|
|
<div class="topbar">
|
|
<div>
|
|
<h1 class="page-title">{{ document.document_id }}</h1>
|
|
<p class="page-subtitle">{{ document.original_filename or document.canonical_filename or document.document_type }}</p>
|
|
</div>
|
|
<div class="badges">
|
|
<span class="badge {% if document.review_status == 'reviewed' %}reviewed{% else %}pending{% endif %}">{{ document.review_status }}</span>
|
|
<span class="badge">{{ document.document_type }}</span>
|
|
<span class="badge">{{ document.mime_type }}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card" style="margin-bottom: 0;">
|
|
<div class="button-row">
|
|
<form method="post" action="/documents/{{ document.document_id }}/rerun-ocr">
|
|
<button type="submit">Re-run OCR</button>
|
|
</form>
|
|
<form method="post" action="/documents/{{ document.document_id }}/save-ocr-corrected-pdf">
|
|
<button class="primary" type="submit">Save OCR-corrected PDF</button>
|
|
</form>
|
|
<form method="post" action="/documents/{{ document.document_id }}/save-field-enriched-pdf">
|
|
<button type="submit">Save field-enriched PDF</button>
|
|
</form>
|
|
<form method="post" action="/documents/{{ document.document_id }}/move-to-trash">
|
|
<button class="danger" type="submit">Move to trash</button>
|
|
</form>
|
|
</div>
|
|
|
|
<form method="post" action="/documents/{{ document.document_id }}/save-document-type" style="margin-top: 1rem;">
|
|
<div style="display:flex; align-items:flex-end; gap:0.6rem; flex-wrap:wrap;">
|
|
<div style="position:relative;">
|
|
<label for="document_type_input">Document type</label>
|
|
<input
|
|
id="document_type_input"
|
|
type="text"
|
|
name="document_type"
|
|
value="{{ document.document_type or '' }}"
|
|
placeholder="receipt"
|
|
autocomplete="off"
|
|
style="min-width:160px; max-width:260px;"
|
|
>
|
|
<div id="document-type-suggestions" style="display:none; position:absolute; top:100%; left:0; right:0; z-index:20; background:#fff; border:1px solid #d7dce5; border-radius:12px; margin-top:0.35rem; max-height:220px; overflow-y:auto; box-shadow:0 10px 24px rgba(15,23,42,0.10);"></div>
|
|
</div>
|
|
<button type="submit" style="height:38px;">Save</button>
|
|
</div>
|
|
</form>
|
|
|
|
<div class="queue-nav-row">
|
|
{% if prev_doc %}
|
|
<a class="button-link" href="/documents/{{ prev_doc.document_id }}">← Previous</a>
|
|
{% endif %}
|
|
{% if next_doc %}
|
|
<a class="button-link" href="/documents/{{ next_doc.document_id }}">Next →</a>
|
|
{% endif %}
|
|
{% if next_ocr_doc %}
|
|
<a class="button-link" href="/documents/{{ next_ocr_doc.document_id }}">Next OCR review</a>
|
|
{% endif %}
|
|
{% if next_fields_doc %}
|
|
<a class="button-link" href="/documents/{{ next_fields_doc.document_id }}">Next field extraction</a>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="workspace-grid">
|
|
<section>
|
|
<div class="card preview-card">
|
|
<h2 class="card-title">Document preview</h2>
|
|
{% if file_url %}
|
|
{% if document.mime_type == "application/pdf" %}
|
|
<iframe class="preview-frame" src="{{ file_url }}"></iframe>
|
|
{% elif document.mime_type in ["image/jpeg", "image/png"] %}
|
|
<img class="preview-image" src="{{ file_url }}" alt="Document image">
|
|
{% else %}
|
|
<p><a href="{{ file_url }}" target="_blank">Open file</a></p>
|
|
{% endif %}
|
|
{% else %}
|
|
<p class="empty-state">No preview available.</p>
|
|
{% endif %}
|
|
</div>
|
|
</section>
|
|
|
|
<section>
|
|
<div class="card">
|
|
<div class="right-pane-tabs">
|
|
<button class="tab-button{% if active_tab == 'ocr-review' %} active{% endif %}" type="button" data-tab="ocr-review">OCR Review</button>
|
|
<button class="tab-button{% if active_tab == 'extracted-fields' %} active{% endif %}" type="button" data-tab="extracted-fields">Extracted Fields</button>
|
|
<button class="tab-button{% if active_tab == 'additional-fields' %} active{% endif %}" type="button" data-tab="additional-fields">Additional Fields</button>
|
|
<button class="tab-button{% if active_tab == 'versions' %} active{% endif %}" type="button" data-tab="versions">Versions</button>
|
|
<button class="tab-button{% if active_tab == 'raw-ocr' %} active{% endif %}" type="button" data-tab="raw-ocr">Raw OCR</button>
|
|
</div>
|
|
|
|
<div class="tab-panel{% if active_tab == 'ocr-review' %} active{% endif %}" data-panel="ocr-review">
|
|
<h2 class="card-title">Reviewed OCR</h2>
|
|
{% if reviewed_ocr %}
|
|
<p>Current reviewed version saved at {{ reviewed_ocr.created_at }} — v{{ reviewed_ocr.version_number }}</p>
|
|
{% else %}
|
|
<p class="empty-state">No reviewed OCR saved yet.</p>
|
|
{% endif %}
|
|
|
|
<p>
|
|
Expected OCR lines: <span id="expected-lines">{{ expected_line_count }}</span><br>
|
|
Current editor lines: <span id="actual-lines">{{ actual_line_count }}</span><br>
|
|
<span id="line-warning" class="line-warning" {% if expected_line_count == actual_line_count %}style="display:none;"{% endif %}>
|
|
Line count mismatch may affect corrected PDF layout.
|
|
</span>
|
|
</p>
|
|
|
|
<form method="post" action="/documents/{{ document.document_id }}/review-text">
|
|
<div class="form-field full">
|
|
<label for="reviewed_text">Edit reviewed OCR text (one line per OCR line)</label>
|
|
<div class="editor-wrap">
|
|
<pre class="line-numbers" id="line-numbers">{% for n in line_numbers %}{{ n }}
|
|
{% endfor %}</pre>
|
|
<textarea id="reviewed_text" name="reviewed_text" rows="34" spellcheck="false">{{ review_text_value }}</textarea>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-field full">
|
|
<label>Quality flags</label>
|
|
<div>
|
|
{% for flag in quality_flag_options %}
|
|
<label style="display:block; margin-bottom: 0.25rem;">
|
|
<input type="checkbox" name="quality_flags" value="{{ flag }}" {% if flag in current_quality_flags %}checked{% endif %}>
|
|
{{ flag }}
|
|
</label>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-field full">
|
|
<label for="quality_note">Quality note</label>
|
|
<textarea id="quality_note" name="quality_note" rows="4">{{ current_quality_note }}</textarea>
|
|
</div>
|
|
|
|
<div class="button-row">
|
|
<button class="primary" type="submit" id="save-reviewed-btn">Save reviewed OCR</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="tab-panel{% if active_tab == 'extracted-fields' %} active{% endif %}" data-panel="extracted-fields">
|
|
<h2 class="card-title">Extracted fields</h2>
|
|
|
|
{% if current_extracted %}
|
|
<p>Current extracted fields last updated at {{ current_extracted.updated_at }}</p>
|
|
{% else %}
|
|
<p class="empty-state">No extracted fields saved yet.</p>
|
|
{% endif %}
|
|
|
|
<form method="get" action="/documents/{{ document.document_id }}">
|
|
<input type="hidden" name="autofill_extracted" value="1">
|
|
<input type="hidden" name="tab" value="extracted-fields">
|
|
<div class="button-row">
|
|
<button type="submit">Auto-extract fields</button>
|
|
</div>
|
|
</form>
|
|
|
|
<form method="post" action="/documents/{{ document.document_id }}/save-extracted-fields" style="margin-top: 1rem;">
|
|
<div class="form-grid">
|
|
<div class="form-field"><label>Merchant raw</label><input type="text" name="merchant_raw" value="{{ extracted_form.merchant_raw }}"></div>
|
|
<div class="form-field"><label>Merchant normalized</label><input type="text" name="merchant_normalized" value="{{ extracted_form.merchant_normalized }}"></div>
|
|
<div class="form-field"><label>Transaction date</label><input type="date" name="transaction_date" value="{{ extracted_form.transaction_date }}"></div>
|
|
<div class="form-field"><label>Transaction time</label><input type="text" name="transaction_time" value="{{ extracted_form.transaction_time }}"></div>
|
|
<div class="form-field"><label>Subtotal</label><input type="text" name="subtotal" value="{{ extracted_form.subtotal }}"></div>
|
|
<div class="form-field"><label>Tax</label><input type="text" name="tax" value="{{ extracted_form.tax }}"></div>
|
|
<div class="form-field"><label>Total</label><input type="text" name="total" value="{{ extracted_form.total }}"></div>
|
|
<div class="form-field"><label>Currency</label><input type="text" name="currency" value="{{ extracted_form.currency }}"></div>
|
|
<div class="form-field"><label>Payment method</label><input type="text" name="payment_method" value="{{ extracted_form.payment_method }}"></div>
|
|
<div class="form-field"><label>Reference number</label><input type="text" name="receipt_number" value="{{ extracted_form.receipt_number }}"></div>
|
|
<div class="form-field full"><label>Location</label><input type="text" name="location" value="{{ extracted_form.location }}"></div>
|
|
<div class="form-field full"><label>Counterparty</label><input type="text" name="counterparty" value="{{ extracted_form.counterparty }}"></div>
|
|
<div class="form-field full"><label>Extra JSON</label><textarea name="extra_json" rows="8">{{ extracted_form.extra_json }}</textarea></div>
|
|
</div>
|
|
|
|
<div class="button-row" style="margin-top: 1rem;">
|
|
<button class="primary" type="submit">Save extracted fields</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="tab-panel{% if active_tab == 'additional-fields' %} active{% endif %}" data-panel="additional-fields">
|
|
<h2 class="card-title">Additional fields</h2>
|
|
|
|
{% if current_additional %}
|
|
<p>Current additional fields last updated at {{ current_additional.updated_at }}</p>
|
|
{% else %}
|
|
<p class="empty-state">No additional fields saved yet.</p>
|
|
{% endif %}
|
|
|
|
{% if presets %}
|
|
<form method="get" action="/documents/{{ document.document_id }}" style="margin-bottom: 1rem;">
|
|
<input type="hidden" name="tab" value="additional-fields">
|
|
<div class="button-row">
|
|
<select name="preset_id">
|
|
<option value="">Select preset</option>
|
|
{% for preset in presets %}
|
|
<option value="{{ preset.id }}" {% if selected_preset_id == preset.id %}selected{% endif %}>{{ preset.name }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
<button type="submit">Apply preset</button>
|
|
<a class="button-link" href="/presets/">Manage presets</a>
|
|
</div>
|
|
</form>
|
|
{% else %}
|
|
<div class="button-row" style="margin-bottom: 1rem;">
|
|
<a class="button-link" href="/presets/">Create first preset</a>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<form method="post" action="/documents/{{ document.document_id }}/save-additional-fields">
|
|
<div class="form-grid">
|
|
<div class="form-field">
|
|
<label>Primary owner</label>
|
|
<input type="text" name="owner_primary" value="{{ additional_form.owner_primary }}">
|
|
</div>
|
|
<div class="form-field">
|
|
<label>Secondary owner</label>
|
|
<input type="text" name="owner_secondary" value="{{ additional_form.owner_secondary }}">
|
|
</div>
|
|
<div class="form-field">
|
|
<label>Paid by person</label>
|
|
<input type="text" name="paid_by_person" value="{{ additional_form.paid_by_person }}">
|
|
</div>
|
|
<div class="form-field full">
|
|
<label>Covered people</label>
|
|
<input type="text" name="covered_people" value="{{ additional_form.covered_people }}" placeholder="Full Name, Full Name">
|
|
</div>
|
|
<div class="form-field full">
|
|
<label>Attendees</label>
|
|
<input type="text" name="attendees" value="{{ additional_form.attendees }}" placeholder="Full Name, Full Name">
|
|
</div>
|
|
<div class="form-field full">
|
|
<label>Occasion note</label>
|
|
<input type="text" name="occasion_note" value="{{ additional_form.occasion_note }}" placeholder="Dinner with Camie and friends">
|
|
</div>
|
|
<div class="form-field">
|
|
<label><input type="checkbox" name="is_shared_expense" value="1" {% if additional_form.is_shared_expense %}checked{% endif %}> Shared expense</label>
|
|
</div>
|
|
<div class="form-field full">
|
|
<label>Reimbursement expected from</label>
|
|
<input type="text" name="reimbursement_expected_from" value="{{ additional_form.reimbursement_expected_from }}" placeholder="Full Name, Full Name">
|
|
</div>
|
|
<div class="form-field">
|
|
<label>Reimbursement paid by</label>
|
|
<input type="text" name="reimbursement_paid_by" value="{{ additional_form.reimbursement_paid_by }}">
|
|
</div>
|
|
<div class="form-field">
|
|
<label>Reimbursement paid to</label>
|
|
<input type="text" name="reimbursement_paid_to" value="{{ additional_form.reimbursement_paid_to }}">
|
|
</div>
|
|
<div class="form-field">
|
|
<label>Reimbursement paid amount</label>
|
|
<input type="text" name="reimbursement_paid_amount" value="{{ additional_form.reimbursement_paid_amount }}">
|
|
</div>
|
|
<div class="form-field">
|
|
<label>Reimbursement paid date</label>
|
|
<input type="date" name="reimbursement_paid_date" value="{{ additional_form.reimbursement_paid_date }}">
|
|
</div>
|
|
<div class="form-field full">
|
|
<label>Reimbursement note</label>
|
|
<textarea name="reimbursement_note" rows="4">{{ additional_form.reimbursement_note }}</textarea>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="button-row" style="margin-top: 1rem;">
|
|
<button class="primary" type="submit">Save additional fields</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="tab-panel{% if active_tab == 'versions' %} active{% endif %}" data-panel="versions">
|
|
<h2 class="card-title">Document versions</h2>
|
|
{% if document.versions %}
|
|
<div class="table-wrap">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Version</th>
|
|
<th>Type</th>
|
|
<th>Path</th>
|
|
<th>Created</th>
|
|
<th>Notes</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for version in document.versions %}
|
|
<tr>
|
|
<td>v{{ version.version_number }}</td>
|
|
<td>{{ version.version_type }}</td>
|
|
<td>{{ version.file_path }}</td>
|
|
<td>{{ version.created_at }}</td>
|
|
<td>{{ version.notes or "" }}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% else %}
|
|
<p class="empty-state">No versions found.</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div class="tab-panel{% if active_tab == 'raw-ocr' %} active{% endif %}" data-panel="raw-ocr">
|
|
<h2 class="card-title">Raw OCR</h2>
|
|
{% if raw_ocr %}
|
|
<div class="meta-grid">
|
|
<div class="meta-item"><span class="meta-label">Text version</span>v{{ raw_ocr.version_number }}</div>
|
|
<div class="meta-item"><span class="meta-label">OCR engine</span>{{ raw_ocr.ocr_engine or "unknown" }}</div>
|
|
<div class="meta-item"><span class="meta-label">Engine version</span>{{ raw_ocr.ocr_engine_version or "unknown" }}</div>
|
|
<div class="meta-item"><span class="meta-label">Rerun source</span>{{ raw_ocr.rerun_source or "unknown" }}</div>
|
|
<div class="meta-item"><span class="meta-label">Quality score</span>{{ raw_ocr.quality_score if raw_ocr.quality_score is not none else "not scored yet" }}</div>
|
|
<div class="meta-item"><span class="meta-label">Quality note</span>{{ raw_ocr.quality_note or "" }}</div>
|
|
</div>
|
|
<p><strong>Quality flags:</strong> {{ raw_ocr.quality_flags if raw_ocr and raw_ocr.quality_flags else [] }}</p>
|
|
<pre class="codeblock">{{ raw_ocr.text_content }}</pre>
|
|
{% else %}
|
|
<p class="empty-state">No raw OCR text found.</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h2 class="card-title">Metadata</h2>
|
|
<div class="meta-grid">
|
|
<div class="meta-item"><span class="meta-label">Type</span>{{ document.document_type }}</div>
|
|
<div class="meta-item"><span class="meta-label">Review status</span>{{ document.review_status }}</div>
|
|
<div class="meta-item"><span class="meta-label">Source path</span>{{ document.source_path }}</div>
|
|
<div class="meta-item"><span class="meta-label">Current path</span>{{ document.current_path }}</div>
|
|
<div class="meta-item"><span class="meta-label">Original filename</span>{{ document.original_filename }}</div>
|
|
<div class="meta-item"><span class="meta-label">Canonical filename</span>{{ document.canonical_filename }}</div>
|
|
<div class="meta-item"><span class="meta-label">MIME type</span>{{ document.mime_type }}</div>
|
|
<div class="meta-item"><span class="meta-label">File size</span>{{ document.file_size }}</div>
|
|
<div class="meta-item"><span class="meta-label">Page count</span>{{ document.page_count }}</div>
|
|
<div class="meta-item"><span class="meta-label">Share path</span>{{ document.share_path or "" }}</div>
|
|
<div class="meta-item"><span class="meta-label">Created at</span>{{ document.created_at }}</div>
|
|
<div class="meta-item"><span class="meta-label">Updated at</span>{{ document.updated_at }}</div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
|
|
<script>
|
|
(function () {
|
|
const appShell = document.getElementById("app-shell");
|
|
const menuToggle = document.getElementById("menu-toggle");
|
|
if (appShell && menuToggle) {
|
|
menuToggle.addEventListener("click", function () {
|
|
appShell.classList.toggle("nav-open");
|
|
});
|
|
menuToggle.addEventListener("keydown", function (e) {
|
|
if (e.key === "Enter" || e.key === " ") {
|
|
e.preventDefault();
|
|
appShell.classList.toggle("nav-open");
|
|
}
|
|
});
|
|
}
|
|
|
|
const tabButtons = document.querySelectorAll("[data-tab]");
|
|
const tabPanels = document.querySelectorAll("[data-panel]");
|
|
|
|
function activateTab(target) {
|
|
tabButtons.forEach(function (b) {
|
|
b.classList.toggle("active", b.getAttribute("data-tab") === target);
|
|
});
|
|
tabPanels.forEach(function (p) {
|
|
p.classList.toggle("active", p.getAttribute("data-panel") === target);
|
|
});
|
|
}
|
|
|
|
tabButtons.forEach(function (btn) {
|
|
btn.addEventListener("click", function () {
|
|
const target = btn.getAttribute("data-tab");
|
|
activateTab(target);
|
|
|
|
const url = new URL(window.location.href);
|
|
url.searchParams.set("tab", target);
|
|
window.history.replaceState({}, "", url.toString());
|
|
});
|
|
});
|
|
|
|
const textarea = document.getElementById("reviewed_text");
|
|
const expectedLinesEl = document.getElementById("expected-lines");
|
|
const actualLinesEl = document.getElementById("actual-lines");
|
|
const warningEl = document.getElementById("line-warning");
|
|
const saveBtn = document.getElementById("save-reviewed-btn");
|
|
const lineNumbersEl = document.getElementById("line-numbers");
|
|
|
|
if (textarea && expectedLinesEl && actualLinesEl && warningEl && saveBtn && lineNumbersEl) {
|
|
const expectedLines = parseInt(expectedLinesEl.textContent || "0", 10);
|
|
|
|
function countLines(text) {
|
|
if (text.length === 0) return 0;
|
|
return text.split('\n').length;
|
|
}
|
|
|
|
function rebuildLineNumbers(lineCount) {
|
|
let nums = "";
|
|
for (let i = 1; i <= lineCount; i++) nums += i + "\n";
|
|
lineNumbersEl.textContent = nums;
|
|
}
|
|
|
|
function syncScroll() {
|
|
lineNumbersEl.scrollTop = textarea.scrollTop;
|
|
}
|
|
|
|
function updateEditorState() {
|
|
const actual = countLines(textarea.value);
|
|
actualLinesEl.textContent = actual.toString();
|
|
rebuildLineNumbers(Math.max(actual, expectedLines));
|
|
const mismatch = expectedLines > 0 && actual !== expectedLines;
|
|
warningEl.style.display = mismatch ? "inline" : "none";
|
|
saveBtn.disabled = mismatch;
|
|
syncScroll();
|
|
}
|
|
|
|
textarea.addEventListener("input", updateEditorState);
|
|
textarea.addEventListener("scroll", syncScroll);
|
|
|
|
updateEditorState();
|
|
syncScroll();
|
|
}
|
|
})();
|
|
|
|
const documentTypeInput = document.getElementById("document_type_input");
|
|
const documentTypeSuggestions = document.getElementById("document-type-suggestions");
|
|
const existingDocumentTypes = {{ existing_document_types|tojson }};
|
|
|
|
if (documentTypeInput && documentTypeSuggestions) {
|
|
function renderDocumentTypeSuggestions() {
|
|
const value = (documentTypeInput.value || "").trim().toLowerCase();
|
|
|
|
let matches = existingDocumentTypes.filter(function (item) {
|
|
return item && (!value || item.toLowerCase().includes(value));
|
|
});
|
|
|
|
if (value) {
|
|
matches = matches.filter(function (item) {
|
|
return item.toLowerCase() !== value;
|
|
});
|
|
}
|
|
|
|
matches = matches.slice(0, 8);
|
|
|
|
if (!matches.length) {
|
|
documentTypeSuggestions.style.display = "none";
|
|
documentTypeSuggestions.innerHTML = "";
|
|
return;
|
|
}
|
|
|
|
documentTypeSuggestions.innerHTML = matches.map(function (item) {
|
|
return '<button type="button" class="doc-type-option" data-value="' + item.replace(/"/g, '"') + '" style="display:block; width:100%; text-align:left; padding:0.7rem 0.85rem; border:0; background:#fff; cursor:pointer;">' + item + '</button>';
|
|
}).join("");
|
|
|
|
documentTypeSuggestions.style.display = "block";
|
|
|
|
documentTypeSuggestions.querySelectorAll(".doc-type-option").forEach(function (btn) {
|
|
btn.addEventListener("click", function () {
|
|
documentTypeInput.value = btn.getAttribute("data-value") || "";
|
|
documentTypeSuggestions.style.display = "none";
|
|
documentTypeSuggestions.innerHTML = "";
|
|
documentTypeInput.focus();
|
|
});
|
|
});
|
|
}
|
|
|
|
documentTypeInput.addEventListener("input", renderDocumentTypeSuggestions);
|
|
documentTypeInput.addEventListener("focus", renderDocumentTypeSuggestions);
|
|
|
|
document.addEventListener("click", function (e) {
|
|
if (!documentTypeSuggestions.contains(e.target) && e.target !== documentTypeInput) {
|
|
documentTypeSuggestions.style.display = "none";
|
|
}
|
|
});
|
|
}
|
|
|
|
</script>
|
|
</body>
|
|
</html>
|