Refresh player and admin UI
This commit is contained in:
+323
-129
@@ -1,3 +1,27 @@
|
||||
import {
|
||||
Alignment,
|
||||
BlockQuote,
|
||||
Bold,
|
||||
ClassicEditor,
|
||||
Essentials,
|
||||
FontBackgroundColor,
|
||||
FontColor,
|
||||
FontFamily,
|
||||
FontSize,
|
||||
Heading,
|
||||
HorizontalLine,
|
||||
Indent,
|
||||
IndentBlock,
|
||||
Italic,
|
||||
InputTextView,
|
||||
Plugin,
|
||||
Paragraph,
|
||||
Strikethrough,
|
||||
Subscript,
|
||||
Superscript,
|
||||
Underline
|
||||
} from '/assets/js/ckeditor5/ckeditor5.js';
|
||||
|
||||
(function () {
|
||||
var dataElement = document.getElementById('slide-editor-data');
|
||||
if (!dataElement) {
|
||||
@@ -25,6 +49,99 @@
|
||||
var editorInstances = new Map();
|
||||
var submitting = false;
|
||||
|
||||
class FontSizeInputUI extends Plugin {
|
||||
static get pluginName() {
|
||||
return 'FontSizeInputUI';
|
||||
}
|
||||
|
||||
init() {
|
||||
var editor = this.editor;
|
||||
var fontSizeCommand = editor.commands.get('fontSize');
|
||||
var plugin = this;
|
||||
|
||||
if (!fontSizeCommand) {
|
||||
return;
|
||||
}
|
||||
|
||||
editor.ui.componentFactory.add('fontSizeInput', function (locale) {
|
||||
var view = new InputTextView(locale);
|
||||
|
||||
view.extendTemplate({
|
||||
attributes: {
|
||||
class: ['ck-font-size-input']
|
||||
}
|
||||
});
|
||||
|
||||
view.set({
|
||||
placeholder: 'Font size',
|
||||
ariaLabel: 'Font size'
|
||||
});
|
||||
|
||||
function getCurrentFontSizeValue() {
|
||||
var value = fontSizeCommand.value;
|
||||
if (value === null || value === undefined || value === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
var parsed = Math.round(Number(String(value).replace(/[^0-9.]/g, '')));
|
||||
return Number.isFinite(parsed) && parsed > 0 ? String(parsed) : '';
|
||||
}
|
||||
|
||||
function syncValue() {
|
||||
if (view.element && document.activeElement === view.element) {
|
||||
return;
|
||||
}
|
||||
|
||||
view.value = getCurrentFontSizeValue();
|
||||
}
|
||||
|
||||
view.on('render', function () {
|
||||
if (!view.element) {
|
||||
return;
|
||||
}
|
||||
|
||||
view.element.type = 'text';
|
||||
view.element.inputMode = 'numeric';
|
||||
view.element.autocomplete = 'off';
|
||||
view.element.spellcheck = false;
|
||||
syncValue();
|
||||
});
|
||||
|
||||
function applyValue() {
|
||||
if (!view.element) {
|
||||
return;
|
||||
}
|
||||
|
||||
var size = Math.max(1, Math.round(Number(view.element.value || 0)));
|
||||
if (!size) {
|
||||
return;
|
||||
}
|
||||
|
||||
editor.execute('fontSize', { value: size + 'px' });
|
||||
}
|
||||
|
||||
view.on('input', applyValue);
|
||||
view.on('blur', applyValue);
|
||||
|
||||
view.on('keydown', function (_eventInfo, domEvent) {
|
||||
if (domEvent.key === 'Enter') {
|
||||
domEvent.preventDefault();
|
||||
if (view.element) {
|
||||
view.element.blur();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
plugin.listenTo(editor.model.document.selection, 'change:range', syncValue);
|
||||
plugin.listenTo(fontSizeCommand, 'change:value', syncValue);
|
||||
|
||||
syncValue();
|
||||
|
||||
return view;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function escapeHtml(value) {
|
||||
return String(value ?? '')
|
||||
.replace(/&/g, '&')
|
||||
@@ -44,25 +161,7 @@
|
||||
}
|
||||
|
||||
function normalizeEditorData(value) {
|
||||
var raw = String(value || '');
|
||||
if (!raw) {
|
||||
return { time: Date.now(), blocks: [] };
|
||||
}
|
||||
try {
|
||||
var parsed = JSON.parse(raw);
|
||||
if (parsed && Array.isArray(parsed.blocks)) {
|
||||
return parsed;
|
||||
}
|
||||
} catch (_error) {
|
||||
// fall through to legacy HTML/plain text
|
||||
}
|
||||
return {
|
||||
time: Date.now(),
|
||||
blocks: [{
|
||||
type: 'paragraph',
|
||||
data: { text: raw }
|
||||
}]
|
||||
};
|
||||
return String(value || '');
|
||||
}
|
||||
|
||||
function sanitizePreviewHtml(html) {
|
||||
@@ -70,23 +169,87 @@
|
||||
output = output.replace(/<script[\s\S]*?<\/script>/gi, '');
|
||||
output = output.replace(/<style[\s\S]*?<\/style>/gi, '');
|
||||
return output.replace(/<[^>]+>/g, function (tag) {
|
||||
var match = tag.match(/^<\s*(\/?)\s*([a-z0-9]+)(?:\s[^>]*)?>$/i);
|
||||
var match = tag.match(/^<\s*(\/?)\s*([a-z0-9]+)([\s\S]*?)(\/?)>$/i);
|
||||
if (!match) {
|
||||
return '';
|
||||
}
|
||||
var closing = Boolean(match[1]);
|
||||
var name = String(match[2] || '').toLowerCase();
|
||||
var allowed = ['b', 'strong', 'i', 'em', 'u', 'br', 'p', 'div', 'ul', 'ol', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'pre', 'code', 'table', 'thead', 'tbody', 'tr', 'th', 'td'];
|
||||
var attrText = String(match[3] || '');
|
||||
var selfClosing = Boolean(match[4]) || name === 'br' || name === 'hr';
|
||||
var allowed = ['a', 'b', 'blockquote', 'br', 'code', 'div', 'em', 'figure', 'figcaption', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'li', 'ol', 'p', 'pre', 'span', 'strong', 'sub', 'sup', 'table', 'tbody', 'td', 'th', 'thead', 'tr', 'u', 'ul'];
|
||||
if (allowed.indexOf(name) === -1) {
|
||||
return '';
|
||||
}
|
||||
if (name === 'br') {
|
||||
return '<br>';
|
||||
if (closing) {
|
||||
return '</' + name + '>';
|
||||
}
|
||||
return closing ? '</' + name + '>' : '<' + name + '>';
|
||||
if (selfClosing) {
|
||||
return '<' + name + sanitizeTagAttributes(name, attrText) + '>';
|
||||
}
|
||||
return '<' + name + sanitizeTagAttributes(name, attrText) + '>';
|
||||
});
|
||||
}
|
||||
|
||||
function sanitizeTagAttributes(tagName, attrText) {
|
||||
var allowedAttributes = {
|
||||
a: ['href', 'title', 'target', 'rel', 'class', 'style'],
|
||||
blockquote: ['class', 'style'],
|
||||
div: ['class', 'style'],
|
||||
figure: ['class', 'style'],
|
||||
figcaption: ['class', 'style'],
|
||||
h1: ['class', 'style'],
|
||||
h2: ['class', 'style'],
|
||||
h3: ['class', 'style'],
|
||||
h4: ['class', 'style'],
|
||||
h5: ['class', 'style'],
|
||||
h6: ['class', 'style'],
|
||||
li: ['class', 'style'],
|
||||
ol: ['class', 'style', 'start'],
|
||||
p: ['class', 'style'],
|
||||
pre: ['class', 'style'],
|
||||
span: ['class', 'style'],
|
||||
table: ['class', 'style'],
|
||||
td: ['class', 'style', 'colspan', 'rowspan'],
|
||||
th: ['class', 'style', 'colspan', 'rowspan', 'scope'],
|
||||
tr: ['class', 'style'],
|
||||
ul: ['class', 'style']
|
||||
};
|
||||
var allowed = allowedAttributes[tagName] || [];
|
||||
if (!allowed.length) {
|
||||
return '';
|
||||
}
|
||||
|
||||
var attrs = [];
|
||||
attrText.replace(/([a-zA-Z0-9:-]+)(?:\s*=\s*("([^"]*)"|'([^']*)'|([^\s"'>/=`]+)))?/g, function (_full, key, _valuePart, doubleQuoted, singleQuoted, bareValue) {
|
||||
var lowerKey = String(key || '').toLowerCase();
|
||||
if (allowed.indexOf(lowerKey) === -1) {
|
||||
return '';
|
||||
}
|
||||
var value = doubleQuoted !== undefined ? doubleQuoted : singleQuoted !== undefined ? singleQuoted : bareValue !== undefined ? bareValue : '';
|
||||
if (lowerKey === 'href' && /^(?:\s*javascript:|\s*data:)/i.test(String(value || ''))) {
|
||||
return '';
|
||||
}
|
||||
if (lowerKey === 'style' && /(?:expression\s*\(|javascript:|url\s*\()/i.test(String(value || ''))) {
|
||||
return '';
|
||||
}
|
||||
if (lowerKey === 'target') {
|
||||
var targetValue = String(value || '').trim();
|
||||
if (targetValue === '_blank') {
|
||||
attrs.push(' target="_blank"');
|
||||
if (attrs.indexOf(' rel="noreferrer noopener"') === -1) {
|
||||
attrs.push(' rel="noreferrer noopener"');
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
||||
attrs.push(' ' + lowerKey + '="' + escapeHtml(value) + '"');
|
||||
return '';
|
||||
});
|
||||
|
||||
return attrs.join('');
|
||||
}
|
||||
|
||||
function renderPreviewListItem(item, tag) {
|
||||
if (item && typeof item === 'object') {
|
||||
var content = item.content !== undefined ? item.content : (item.text !== undefined ? item.text : item.value !== undefined ? item.value : '');
|
||||
@@ -147,22 +310,17 @@
|
||||
if (!raw) {
|
||||
return '<div class="slide-preview-placeholder">Empty text</div>';
|
||||
}
|
||||
try {
|
||||
var parsed = JSON.parse(raw);
|
||||
if (parsed && Array.isArray(parsed.blocks)) {
|
||||
return parsed.blocks.map(renderPreviewBlock).join('');
|
||||
}
|
||||
} catch (_error) {
|
||||
// fall through to raw text
|
||||
}
|
||||
return '<p>' + sanitizePreviewHtml(raw) + '</p>';
|
||||
return sanitizePreviewHtml(raw);
|
||||
}
|
||||
|
||||
function renderPreviewTextRegion(region, value, style, scale) {
|
||||
var fontFamily = style.font_family ? 'font-family:' + escapeHtml(style.font_family) + ';' : '';
|
||||
var fontSize = style.font_size ? 'font-size:' + Math.max(1, Math.round(Number(style.font_size) * scale)) + 'px;' : '';
|
||||
var color = style.font_color ? 'color:' + escapeHtml(style.font_color) + ';' : '';
|
||||
return '<div class="slide-preview-text-content" style="' + fontFamily + fontSize + color + '">' + renderPreviewText(value) + '</div>';
|
||||
var fontSize = style.font_size ? 'font-size:' + Math.max(1, Math.round(Number(style.font_size))) + 'px;' : '';
|
||||
var width = Math.max(1, Math.round(Number(region && region.width ? region.width : 0) || 1));
|
||||
var height = Math.max(1, Math.round(Number(region && region.height ? region.height : 0) || 1));
|
||||
var wrapperStyle = 'width:' + width + 'px;height:' + height + 'px;overflow:hidden;' + fontFamily + fontSize + color;
|
||||
return '<div class="slide-preview-text-content" style="' + wrapperStyle + '">' + renderPreviewText(value) + '</div>';
|
||||
}
|
||||
|
||||
function renderPreviewWebpageRegion(value) {
|
||||
@@ -195,6 +353,16 @@
|
||||
return card ? card.querySelector('input[type="hidden"][name="region_text_' + regionId + '"]') : null;
|
||||
}
|
||||
|
||||
function getEditorFontSizeHiddenInput(regionId) {
|
||||
var card = templateFields.querySelector('[data-region-id="' + regionId + '"]');
|
||||
return card ? card.querySelector('input[name="region_font_size_' + regionId + '"]') : null;
|
||||
}
|
||||
|
||||
function normalizeFontSizeValue(value) {
|
||||
var size = Math.max(1, Math.round(Number(String(value || '').replace(/[^0-9.]/g, ''))));
|
||||
return size ? String(size) : '';
|
||||
}
|
||||
|
||||
function getCurrentTextStyle(region) {
|
||||
var current = existingContent[region.region_key] || {};
|
||||
return {
|
||||
@@ -204,16 +372,8 @@
|
||||
};
|
||||
}
|
||||
|
||||
function getTextStyleFromCard(card, region) {
|
||||
var familyInput = card.querySelector('[name="region_font_family_' + region.id + '"]');
|
||||
var sizeInput = card.querySelector('[name="region_font_size_' + region.id + '"]');
|
||||
var colorInput = card.querySelector('[name="region_font_color_' + region.id + '"]');
|
||||
var current = getCurrentTextStyle(region);
|
||||
return {
|
||||
font_family: String(familyInput ? familyInput.value : current.font_family).trim() || current.font_family,
|
||||
font_size: Math.max(8, Number(sizeInput ? sizeInput.value : current.font_size)),
|
||||
font_color: String(colorInput ? colorInput.value : current.font_color).trim() || current.font_color
|
||||
};
|
||||
function getTextStyleFromCard(_card, region) {
|
||||
return getCurrentTextStyle(region);
|
||||
}
|
||||
|
||||
function getSelectedTemplate() {
|
||||
@@ -229,12 +389,12 @@
|
||||
});
|
||||
}
|
||||
|
||||
function getRegionBox(region, stageRect, canvasWidth, canvasHeight) {
|
||||
function getRegionBox(region, canvasWidth, canvasHeight) {
|
||||
return {
|
||||
left: (Number(region.x || 0) / canvasWidth) * stageRect.width,
|
||||
top: (Number(region.y || 0) / canvasHeight) * stageRect.height,
|
||||
width: (Number(region.width || 0) / canvasWidth) * stageRect.width,
|
||||
height: (Number(region.height || 0) / canvasHeight) * stageRect.height
|
||||
left: Math.max(0, Math.round(Number(region.x || 0))),
|
||||
top: Math.max(0, Math.round(Number(region.y || 0))),
|
||||
width: Math.max(1, Math.round(Number(region.width || 0) || 1)),
|
||||
height: Math.max(1, Math.round(Number(region.height || 0) || 1))
|
||||
};
|
||||
}
|
||||
|
||||
@@ -246,6 +406,9 @@
|
||||
slidePreviewEmpty.style.display = 'flex';
|
||||
slidePreviewEmpty.textContent = 'Select a template to preview the slide.';
|
||||
slidePreviewOverlay.innerHTML = '';
|
||||
slidePreviewOverlay.style.width = '';
|
||||
slidePreviewOverlay.style.height = '';
|
||||
slidePreviewOverlay.style.transform = '';
|
||||
slidePreviewStage.style.aspectRatio = '16 / 9';
|
||||
return;
|
||||
}
|
||||
@@ -260,6 +423,9 @@
|
||||
slidePreviewBackground.style.display = template.background_image_path ? 'block' : 'none';
|
||||
slidePreviewBackground.src = template.background_image_path || '';
|
||||
slidePreviewOverlay.innerHTML = '';
|
||||
slidePreviewOverlay.style.width = '';
|
||||
slidePreviewOverlay.style.height = '';
|
||||
slidePreviewOverlay.style.transform = '';
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -269,9 +435,13 @@
|
||||
|
||||
var stageRect = slidePreviewStage.getBoundingClientRect();
|
||||
var scale = Math.min(stageRect.width / canvasWidth, stageRect.height / canvasHeight) || 1;
|
||||
slidePreviewOverlay.style.width = canvasWidth + 'px';
|
||||
slidePreviewOverlay.style.height = canvasHeight + 'px';
|
||||
slidePreviewOverlay.style.transform = 'scale(' + scale + ')';
|
||||
slidePreviewOverlay.style.transformOrigin = 'top left';
|
||||
var regions = template.regions || [];
|
||||
slidePreviewOverlay.innerHTML = regions.map(function (region) {
|
||||
var box = getRegionBox(region, stageRect, canvasWidth, canvasHeight);
|
||||
var box = getRegionBox(region, canvasWidth, canvasHeight);
|
||||
var card = templateFields.querySelector('[data-region-id="' + region.id + '"]');
|
||||
var hiddenInput = card && card.querySelector('input[type="hidden"][name="region_text_' + region.id + '"]');
|
||||
var htmlInput = card && card.querySelector('textarea[name="region_html_' + region.id + '"]');
|
||||
@@ -312,41 +482,16 @@
|
||||
|
||||
function renderTextRegion(region) {
|
||||
var current = getCurrentRegionValue(region);
|
||||
var style = getCurrentTextStyle(region);
|
||||
var fontChoices = [
|
||||
'Arial',
|
||||
'Courier New',
|
||||
'Garamond',
|
||||
'Georgia',
|
||||
'Helvetica',
|
||||
'Impact',
|
||||
'Lucida Console',
|
||||
'Palatino',
|
||||
'Tahoma',
|
||||
'Times New Roman',
|
||||
'Trebuchet MS',
|
||||
'Verdana'
|
||||
];
|
||||
return '' +
|
||||
'<div class="card template-field-card" data-region-id="' + region.id + '">' +
|
||||
'<div class="template-field-head">' +
|
||||
'<strong>' + escapeHtml(region.label) + '</strong>' +
|
||||
'<span class="chip">Text</span>' +
|
||||
'</div>' +
|
||||
'<div class="row template-text-style-row">' +
|
||||
'<label style="flex: 1;">Font style' +
|
||||
'<select name="region_font_family_' + region.id + '">' + fontChoices.map(function (font) {
|
||||
return '<option value="' + escapeHtml(font) + '"' + (style.font_family === font ? ' selected' : '') + '>' + escapeHtml(font) + '</option>';
|
||||
}).join('') + '</select>' +
|
||||
'</label>' +
|
||||
'<label style="width: 120px;">Size' +
|
||||
'<input type="number" name="region_font_size_' + region.id + '" min="8" max="180" step="1" value="' + escapeHtml(style.font_size) + '" />' +
|
||||
'</label>' +
|
||||
'<label style="width: 140px;">Color' +
|
||||
'<input type="color" name="region_font_color_' + region.id + '" value="' + escapeHtml(style.font_color) + '" />' +
|
||||
'</label>' +
|
||||
'<div class="ckeditor-holder" data-region-id="' + region.id + '">' +
|
||||
'<textarea class="ckeditor-source" rows="10">' + escapeHtml(current) + '</textarea>' +
|
||||
'</div>' +
|
||||
'<div class="editorjs-holder" id="editorjs-' + region.id + '" data-region-id="' + region.id + '"></div>' +
|
||||
'<input type="hidden" name="region_font_size_' + region.id + '" value="' + escapeHtml(getCurrentTextStyle(region).font_size) + '" />' +
|
||||
'<input type="hidden" name="region_text_' + region.id + '" value="' + escapeHtml(current) + '" />' +
|
||||
'</div>';
|
||||
}
|
||||
@@ -422,59 +567,109 @@
|
||||
return renderTextRegion(region);
|
||||
}).join('') : '<div class="muted">This template has no regions.</div>';
|
||||
|
||||
templateFields.querySelectorAll('.editorjs-holder').forEach(function (holder) {
|
||||
templateFields.querySelectorAll('.ckeditor-holder').forEach(function (holder) {
|
||||
var regionId = holder.getAttribute('data-region-id');
|
||||
var source = holder.querySelector('.ckeditor-source');
|
||||
var hidden = getEditorHiddenInput(regionId);
|
||||
var editor = new EditorJS({
|
||||
holder: holder.id,
|
||||
minHeight: 120,
|
||||
var editorConfig = {
|
||||
licenseKey: 'GPL',
|
||||
placeholder: 'Write content...',
|
||||
inlineToolbar: true,
|
||||
tools: {
|
||||
header: {
|
||||
class: Header,
|
||||
config: {
|
||||
placeholder: 'Enter a header',
|
||||
levels: [1, 2, 3, 4],
|
||||
defaultLevel: 3
|
||||
}
|
||||
},
|
||||
list: {
|
||||
class: EditorjsList,
|
||||
inlineToolbar: false,
|
||||
config: {
|
||||
defaultStyle: 'unordered'
|
||||
}
|
||||
},
|
||||
table: {
|
||||
class: Table,
|
||||
inlineToolbar: true,
|
||||
config: {
|
||||
rows: 2,
|
||||
cols: 3,
|
||||
maxRows: 5,
|
||||
maxCols: 5
|
||||
}
|
||||
},
|
||||
marker: {
|
||||
class: Marker
|
||||
}
|
||||
toolbar: {
|
||||
items: [
|
||||
'undo',
|
||||
'redo',
|
||||
'|',
|
||||
'heading',
|
||||
'|',
|
||||
'fontSizeInput',
|
||||
'fontFamily',
|
||||
'fontColor',
|
||||
'fontBackgroundColor',
|
||||
'|',
|
||||
'bold',
|
||||
'italic',
|
||||
'underline',
|
||||
'strikethrough',
|
||||
'subscript',
|
||||
'superscript',
|
||||
'|',
|
||||
'horizontalLine',
|
||||
'blockQuote',
|
||||
'|',
|
||||
'alignment',
|
||||
'|',
|
||||
'outdent',
|
||||
'indent'
|
||||
],
|
||||
shouldNotGroupWhenFull: false
|
||||
},
|
||||
data: normalizeEditorData(hidden ? hidden.value : ''),
|
||||
onChange: function () {
|
||||
var instance = editorInstances.get(regionId);
|
||||
if (!instance) {
|
||||
return;
|
||||
}
|
||||
instance.save().then(function (output) {
|
||||
if (hidden) {
|
||||
hidden.value = JSON.stringify(output);
|
||||
}
|
||||
renderPreview();
|
||||
plugins: [
|
||||
Alignment,
|
||||
BlockQuote,
|
||||
Bold,
|
||||
Essentials,
|
||||
FontBackgroundColor,
|
||||
FontColor,
|
||||
FontFamily,
|
||||
FontSize,
|
||||
FontSizeInputUI,
|
||||
Heading,
|
||||
HorizontalLine,
|
||||
Indent,
|
||||
IndentBlock,
|
||||
Italic,
|
||||
Paragraph,
|
||||
Strikethrough,
|
||||
Subscript,
|
||||
Superscript,
|
||||
Underline
|
||||
],
|
||||
fontFamily: {
|
||||
supportAllValues: true
|
||||
},
|
||||
fontSize: {
|
||||
options: [20, 24, 28, 32, 36, 40, 44],
|
||||
supportAllValues: true
|
||||
},
|
||||
heading: {
|
||||
options: [
|
||||
{ model: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph' },
|
||||
{ model: 'heading1', view: 'h1', title: 'Heading 1', class: 'ck-heading_heading1' },
|
||||
{ model: 'heading2', view: 'h2', title: 'Heading 2', class: 'ck-heading_heading2' },
|
||||
{ model: 'heading3', view: 'h3', title: 'Heading 3', class: 'ck-heading_heading3' },
|
||||
{ model: 'heading4', view: 'h4', title: 'Heading 4', class: 'ck-heading_heading4' }
|
||||
]
|
||||
},
|
||||
initialData: normalizeEditorData((source && source.value) || (hidden ? hidden.value : ''))
|
||||
};
|
||||
|
||||
ClassicEditor.create(source || holder, editorConfig).then(function (editor) {
|
||||
editorInstances.set(regionId, editor);
|
||||
var fontSizeHidden = getEditorFontSizeHiddenInput(regionId);
|
||||
var fontSizeCommand = editor.commands.get('fontSize');
|
||||
if (hidden) {
|
||||
hidden.value = editor.getData();
|
||||
}
|
||||
if (fontSizeHidden && fontSizeCommand) {
|
||||
fontSizeHidden.value = normalizeFontSizeValue(fontSizeCommand.value) || fontSizeHidden.value;
|
||||
fontSizeCommand.on('change:value', function () {
|
||||
fontSizeHidden.value = normalizeFontSizeValue(fontSizeCommand.value) || fontSizeHidden.value;
|
||||
});
|
||||
}
|
||||
editor.model.document.on('change:data', function () {
|
||||
var instance = editorInstances.get(regionId);
|
||||
if (instance !== editor) {
|
||||
return;
|
||||
}
|
||||
if (hidden) {
|
||||
hidden.value = editor.getData();
|
||||
}
|
||||
renderPreview();
|
||||
});
|
||||
renderPreview();
|
||||
}).catch(function (error) {
|
||||
console.error('Failed to initialize CKEditor.', error);
|
||||
});
|
||||
editorInstances.set(regionId, editor);
|
||||
});
|
||||
|
||||
templateFields.querySelectorAll('input[type="file"][name^="region_image_"]').forEach(function (input) {
|
||||
@@ -497,16 +692,15 @@
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
var saves = Array.prototype.map.call(templateFields.querySelectorAll('.editorjs-holder'), function (holder) {
|
||||
var saves = Array.prototype.map.call(templateFields.querySelectorAll('.ckeditor-holder'), function (holder) {
|
||||
var regionId = holder.getAttribute('data-region-id');
|
||||
var editor = editorInstances.get(regionId);
|
||||
var hidden = getEditorHiddenInput(regionId);
|
||||
if (!editor || !hidden) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return editor.save().then(function (output) {
|
||||
hidden.value = JSON.stringify(output);
|
||||
});
|
||||
hidden.value = editor.getData();
|
||||
return Promise.resolve();
|
||||
});
|
||||
submitting = true;
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user