【问题标题】:Adding a new item on google document's context menu using chrome extension使用 chrome 扩展在谷歌文档的上下文菜单上添加新项目
【发布时间】:2020-02-01 08:36:14
【问题描述】:

现在我正在尝试制作一个控制谷歌文档的谷歌浏览器扩展。 我想使用 chrome 扩展在谷歌文档的上下文菜单中添加一个新项目。 当您在 google 文档上单击鼠标右键时,您可以看到上下文菜单。 使用 chrome 扩展,我想在该菜单上添加一个新项目,如“订阅”。 我该怎么做?

【问题讨论】:

  • 欢迎来到 Stack Overflow!请阅读help pages,获取SO tour,了解how to ask good questions,以及此question checklist。另请了解如何创建minimal reproducible example。如果您在编程论坛上需要帮助,最好在文档的上下文中发布代码和/或提出您的问题:)
  • 这是一个标准的 DOM 操作任务,没有专门的扩展 API。假设您了解 JavaScript 和 DOM,只需声明一个带有“contextmenu”事件侦听器的 content script,在其中使用 MutationObserver 等待菜单出现并添加您的 DOM 元素,并使用点击侦听器来执行您想要的操作。跨度>

标签: google-chrome-extension contextmenu google-docs google-docs-api right-click


【解决方案1】:

按照 wOxxOm 的说明进行操作:

首先,我们需要建立一个内容脚本,将以下代码添加到您的 manifest.json 中

  "permissions": [
    "https://docs.google.com/*"
  ],
  "content_scripts": [
    {
      "matches": [
        "https://docs.google.com/*"
      ],
      "js": [
        "scripts/content.js"
      ],
      "run_at": "document_end"
    }
  ],

然后在你的 content.js 中

function filterHiddenElements(nodeList) {
    return Array.from(nodeList).filter(v=>v.style.display !== "none" && !["hidden", "collapse"].includes(v.style.visibility));
}

function getContextMenuElement() {
    // there are many divs that match the css selector, but only one will be visible.
    const contextMenus = filterHiddenElements(document.querySelectorAll(".goog-menu.goog-menu-vertical.apps-menu-hide-mnemonics"));
    // return only the visible ones
    return contextMenus.length > 0 ? contextMenus[0] : null;
}

function contextMenuEventHandler() {
    const id = "custom-context-menu-id";
    const customContextMenuName = "Custom Name";
    const customContextMenuHint = "Custom Hint";

    const contextMenuElement = getContextMenuElement();
    if (contextMenuElement) {
        const preExisting = document.querySelector("#" + id);
        if (preExisting) {
            // we need to remove the preExisting element because google docs removes all elements and recreates them.
            // it will remain at the top then next time if we don't do this
            preExisting.parentElement.removeChild(preExisting);
        }
        const separators = filterHiddenElements(contextMenuElement.querySelectorAll(".apps-hoverable-menu-separator-container"));
        if (separators.length) {
            // you can also put a custom icon in place of .docs-icon-img-container
            const innerHTML = `
                  <div class="goog-menuitem-content">
                      <div class="docs-icon goog-inline-block goog-menuitem-icon" aria-hidden="true">
                          <div class="docs-icon-img-container docs-icon-img docs-icon-cut">
                          </div>
                      </div>
                      <span class="goog-menuitem-label">
                        ${customContextMenuName}
                      </span>
                      <span class="goog-menuitem-accel" aria-label="⌘X">
                        ${customContextMenuHint}
                      </span>
                  </div>`;
            // this can't be HTML text because it will handle the events like hover and click
            const div = document.createElement("div");
            div.innerHTML = innerHTML;
            div.className = "goog-menuitem apps-menuitem";
            div.id = id;
            div.setAttribute("role", "menuitem");

            // hover events
            div.addEventListener("mouseenter", e=>{
                e.target.classList.add("goog-menuitem-highlight");
            }
            );
            div.addEventListener("mouseleave", e=>{
                e.target.classList.remove("goog-menuitem-highlight");
            }
            );

            // click event
            div.addEventListener("click", onClickEventHandler);
            // put it above the first separator
            separators[0].parentElement.insertBefore(div, separators[0]);
        }
    } else {
        console.log("Could not find context menu");
    }
}

function onClickEventHandler(e) {
    alert(`#${e.target.id} has been clicked!`);
}

document.body.addEventListener('contextmenu', contextMenuEventHandler);

免责声明:因为这不遵循官方 API,所以这是一种非常 hacky 的方式,很可能会被破坏。但是,如果遇到问题,修复应该不会那么难。它从 2021 年 5 月开始工作。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2019-01-11
  • 1970-01-01
  • 1970-01-01
  • 2015-05-25
  • 1970-01-01
  • 1970-01-01
  • 2017-05-14
  • 1970-01-01
相关资源
最近更新 更多