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

如何通过Chrome扩展移除嵌套iframe中video.js的按键事件监听

解决Chrome扩展中video.js数字热键劫持输入框的问题

我开发了一款Chrome扩展,做了个视频覆盖层,支持通过快捷键激活、输入时间戳跳转视频。但遇到卡点:video.js播放器的数字热键会劫持输入框的数字输入,直接触发视频跳转到对应进度,导致没法正常输入时间戳。

已知信息

  • 视频播放器嵌套在id为player的iframe里
  • 劫持输入的keydown事件监听来自video.js库
  • 手动在控制台移除该事件监听后,扩展功能完全正常

已尝试但无效的方法

  • 给元素添加带event.stopPropagation()和event.preventDefault()的keydown监听,结果直接禁用了所有视频相关按键,连覆盖层都打不开
  • 尝试用第二次快捷键移除添加的监听,但视频毫无反应,还是没法输入数字,仿佛第一次加的监听根本没生效
  • 想在content.js里通过contentDocument和contentWindow访问iframe内元素,但扩展没权限,涉及CORS问题,兼容性极差
  • 尝试把焦点从视频切到覆盖层,不管是快捷键触发还是扩展加载时执行都没用

核心代码片段(原尝试禁用监听的部分)

function handleKeydown(event) {
  const isCtrlKey = OSName === "Mac/iOS" ? event.metaKey : event.ctrlKey;
  const isAltKey = OSName === "Mac/iOS" ? event.ctrlKey : event.altKey;

  if (isCtrlKey && isAltKey) {
    if (
      window.location.href.includes("watch") ||
      window.location.href.includes("open") ||
      window.location.href.includes("redbarradio")
    ) {
      // document.activeElement.blur()
      // console.log(document.activeElement)

      overlayVisibleBool.value = !overlayVisibleBool.value;

      const overlayDiv = document.getElementById("rr_overlay");

      if (!overlayDiv) {
        appendOverlay();
        appendListeners();
        appendTippy();
      }

      if (!spotifyOverlayBackground) {
        spotifyOverlayBackground = true;
      }

      toggleOverlay();
      document.getElementById("timeInput").value = "";

      let cancelIt = (event) => {
        event.preventDefault()
        event.stopPropagation()
      }

      let player = document.getElementById("player")
      console.log(player)
      console.log("overlayBool: ", overlayVisibleBool.value)
      // if (overlayVisibleBool.value) {
      //   player.addEventListener("keydown", cancelIt, true)
      //   console.log("Keydown cancelled.")
      // } 
      // else {
      //   player.removeEventListener("keydown", cancelIt, true)
      //   console.log("Keydown enabled.")
      // }
    }
  }
}

document.addEventListener("keydown", handleKeydown);

补充定位

已确认问题根源是video.js的hotkeys库:当视频元素被选中时,该库会捕获数字输入,事件监听绑定在视频所在iframe的document元素上。


解决方案:针对性拦截iframe内的数字热键

因为事件绑定在iframe内部且跨域限制无法直接操作,我们可以通过Chrome扩展的content script注入到iframe内部来处理:

1. 修改manifest.json,允许注入到iframe

修改扩展的manifest.json,添加all_frames: true让content script可以注入到目标域名的所有iframe中:

"content_scripts": [
  {
    "matches": ["*://redbarradio.net/*", "其他目标域名"],
    "all_frames": true, // 关键配置:允许注入到iframe
    "js": ["iframe-content.js"]
  }
]

2. 创建iframe-content.js,在iframe内拦截事件

在iframe内部监听消息同步覆盖层状态,仅在覆盖层激活时拦截数字键:

let overlayActive = false;

// 接收主页面的覆盖层状态消息
window.addEventListener('message', (event) => {
  if (event.data?.type === 'TOGGLE_OVERLAY') {
    overlayActive = event.data.active;
  }
});

// 在捕获阶段优先拦截数字键事件
document.addEventListener('keydown', (event) => {
  // 仅当覆盖层激活且按下的是数字键时,阻止事件传递
  if (overlayActive && /^[0-9]$/.test(event.key)) {
    event.stopPropagation();
    event.preventDefault();
  }
}, true);

3. 主页面content.js同步状态到iframe

修改handleKeydown函数,在切换覆盖层时给iframe发送状态消息:

toggleOverlay();
document.getElementById("timeInput").value = "";

// 向iframe发送覆盖层状态
const playerIframe = document.getElementById('player');
if (playerIframe) {
  playerIframe.contentWindow.postMessage({
    type: 'TOGGLE_OVERLAY',
    active: overlayVisibleBool.value
  }, '*'); // 若知道iframe域名,替换为具体域名更安全
}

4. 强制输入框获取焦点

在toggleOverlay函数中,添加输入框自动聚焦逻辑,进一步降低视频捕获按键的概率:

function toggleOverlay() {
  const overlay = document.getElementById('rr_overlay');
  const timeInput = document.getElementById('timeInput');
  if (overlayVisibleBool.value) {
    overlay.style.display = 'block';
    // 延迟确保元素渲染完成后再聚焦
    setTimeout(() => timeInput.focus(), 100);
  } else {
    overlay.style.display = 'none';
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 01:12:18