186 lines
5.1 KiB
JavaScript
186 lines
5.1 KiB
JavaScript
import EditorJS from '../../vendor/editorjs/editorjs.mjs';
|
|
|
|
const form = document.querySelector('[data-page-editor]');
|
|
if (form) {
|
|
const holder = form.querySelector('[data-editor-holder]');
|
|
if (!holder) {
|
|
// No holder available, skip initialization.
|
|
} else {
|
|
const contentField = form.querySelector('#page-content');
|
|
const toggleButton = document.querySelector('[data-editor-toggle]');
|
|
const saveButton = document.querySelector('[data-editor-save]');
|
|
const canEdit = form.dataset.canEdit === '1';
|
|
|
|
const parseData = (value) => {
|
|
if (!value) {
|
|
return { blocks: [] };
|
|
}
|
|
try {
|
|
const parsed = JSON.parse(value);
|
|
if (parsed && typeof parsed === 'object') {
|
|
if (!Array.isArray(parsed.blocks)) {
|
|
parsed.blocks = [];
|
|
}
|
|
return parsed;
|
|
}
|
|
} catch (error) {
|
|
// ignore invalid JSON
|
|
}
|
|
return { blocks: [] };
|
|
};
|
|
|
|
const setToggleLabel = (mode) => {
|
|
if (!toggleButton) {
|
|
return;
|
|
}
|
|
const viewLabel = toggleButton.dataset.viewLabel || '';
|
|
const editLabel = toggleButton.dataset.editLabel || '';
|
|
const text = mode === 'edit' ? viewLabel : editLabel;
|
|
const icon = toggleButton.querySelector('[data-editor-icon]');
|
|
|
|
if (icon) {
|
|
icon.className = mode === 'edit' ? 'bi bi-eye-fill' : 'bi bi-pencil-square';
|
|
}
|
|
toggleButton.setAttribute('aria-label', text);
|
|
toggleButton.dataset.tooltip = text;
|
|
};
|
|
|
|
let mode = form.dataset.editMode === 'edit' && canEdit ? 'edit' : 'view';
|
|
form.dataset.editMode = mode;
|
|
setToggleLabel(mode);
|
|
|
|
const HeaderTool = window.Header || window.EditorJSHeader || null;
|
|
const ListTool = window.EditorjsList || window.List || null;
|
|
const ChecklistTool = window.Checklist || window.EditorJSChecklist || null;
|
|
const TableTool = window.Table || window.EditorJSTable || null;
|
|
const ColumnsTool = window.editorjsColumns || window.Columns || null;
|
|
const MarkerTool = window.Marker || null;
|
|
|
|
const tools = {};
|
|
if (HeaderTool) {
|
|
tools.header = {
|
|
class: HeaderTool,
|
|
inlineToolbar: true,
|
|
config: {
|
|
placeholder: form.dataset.headerPlaceholder || 'Heading',
|
|
levels: [1, 2, 3, 4],
|
|
defaultLevel: 1,
|
|
},
|
|
};
|
|
}
|
|
if (ListTool) {
|
|
tools.list = {
|
|
class: ListTool,
|
|
inlineToolbar: true,
|
|
config: {
|
|
defaultStyle: 'unordered',
|
|
},
|
|
};
|
|
}
|
|
if (ChecklistTool) {
|
|
tools.checklist = {
|
|
class: ChecklistTool,
|
|
inlineToolbar: true,
|
|
};
|
|
}
|
|
if (TableTool) {
|
|
tools.table = {
|
|
class: TableTool,
|
|
inlineToolbar: true,
|
|
config: {
|
|
rows: 2,
|
|
cols: 2,
|
|
},
|
|
};
|
|
}
|
|
if (ColumnsTool) {
|
|
const innerTools = { ...tools };
|
|
tools.columns = {
|
|
class: ColumnsTool,
|
|
config: {
|
|
EditorJsLibrary: EditorJS,
|
|
tools: innerTools,
|
|
},
|
|
};
|
|
}
|
|
if (MarkerTool) {
|
|
tools.marker = {
|
|
class: MarkerTool,
|
|
shortcut: 'CMD+SHIFT+M',
|
|
};
|
|
}
|
|
|
|
const inlineTools = ['bold', 'italic', 'link'];
|
|
if (MarkerTool) {
|
|
inlineTools.unshift('marker');
|
|
}
|
|
|
|
const editor = new EditorJS({
|
|
holder,
|
|
data: parseData(contentField ? contentField.value : ''),
|
|
readOnly: mode !== 'edit',
|
|
autofocus: mode === 'edit',
|
|
placeholder: form.dataset.placeholder || undefined,
|
|
tools,
|
|
inlineToolbar: inlineTools,
|
|
});
|
|
|
|
const toggleMode = async (nextMode) => {
|
|
if (!canEdit || mode === nextMode) {
|
|
return;
|
|
}
|
|
mode = nextMode;
|
|
form.dataset.editMode = mode;
|
|
setToggleLabel(mode);
|
|
if (editor.readOnly && editor.readOnly.toggle) {
|
|
await editor.readOnly.toggle(mode !== 'edit');
|
|
}
|
|
if (saveButton) {
|
|
saveButton.disabled = mode !== 'edit';
|
|
}
|
|
};
|
|
|
|
if (toggleButton && canEdit) {
|
|
toggleButton.addEventListener('click', () => {
|
|
toggleMode(mode === 'edit' ? 'view' : 'edit');
|
|
});
|
|
}
|
|
|
|
if (form && contentField && canEdit) {
|
|
form.addEventListener('submit', async (event) => {
|
|
if (form.dataset.submitting === '1') {
|
|
return;
|
|
}
|
|
event.preventDefault();
|
|
const output = await editor.save();
|
|
contentField.value = JSON.stringify(output);
|
|
form.dataset.submitting = '1';
|
|
|
|
try {
|
|
const formData = new FormData(form);
|
|
const response = await fetch(form.action || window.location.pathname, {
|
|
method: 'POST',
|
|
headers: {
|
|
'X-Requested-With': 'XMLHttpRequest',
|
|
Accept: 'application/json',
|
|
},
|
|
body: formData,
|
|
});
|
|
if (response.redirected) {
|
|
window.location.href = response.url;
|
|
return;
|
|
}
|
|
const data = await response.json().catch(() => null);
|
|
if (data && data.redirect) {
|
|
window.location.href = data.redirect;
|
|
return;
|
|
}
|
|
window.location.reload();
|
|
} catch (error) {
|
|
form.submit();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|