返回

AlloyEditor表格单元格背景色自定义方案

vue.js

AlloyEditor 表格单元格背景色自定义处理

问题分析

AlloyEditor 基于 CKEditor 构建,提供强大的富文本编辑功能。用户反馈:在使用 AlloyEditor 编辑表格时,期望点击 “BGColor” 按钮时,能直接为表格 <td> 单元格设置背景颜色,而不是仅对单元格内的文字内容添加 <span> 包裹并设置背景色。当前,虽然自定义颜色在表格配置中生效,却仅影响文本背景,并未直接作用于单元格本身。 这通常是由于默认的 BGColor 行为导致的,它将颜色样式应用在所选文本或插入 <span> 元素来承载样式。

解决方案一:自定义按钮并覆写 BGColor 功能

可以通过创建自定义的插件或直接覆盖默认的 BGColor 行为来实现这个需求。我们创建一个新命令来专门处理表格单元格的背景颜色,并禁用原有的 BGColor 逻辑。

操作步骤:

  1. 移除默认BGColor: 首先从toolbar的配置中移除原有的"BGColor"按钮。

  2. 注册自定义命令: 创建一个自定义命令来替代 BGColor,该命令能获取当前选中的单元格并应用背景颜色。

  3. 创建新按钮并绑定: 在toolbar中注册新按钮,将该按钮绑定到自定义的命令。

  4. 实现自定义背景色设置: 新命令的核心逻辑应判断当前是否选中了 <td> 元素,如果选中,则将选定的颜色应用到该元素的 style.backgroundColor 属性。

代码示例:

module.exports.buildEditor = function (element, readonly) {
  window.CKEDITOR.config.forcePasteAsPlainText = true;

  var editor = AlloyEditor.editable(element, {
      readOnly: readonly,
      toolbars: {
          add: {
              tabIndex: 2,
              buttons: ['reference', 'table', 'image']
          },
          styles: {
              tabIndex: 1,
              selections: [{
                      name: 'text',
                      buttons: [
                          "Copy",
                          "Paste",
                          "PasteFromWord",
                          //"BGColor"  Remove the default BGColor button
                      ],
                      test: AlloyEditor.SelectionTest.text
                  },
                  {
                      name: 'link',
                      buttons: ['linkEdit'],
                      test: AlloyEditor.SelectionTest.link
                  },
                  {
                      name: 'image',
                      buttons: ['imageLeft', 'imageCenter', 'imageRight'],
                      test: AlloyEditor.SelectionTest.image
                  },
                  {
                      name: 'table',
                      buttons: [{
                          name: 'styles',
                          cfg: {
                              styles: [{
                                      name: 'Normal Table',
                                      style: {
                                          element: 'table',
                                          attributes: {
                                              'class': 'table'
                                          }
                                      }
                                  },
                                  {
                                      name: 'Striped Table',
                                      style: {
                                          element: 'table',
                                          attributes: {
                                              'class': 'table table-striped'
                                          }
                                      }
                                  },
                                  {
                                      name: 'Bordered Table',
                                      style: {
                                          element: 'table',
                                          attributes: {
                                              'class': 'table table-bordered'
                                          }
                                      }
                                  },
                                  {
                                      name: 'Condensed Table',
                                      style: {
                                          element: 'table',
                                          attributes: {
                                              'class': 'table table-condensed'
                                          }
                                      }
                                  },
                                  {
                                        name: 'BG Cell Strong Cyan',
                                        style: {
                                            element: 'td',
                                            styles: {
                                                'background-color': '#1ABC9C'
                                            }
                                        }
                                    }

                              ]
                          }
                      }, 'tableHeading', 'tableRow', 'tableColumn', 'tableCell', 'tableRemove',  'customBGColor' /* 新增自定义按钮*/  ],
                      getArrowBoxClasses: AlloyEditor.SelectionGetArrowBoxClasses.table,
                      setPosition: customSelectionSetPosition,
                      test: AlloyEditor.SelectionTest.table
                  }
              ]
          }
      }
  });

    // Register custom command for BGColor on td
  editor.on('instanceReady', function(){
      const editorInstance = editor.get('instance');

     editorInstance.addCommand('customBGColor', {
         exec: function (editor) {
            var selection = editor.getSelection();
            var selectedElement = selection.getStartElement();
            if(selectedElement && selectedElement.getName() === 'td'){
                const color = prompt('Enter a color value (e.g., red, #ff0000, rgba(255,0,0,0.5))'); // 用户交互, 可以改为 colorpicker

                if(color) {
                 selectedElement.setStyle('background-color', color) ;
                }
            } else{
                alert('Please select a table cell')
            }


         }
       });

       editorInstance.ui.addButton('customBGColor', {
        label: 'BG Cell Color',
        command: 'customBGColor',
       // icon: '' You can also set custom icons here
        });

     })


  return editor;
};

这个示例会给表格工具栏添加一个名为“BG Cell Color”的按钮。点击该按钮,将提示用户输入颜色值。 只有当用户选择的是表格 <td> 元素时,才会应用背景颜色。此代码提供基础功能,颜色选择可通过其他插件,如颜色选择器组件来进一步增强。
关键代码解释

  • 移除'BGColor': 从 buttons 数组中删除 BGColor, 阻止默认的文字背景颜色效果
  • 注册customBGColor 命令: editorInstance.addCommand 注册一个新的命令
    • 命令内部获取当前的选中的开始节点 getStartElement 并判断是否为<td> 节点.
    • 当选中的节点是<td> , 弹出一个prompt 窗口让用户输入颜色值. 这里可以使用 color picker 来代替
    • 设置颜色, 使用 setStyle 来直接修改样式
  • editorInstance.ui.addButton 为新增的命令注册一个按钮,添加 label 和绑定 command.

安全注意事项

用户提供的颜色值可以接受各种输入格式(如 red, #ff0000rgb(255,0,0)),这在安全性方面可能存在一些风险。要避免样式注入攻击(XSS)可以对用户输入做如下处理:

  • 使用浏览器内置方法来解析颜色值,验证是否为合法的颜色格式,或者,
  • 使用成熟的色彩库进行解析,例如Color.js 或 chroma.js 等
  • 对传入的 CSS 属性值做一些基本的转义

这些方式确保输入值不含有可执行代码,并保障页面的安全性。

解决方案二:使用已有的插件

AlloyEditor 和 CKEditor 具有插件机制。如果需求更复杂或想利用社区的解决方案,可以查找是否有现有插件实现了 <td> 单元格颜色选择功能。一些插件可以直接集成,无需从零开发。

使用插件通常更为快速,但应注意选择维护良好,有良好口碑的插件,并进行充分测试,确保符合项目要求。

本文提供的第一种方案可直接处理此需求,可以根据需求考虑是否使用现成的插件或者直接基于第一种方法进行扩展.