You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否将TinyMCE 6的Quick Insert工具栏自定义为点击展开的图标按钮?

实现TinyMCE 6自定义点击触发的Quick Insert按钮

核心思路

  1. 禁用默认的Quick Insert工具栏,避免与自定义组件冲突
  2. 自定义一个浮动按钮,仅在用户点击空行或回车新建空行时显示
  3. 点击按钮时弹出包含插入选项的自定义菜单,调用TinyMCE内置命令完成操作

具体实现代码

tinymce.init({
  selector: '#editor',
  quickbars_insert_toolbar: false, // 关闭默认quickbar
  toolbar: 'undo redo bold italic', // 保留原有工具栏配置
  setup: function(editor) {
    // 定义插入菜单的选项列表
    const insertOptions = [
      { text: '插入图片', onclick: () => editor.execCommand('mceImage') },
      { text: '插入链接', onclick: () => editor.execCommand('mceLink') },
      { text: '插入表格', onclick: () => editor.execCommand('mceTableInsert') },
      { text: '插入代码块', onclick: () => editor.execCommand('mceCodeBlock') }
    ];

    // 创建自定义快速插入按钮
    const quickInsertBtn = editor.ui.factory.create({
      type: 'button',
      icon: 'plus', // 使用内置加号图标,可替换为其他内置图标或自定义CSS类
      tooltip: '快速插入内容',
      onclick: () => {
        // 注册临时上下文菜单并触发
        editor.ui.registry.addContextMenu('customQuickInsert', {
          update: () => insertOptions
        });
        editor.execCommand('mceContextMenu', false, 'customQuickInsert');
      }
    });

    // 初始化按钮:添加到编辑器容器并默认隐藏
    editor.on('PostRender', () => {
      const btnContainer = document.createElement('div');
      editor.getContainer().appendChild(btnContainer);
      quickInsertBtn.renderTo(btnContainer);
      quickInsertBtn.hide();
    });

    // 判断当前选区是否在空行(空段落)中
    const isEmptyLine = () => {
      const selectedNode = editor.selection.getNode();
      const isEmptyPara = selectedNode.tagName === 'P' && 
                          (selectedNode.textContent.trim() === '' || 
                           selectedNode.innerHTML.trim() === '<br data-mce-bogus="1">');
      return isEmptyPara;
    };

    // 更新按钮的显示状态和位置
    const updateBtnState = () => {
      if (!isEmptyLine()) {
        quickInsertBtn.hide();
        return;
      }

      // 获取选区位置,定位按钮到选区上方居中位置
      const selectionRect = editor.selection.getRng().getBoundingClientRect();
      const editorRect = editor.getContainer().getBoundingClientRect();
      const btnEl = quickInsertBtn.getEl();

      btnEl.style.position = 'absolute';
      btnEl.style.left = `${selectionRect.left - editorRect.left + selectionRect.width / 2 - 16}px`;
      btnEl.style.top = `${selectionRect.top - editorRect.top - 32}px`;
      btnEl.style.zIndex = 1000; // 确保按钮在最上层
      quickInsertBtn.show();
    };

    // 绑定触发事件:点击编辑器、节点变化、回车
    editor.on('Click NodeChange KeyUp', (e) => {
      if (e.type === 'KeyUp' && e.keyCode !== 13) return; // 仅处理回车键触发的空行
      updateBtnState();
    });

    // 点击编辑器其他区域时隐藏按钮
    editor.getBody().addEventListener('click', (e) => {
      if (!quickInsertBtn.getEl().contains(e.target)) {
        quickInsertBtn.hide();
      }
    });
  }
});

关键细节说明

  • 禁用默认quickbar:通过quickbars_insert_toolbar: false完全关闭默认功能,避免冲突
  • 按钮定位:利用选区的DOM坐标计算按钮位置,确保显示在空行上方的合理位置
  • 菜单触发:通过临时注册上下文菜单并调用mceContextMenu命令实现点击按钮弹出菜单的效果
  • 空行判断:针对TinyMCE默认生成的空段落(含<br data-mce-bogus="1">)做兼容判断
  • 扩展性:可直接在insertOptions数组中添加更多插入选项,调用对应的TinyMCE内置命令即可

样式自定义(可选)

如果需要调整按钮的外观,可通过CSS修改:

.tox-tbtn--icon.plus {
  /* 自定义按钮样式 */
  background-color: #f5f5f5;
  border-radius: 50%;
}

.tox-menu--context {
  /* 自定义菜单样式 */
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.15);
}

内容的提问来源于stack exchange,提问作者TidyBars

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 14:36:27