CKEditor在表格可编辑DIV自动实例化的问题及解决需求
解决表格内contenteditable元素被CKEditor自动初始化的问题
问题描述
我有一个带contenteditable列的表格,用户可在其中输入数据。但保存后重新加载页面,表格内所有contenteditable的DIV都会被自动生成CKEditor实例,破坏了占位符及其他功能。仅表格内的contenteditable DIV出现此问题,表格内的input或表格外的contenteditable DIV均正常。此外,页面中有一个textarea需要保留CKEditor功能。
需二选一解决:
- 检测并销毁表格内所有CKEditor实例
- 阻止CKEditor在表格内初始化
方案一:阻止CKEditor自动初始化表格内元素
CKEditor默认会自动检测页面contenteditable元素并初始化,可通过以下方式精准控制:
方法1:给目标元素添加忽略属性
在createCol函数创建contenteditable DIV时,添加data-cke-editable="false"属性,CKEditor会自动跳过这些元素:
// 对应number和text类型的元素创建分支 } else if(type === 'number') { element = document.createElement('div'); element.setAttribute('contenteditable', 'true'); element.classList.add('table-col-text'); // 添加CKEditor忽略标记 element.setAttribute('data-cke-editable', 'false'); $(element).keypress(function(e) { if (isNaN(String.fromCharCode(e.which))) e.preventDefault(); }); } else if(type === 'text') { element = document.createElement('div'); element.setAttribute('contenteditable', 'true'); element.classList.add('table-col-text'); // 添加CKEditor忽略标记 element.setAttribute('data-cke-editable', 'false'); }
方法2:全局关闭自动inline初始化,仅手动指定textarea
关闭CKEditor的自动inline初始化,只手动初始化需要的textarea:
// 关闭自动inline初始化 CKEDITOR.disableAutoInline(); // 手动初始化目标textarea CKEDITOR.replace('your-target-textarea-id');
方案二:销毁表格内已生成的CKEditor实例
若无法阻止初始化,可在页面加载完成后遍历表格元素,销毁对应实例:
document.addEventListener('DOMContentLoaded', function() { // 选择表格内所有contenteditable元素 const tableEditables = document.querySelectorAll('#tbody [contenteditable="true"]'); tableEditables.forEach(el => { // 查找元素对应的CKEditor实例 const editor = CKEDITOR.editor.getEditor(el); if (editor) { // 销毁实例并恢复原元素状态 editor.destroy(true); } }); });
附:原动态创建行/列代码
动态创建新行代码
function addRow() { var mainRow = document.querySelector('#main-row'); var tbody = document.querySelector('#tbody'); var newRow = document.createElement('tr'); var rowIndex = tbody.children.length; newRow.classList.add('table-body-row'); newRow.setAttribute('table-row-index', rowIndex); for(var i = 0; i < mainRow.children.length; i++) { var newCol = document.createElement('td'); var newElement = createCol(tableColsConfig[i]); newCol.append(newElement); newRow.append(newCol); } var iconDelete = newRow.children[mainRow.children.length - 1]; iconDelete.innerHTML = '<i class="table-icon fa fa-minus" aria-hidden="true"></i>'; iconDelete.classList.add('table-delete-box'); iconDelete.classList.add('icon-container'); iconDelete.setAttribute('table-row-index', rowIndex); iconDelete.setAttribute('onclick', 'deleteRow(this)'); tbody.append(newRow); if(tbody.children.length === maxRows) { addRowButton.classList.add('table-icon-disabled'); } }
动态创建新列代码
function createCol(colConfig) { var element; var type; if(!colConfig || !colConfig.type) { type = ''; } else { type = colConfig.type; } if(type === 'select') { element = document.createElement('select'); element.classList.add('table-col-select'); for(var j = 0; j < colConfig.options.length; j++) { var current = colConfig.options[j]; var option = document.createElement('option'); option.setAttribute('label', current.label); option.setAttribute('value', current.value); element.append(option); } } else if(type === 'date') { element = document.createElement('input'); element.classList.add('dateBlock'); element.classList.add('table-col-date'); $(element).datetimepicker({ //defaultDate: new Date(), format: 'DD.MM.YYYY', pickTime: false, icons: { time: "fa fa-clock-o", date: "fa fa-calendar", up: "fa fa-arrow-up", down: "fa fa-arrow-down" } }); $(element).on('dp.change', function(e) { handleTableInput(e); }); } else if(type === 'number') { element = document.createElement('div'); element.setAttribute('contenteditable', 'true'); element.classList.add('table-col-text'); $(element).keypress(function(e) { if (isNaN(String.fromCharCode(e.which))) e.preventDefault(); }); } else if(type === 'text') { element = document.createElement('div'); element.setAttribute('contenteditable', 'true'); element.classList.add('table-col-text'); } else { return; } //绑定配置中的自定义类 if(colConfig.customClass) { var classArr = colConfig.customClass; for(var i = 0; i < classArr.length; i++) { element.classList.add(classArr[i]); } } //绑定配置中的回调函数 if(colConfig.callback && colConfig.callbackType) { var callbackFunc = colConfig.callback; var callbackType = colConfig.callbackType; element.setAttribute('on' + callbackType, callbackFunc + '(event)'); if(colConfig.triggerImmediately) { var customEvent = new Event(callbackType); element.dispatchEvent(customEvent); } } //绑定配置中的自定义属性 if(colConfig.attr) { var attrs = Object.entries(colConfig.attr); for(var i = 0; i < attrs.length; i++) { var attrName = attrs[i][0]; var attrValue = attrs[i][1]; element.setAttribute(attrName, attrValue); } } element.addEventListener('change', function() { handleTableInput(event) }); element.addEventListener('input', function() { handleTableInput(event) }); element.setAttribute('inputId', colConfig.inputId); return element; }
内容的提问来源于stack exchange,提问作者Nkwitchoua
相关产品推荐
相关产品推荐

