如何创建一个用户脚本,在网页上创建一个按钮,单击该按钮时,为该用户脚本运行 GM_registerMenuCommand?

问题描述 投票:0回答:1

我有一个用户脚本,其中包含

GM_registerMenuCommand('Render LaTeX', () => {
(等等),该用户脚本的一部分仅在通过从浏览器栏中选择 ViolentMonkey 插件手动触发时运行,然后单击标有“Render LaTeX”的按钮。

我想向该用户脚本设置为匹配的网页添加一个按钮,单击该按钮即可执行上述操作。我只是不知道该怎么做。我能找到的关于按钮的唯一信息是here

我尝试修改链接问题的第二个答案中提供的代码。我能够调整文本和位置,但我不知道如何使按钮执行我想要的操作或更改其外观以更好地适应它正在运行的网站。

// ==UserScript==
// @name        TeX Button
// @namespace   all
// @match     https://mail.google.com/mail/*
// @version     1
// @grant       none
// ==/UserScript==

(function(){
    'use strict'

  window.addEventListener('load', () => {
    addButton('TeX', selectReadFn)
    })

    function addButton(text, onclick, cssObj) {
        cssObj = cssObj || {position: 'absolute', bottom: '92.375%', left:'19.35%', 'z-index': 3}
        let button = document.createElement('button'), btnStyle = button.style
        document.body.appendChild(button)
        button.innerHTML = text
        button.onclick = onclick
        Object.keys(cssObj).forEach(key => btnStyle[key] = cssObj[key])
        return button
    }

    function selectReadFn() {
        [...document.getElementsByClassName('MN')].filter(isRead).forEach(element => element.click())
    }

    function isRead(element) {
        childs = element.parentElement.parentElement.parentElement.getElementsByClassName('G3')
        return ![...childs].some(e => e.innerText.search(/unread/i)!==-1)
    }

}())

下面是我提到的 GM_registerMenuCommand 的代码。我不知道这是否真的需要参考,但我想分享一下也没什么坏处。

// ==UserScript==
// @name        LaTeX for Gmail v2.1
// @namespace   Violentmonkey Scripts
// @match       https://mail.google.com/mail/*
// @grant       GM_registerMenuCommand
// @grant       GM_addElement
// @require     https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.js
// @version     2.1
// @author      /u/MistralMireille & /u/LoganJFisher
// @description Adds support for TeXTheWorld delimiters to Gmail, and an register menu to activate rendering using traditional LaTeX delimiters
// ==/UserScript==

GM_addElement('link', {
  rel: "stylesheet",
  src: "https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.css"
});

function renderLatex() {
  document.querySelectorAll("#\\:1 > .nH .aHU.hx > [role='list'] > [role='listitem'][aria-expanded='true']").forEach(message => {
let subportion = message.querySelector("[data-message-id]"); // need to select a subportion of [role='listitem'] to stop rendering latex in the textinput
if(subportion) {
  message = subportion;
}
message.innerHTML = message.innerHTML.replace(/\[;(.+?);\]/g, (match, p1) => {
  return katex.renderToString(p1, { throwOnError: false, output: "mathml", displayMode: false });
});
message.innerHTML = message.innerHTML.replace(/\[\(;(.+?);\)\]/g, (match, p1) => {
  return katex.renderToString(p1, { throwOnError: false, output: "mathml", displayMode: true });
});
  });
}

GM_registerMenuCommand('Render LaTeX', () => {
  document.querySelectorAll("#\\:1 > .nH .aHU.hx > [role='list'] > [role='listitem'][aria-expanded='true']").forEach(message => {
    let subportion = message.querySelector("[data-message-id]"); // need to select a subportion of [role='listitem'] to stop rendering latex in the textinput
    if(subportion) {
      message = subportion;
    }
    message.innerHTML = message.innerHTML.replace(/\\\[(.+?)\\\]/g, (match, p1) => {
      return katex.renderToString(p1, { throwOnError: false, output: "mathml", displayMode: true });
    });
    message.innerHTML = message.innerHTML.replace(/\$\$(.+?)\$\$/g, (match, p1) => {
      return katex.renderToString(p1, { throwOnError: false, output: "mathml", displayMode: true });
    });
    //message.innerHTML = message.innerHTML.replace(/\\begin\{displaymath}(.+?)\\end\{displaymath}/g, (match, p1) => {
      //return katex.renderToString(p1, { throwOnError: false, output: "mathml", displayMode: true });
    //});
    //message.innerHTML = message.innerHTML.replace(/\\begin\{equation}(.+?)\\end\{equation}/g, (match, p1) => {
      //return katex.renderToString(p1, { throwOnError: false, output: "mathml", displayMode: true });
    //});
    message.innerHTML = message.innerHTML.replace(/\\\((.+?)\\\)/g, (match, p1) => {
      return katex.renderToString(p1, { throwOnError: false, output: "mathml", displayMode: false });
    });
    message.innerHTML = message.innerHTML.replace(/\$(.+?)\$/g, (match, p1) => {
      return katex.renderToString(p1, { throwOnError: false, output: "mathml", displayMode: false });
    });
    message.innerHTML = message.innerHTML.replace(/\\begin\{math}(.+?)\\end\{math}/g, (match, p1) => {
      return katex.renderToString(p1, { throwOnError: false, output: "mathml", displayMode: false });
    });
  });
});

function waitForElement(queryString) {
  let count = 0;
  return new Promise((resolve, reject) => {
let findInterval = setInterval(() => {
  let waitElement = document.querySelector(queryString);
  if(waitElement) {
    clearInterval(findInterval);
    resolve(waitElement);
  } else if(count > 20) {
    clearInterval(findInterval);
    reject(`Couldn't find waitElement: ${queryString}.`);
  } else {
    count += 1;
  }
}, 100);
  });
}

window.addEventListener('load', () => {
  waitForElement("#\\:1 > .nH").then(messagesDiv => {
(new MutationObserver((mutationRecords, observerElement) => {
  mutationRecords.forEach(mutationRecord => {
    switch(mutationRecord.type) {
      case "childList":
        mutationRecord.addedNodes.forEach(addedNode => {
          console.log(addedNode);
          if(addedNode.tagName === "DIV" && addedNode.getAttribute("role") === "listitem") {
            renderLatex();
          }
        });
        break;
      case "attributes":
        if(mutationRecord.target.tagName === "DIV" && mutationRecord.target.getAttribute("role") === "listitem" && mutationRecord.attributeName === "aria-expanded") {
          renderLatex();
        }
    }
  });
})).observe(messagesDiv, { childList: true, subtree: true, attributes: true, attributeOldValue: true});
  });
});
javascript button userscripts violentmonkey
1个回答
0
投票

这是修改后的脚本,添加一个按钮和一个 menuCommand,它们都会调用

renderLatex
:

// ==UserScript==
// @name        LaTeX for Gmail v2.1
// @namespace   Violentmonkey Scripts
// @match       https://mail.google.com/mail/*
// @grant       GM_registerMenuCommand
// @grant       GM_addElement
// @require     https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.js
// @version     2.1
// @author      /u/MistralMireille & /u/LoganJFisher
// @description Adds support for TeXTheWorld delimiters to Gmail, and an register menu to activate rendering using traditional LaTeX delimiters
// @noframes
// ==/UserScript==

/* globals katex */

GM_addElement('link', {
    rel: "stylesheet",
    src: "https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.css"
});

function renderLatex() {
    console.log('rendering latex...');
    const messages = document.querySelectorAll("#\\:1 > .nH .aHU.hx > [role='list'] > [role='listitem'][aria-expanded='true']");
    messages.forEach(message => {
        let subportion = message.querySelector("[data-message-id]"); // need to select a subportion of [role='listitem'] to stop rendering latex in the textinput
        if(subportion) {
            message = subportion;
        }
        message.innerHTML = message.innerHTML.replace(/\[;(.+?);\]/g, (match, p1) => {
            return katex.renderToString(p1, { throwOnError: false, output: "mathml", displayMode: false });
        });
        message.innerHTML = message.innerHTML.replace(/\[\(;(.+?);\)\]/g, (match, p1) => {
            return katex.renderToString(p1, { throwOnError: false, output: "mathml", displayMode: true });
        });
    });
}

function waitForElement(queryString) {
    let count = 0;
    return new Promise((resolve, reject) => {
        let findInterval = setInterval(() => {
            let waitElement = document.querySelector(queryString);
            if(waitElement) {
                clearInterval(findInterval);
                resolve(waitElement);
            } else if(count > 20) {
                clearInterval(findInterval);
                reject(`Couldn't find waitElement: ${queryString}.`);
            } else {
                count += 1;
            }
        }, 100);
    });
}

window.addEventListener('load', () => {
    waitForElement("#\\:1 > .nH").then(messagesDiv => {
        addButton(messagesDiv);

        (new MutationObserver((mutationRecords, observerElement) => {
            mutationRecords.forEach(mutationRecord => {
                switch(mutationRecord.type) {
                    case "childList":
                        mutationRecord.addedNodes.forEach(addedNode => {
                            console.log(addedNode);
                            if(addedNode.tagName === "DIV" && addedNode.getAttribute("role") === "listitem") {
                                renderLatex();
                            }
                        });
                        break;
                    case "attributes":
                        if(mutationRecord.target.tagName === "DIV" && mutationRecord.target.getAttribute("role") === "listitem" && mutationRecord.attributeName === "aria-expanded") {
                            renderLatex();
                        }
                }
            });
        })).observe(messagesDiv, { childList: true, subtree: true, attributes: true, attributeOldValue: true});
    });
});

function addButton(parent) {
    GM_registerMenuCommand('Render LaTeX', renderLatex);
    GM_addElement(parent, 'button', {
        id: 'LatexButton',
        textContent: 'RENDER LATEX'
    });

    parent.querySelector('#LatexButton').addEventListener('click', renderLatex);
}

*您可以使用

GM_addStyle(css)
轻松为此按钮添加样式。

© www.soinside.com 2019 - 2024. All rights reserved.