I edited the orders.php file. THE CK EDITOR was not updating because CKEditor 5 ignores direct DOM updates and was immediately reverting to the internal model.
So I rebuilt the handler to find the CKEditor 5 editor instance and then insert using:
- editor.getData() + editor.setData(current + comment)
That is the method CKEditor 5 actually honors.
Inject near the top of orders.php after $show_including_tax is set (or anywhere before the form is rendered).
/* ===== BOF: Predefined Comments (Zen4All / Boilerplate) ===== /
$z4a_predefined_comments = [];
if (defined('TABLE_ORDER_COMMENTS_CONTENT')) {
$z4a_predefined_comments_query = "SELECT comment_id, comment_title, comment_text
FROM " . TABLE_ORDER_COMMENTS_CONTENT . "
ORDER BY comment_title";
$z4a_predefined_comments = $db->Execute($z4a_predefined_comments_query);
}
/ ===== EOF: Predefined Comments ===== */
Inject inside the status update form (near the comments textarea).
This version stores the comment body in each option’s data-comment attribute.
/* ===== BOF: Predefined Comments dropdown ===== */
if (isset($z4a_predefined_comments) && is_object($z4a_predefined_comments) && !$z4a_predefined_comments->EOF) {
echo '<div class="form-group" style="margin: 10px 0;">';
echo ' <label for="z4a_predefined_comments"><strong>' . (defined('ENTRY_PREDEFINED_COMMENTS') ? ENTRY_PREDEFINED_COMMENTS : 'Predefined Comments') . '</strong></label>';
echo ' <select id="z4a_predefined_comments" class="form-control" onchange="z4aInsertPredefinedComment(this)">';
echo ' <option value="">' . (defined('TEXT_SELECT_COMMENT') ? TEXT_SELECT_COMMENT : 'Select a comment...') . '</option>';
while (!$z4a_predefined_comments->EOF) {
$commentTitle = zen_output_string_protected($z4a_predefined_comments->fields['comment_title']);
$commentText = $z4a_predefined_comments->fields['comment_text'];
// Escape for attribute safely
$commentTextAttr = htmlspecialchars($commentText, ENT_QUOTES, CHARSET);
echo ' <option value="' . (int)$z4a_predefined_comments->fields['comment_id'] . '" data-comment="' . $commentTextAttr . '">' . $commentTitle . '</option>';
$z4a_predefined_comments->MoveNext();
}
echo ' </select>';
echo '</div>';
}
/* ===== EOF: Predefined Comments dropdown ===== */
Inject once on the page (best placed near the bottom of orders.php, after the form exists, or in the header if you prefer).
This is the critical piece: it finds CKEditor 5’s editor instance and uses setData() so the UI updates correctly.
<script>
/* ===== BOF: Predefined Comments insert (CKEditor 5 safe) ===== */
window.z4aInsertPredefinedComment = function(sel) {
try {
var opt = sel.options[sel.selectedIndex];
if (!opt) return;
var html = opt.getAttribute('data-comment') || '';
if (!html.trim()) return;
// breadcrumb for debugging (optional)
window.__z4a_last_inserted = html.substring(0, 160);
// locate textarea
var ta = document.querySelector('textarea[name="comments"], #comments');
// Try to locate CKEditor 5 instance in the page
// Common patterns:
// - window.editor (single editor)
// - window.editors (map)
// - element.ckeditorInstance (some builds)
var editor = null;
if (window.editor && typeof window.editor.setData === 'function') {
editor = window.editor;
} else if (window.editors && typeof window.editors === 'object') {
for (var k in window.editors) {
if (window.editors[k] && typeof window.editors[k].setData === 'function') {
editor = window.editors[k];
break;
}
}
}
// If we found CKEditor 5, update it properly
if (editor && typeof editor.getData === 'function' && typeof editor.setData === 'function') {
var current = editor.getData() || '';
editor.setData(current + html);
// Keep textarea in sync for submit safety
if (ta) ta.value = editor.getData();
return;
}
// Fallback: no editor instance found, just append to textarea
if (ta) {
ta.value = (ta.value || '') + html;
}
} catch (e) {
// swallow to avoid breaking admin
console.error(e);
}
};
/* ===== EOF: Predefined Comments insert ===== */
</script>
NTO: building a better network thru collaboration
www.needtoorder.com | www.coffeewitheinstein.com