103 lines
3.8 KiB
HTML
103 lines
3.8 KiB
HTML
<label class="form-label">Notes</label>
|
|
<div class="d-flex justify-content-between align-items-start border rounded py-1 px-2">
|
|
<div class="me-3 w-100 markdown-body" id="editContainer"></div>
|
|
<script type="application/json" id="noteContent">{{ (field['template_ctx']['values']['notes'] if field['template_ctx']['values']['notes'] else '') | tojson }}</script>
|
|
<div class="form-check form-switch">
|
|
<input type="checkbox" class="form-check-input" id="editSwitch" onchange="changeMode()" role="switch"
|
|
aria-label="Edit mode switch for inventory notes.">
|
|
<label for="editSwitch" class="form-check-label">Edit</label>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@5/github-markdown.min.css" -->
|
|
<style>
|
|
textarea.auto-md {
|
|
box-sizing: border-box;
|
|
width: 100%;
|
|
max-height: 60vh;
|
|
overflow: hidden;
|
|
resize: vertical;
|
|
}
|
|
|
|
@supports (field-sizing: content) {
|
|
textarea.auto-md {
|
|
field-sizing: content;
|
|
}
|
|
}
|
|
</style>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/dompurify/dist/purify.min.js"></script>
|
|
<script src="{{ url_for('static', filename='js/components/markdown.js') }}" defer></script>
|
|
<script src="{{ url_for('static', filename='js/utils/json.js') }}" defer></script>
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
MarkDown.renderInto(document.getElementById('editContainer'), getMarkdown());
|
|
});
|
|
|
|
// used by entry_buttons submit
|
|
window.getMarkdown = function () {
|
|
return readJSONScript('noteContent', "");
|
|
};
|
|
|
|
function setMarkdown(md) {
|
|
const el = document.getElementById('noteContent');
|
|
if (el) el.textContent = JSON.stringify(md ?? "");
|
|
}
|
|
|
|
function changeMode() {
|
|
const container = document.getElementById('editContainer');
|
|
const toggle = document.getElementById('editSwitch');
|
|
if (!toggle.checked) {
|
|
MarkDown.renderInto(container, getMarkdown());
|
|
return;
|
|
}
|
|
|
|
const current = getMarkdown();
|
|
container.innerHTML = `
|
|
<textarea class="form-control w-100 auto-md" id="editor" name="notes">${escapeForTextarea(current)}</textarea>
|
|
<div class="mt-2 d-flex gap-2">
|
|
<button type="button" class="btn btn-primary btn-sm" onclick="saveEdit()">Save</button>
|
|
<button type="button" class="btn btn-secondary btn-sm" onclick="cancelEdit()">Cancel</button>
|
|
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="togglePreview()">Preview</button>
|
|
</div>
|
|
<div class="mt-2 border rounded p-2 d-none" id="preview" aria-live="polite"></div>
|
|
`;
|
|
const ta = document.getElementById('editor');
|
|
autoGrow(ta);
|
|
ta.addEventListener('input', () => autoGrow(ta));
|
|
}
|
|
|
|
function saveEdit() {
|
|
const ta = document.getElementById('editor');
|
|
const value = ta ? ta.value : "";
|
|
setMarkdown(value);
|
|
MarkDown.renderInto(document.getElementById('editContainer'), value);
|
|
document.getElementById('editSwitch').checked = false;
|
|
}
|
|
|
|
function cancelEdit() {
|
|
document.getElementById('editSwitch').checked = false;
|
|
MarkDown.renderInto(document.getElementById('editContainer'), getMarkdown());
|
|
}
|
|
|
|
function togglePreview() {
|
|
const ta = document.getElementById('editor');
|
|
const preview = document.getElementById('preview');
|
|
preview.classList.toggle('d-none');
|
|
if (!preview.classList.contains('d-none')) {
|
|
MarkDown.renderInto(preview, ta ? ta.value : "");
|
|
}
|
|
}
|
|
|
|
function autoGrow(ta) {
|
|
if (!ta) return;
|
|
if (CSS?.supports?.('field-sizing: content')) return;
|
|
ta.style.height = 'auto';
|
|
ta.style.height = ta.scrollHeight + 'px';
|
|
}
|
|
|
|
function escapeForTextarea(s) {
|
|
return (s ?? "").replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
|
|
}
|
|
</script>
|