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

如何点击菜单按钮向Trix编辑器插入文本?含视频嵌入与模态框需求

解决Trix编辑器自定义视频插入按钮及相关问题

一、修正insertString使用问题,明确正确用法

你当前在textAttributes.parser里尝试插入内容的思路是错的——textAttributes是用来定义文本格式(如颜色、加粗)的配置项,根本不是用来处理自定义元素插入的。要实现内容插入,得在按钮的点击回调里操作编辑器实例。

获取编辑器实例的正确方式

可以通过Trix的trix-initialize事件提前保存当前编辑器实例,方便后续调用:

let trixEditorInstance;
document.addEventListener("trix-initialize", function(event) {
  trixEditorInstance = event.target.editor;
});

二、实现点击按钮弹出模态框输入URL

1. 先添加模态框的HTML结构

<!-- 视频插入模态框 -->
<div id="videoModal" style="display:none; position:fixed; top:50%; left:50%; transform:translate(-50%,-50%); padding:24px; background:#fff; border-radius:8px; box-shadow:0 2px 12px rgba(0,0,0,0.15); z-index:1000;">
  <h3 style="margin-top:0; font-size:16px;">插入视频</h3>
  <label style="display:block; margin:12px 0 8px;">YouTube/Vimeo视频URL:</label>
  <input type="text" id="videoUrlInput" style="width:100%; padding:8px; border:1px solid #ddd; border-radius:4px;" placeholder="示例:https://www.youtube.com/watch?v=abc123">
  <div style="display:flex; gap:8px; margin-top:16px; justify-content:flex-end;">
    <button id="closeModalBtn" style="padding:8px 16px; border:1px solid #ddd; border-radius:4px; background:#fff; cursor:pointer;">取消</button>
    <button id="insertVideoBtn" style="padding:8px 16px; border:none; border-radius:4px; background:#007bff; color:#fff; cursor:pointer;">插入</button>
  </div>
</div>
<!-- 模态框遮罩层 -->
<div id="modalOverlay" style="display:none; position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.5); z-index:999;"></div>

2. 给Trix工具栏添加自定义按钮

通过trix-toolbar-initialize事件把按钮插入到工具栏:

document.addEventListener("trix-toolbar-initialize", function(event) {
  const toolbar = event.target;
  // 创建插入视频按钮
  const videoBtn = document.createElement("button");
  videoBtn.type = "button";
  videoBtn.textContent = "插入视频";
  videoBtn.classList.add("trix-button");
  videoBtn.addEventListener("click", () => {
    // 打开模态框
    document.getElementById("videoModal").style.display = "block";
    document.getElementById("modalOverlay").style.display = "block";
    document.getElementById("videoUrlInput").focus();
  });
  // 把按钮添加到文本工具组的后面
  const textToolsGroup = toolbar.querySelector(".trix-button-group--text-tools");
  textToolsGroup.insertAdjacentElement("afterend", videoBtn);
});

3. 处理URL解析、ID加密及插入逻辑

// 从URL中提取YouTube/Vimeo视频ID
function getVideoId(url) {
  let videoId = null;
  // 匹配YouTube的各种URL格式
  const youtubeRegex = /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/;
  const youtubeMatch = url.match(youtubeRegex);
  if (youtubeMatch) videoId = youtubeMatch[1];
  
  // 匹配Vimeo的URL格式
  const vimeoRegex = /vimeo\.com\/(\d+)/;
  const vimeoMatch = url.match(vimeoRegex);
  if (vimeoMatch) videoId = vimeoMatch[1];
  
  return videoId;
}

// 视频ID加密函数(替换成你实际的加密逻辑)
function encryptVideoId(id) {
  // 示例:用Base64简单编码,实际请用安全加密算法(如AES)
  return btoa(id);
}

// 插入视频元素到编辑器
document.getElementById("insertVideoBtn").addEventListener("click", function() {
  const input = document.getElementById("videoUrlInput");
  const url = input.value.trim();
  if (!url) return;
  
  const videoId = getVideoId(url);
  if (!videoId) {
    alert("请输入有效的YouTube或Vimeo视频URL");
    return;
  }
  
  const encryptedId = encryptVideoId(videoId);
  // 创建自定义视频占位元素(可根据需求改成iframe或其他结构)
  const videoElement = document.createElement("div");
  videoElement.className = "trix-video-embed";
  videoElement.dataset.encryptedId = encryptedId;
  videoElement.style.padding = "12px";
  videoElement.style.border = "1px dashed #ccc";
  videoElement.style.borderRadius = "4px";
  videoElement.innerHTML = `<p>已插入视频(加密ID:${encryptedId})</p>`;
  
  // 插入到编辑器当前光标位置
  if (trixEditorInstance) {
    trixEditorInstance.focus();
    trixEditorInstance.insertHTML(videoElement.outerHTML);
  }
  
  // 关闭模态框并清空输入
  document.getElementById("videoModal").style.display = "none";
  document.getElementById("modalOverlay").style.display = "none";
  input.value = "";
});

// 关闭模态框
document.getElementById("closeModalBtn").addEventListener("click", function() {
  document.getElementById("videoModal").style.display = "none";
  document.getElementById("modalOverlay").style.display = "none";
});

三、关键配置补充

Trix默认会过滤部分HTML元素和属性,要保留自定义的data-encrypted-id属性,需要添加如下配置:

// 允许自定义元素和属性
Trix.config.allowedElements.push("div");
Trix.config.allowedAttributes["data-encrypted-id"] = true;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 21:13:22