3

我正在使用 JavaScript 为 Chrome 浏览器编写 Gmail 扩展程序。我正在尝试使用以下代码send从页面中获取按钮元素:Compose

SendButton  = document.getElementById('js_frame').contentDocument.getElementsByClassName('T-I J-J5-Ji Bq nS T-I-KE L3')[0];

但后来我不断收到一条消息,说typeof SendButton is undefined.

我该如何解决这个问题?

4

2 回答 2

1

您正在查看错误的文档。

Gmail#js_frame是一个不可见的框架,它负责非 UI 的东西(它的主体只包含<script>标签,仅供参考)。在您之前的问题中,我已经展示了如何获得正确的参考:

  • document.getElementById('canvas_frame').contentDocument如果存在
  • documentif#canvas_frame不存在,但js_frame存在。js_frame` 用于排除 Gmail 域中的非 Gmail 页面,例如帮助页面。

因此,在获得doc2(参见上一个答案)之后,您需要查询该文档上的元素:

// Paste declaration of doc2 from https://stackoverflow.com/a/14032326/938089
// And to get the button when available
if (doc2) {
    sendButton = doc2.getElementsByClassName('T-I J-J5-Ji Bq nS T-I-KE L3')[0];
}
于 2012-12-25T20:20:34.467 回答
0

您不能依赖发送按钮的 class 或 id 属性,因为它们在每次创建撰写字段时都会更改,甚至可能会因每个用户而更改。那么我们对按钮了解多少呢?

  • 它的 innerHTML 是“发送”(见脚注)
  • 它有一个值为“按钮”的角色属性
  • 它位于“撰写新消息”容器内,该容器还有其他标签,如“发件人”、“收件人”(见脚注 2)

有了这些信息,我们可以在原生 Javascript 中使用一个不错的 Xpath 查询来检索我们的按钮。

var xpath = '//div[@role="button" and text()="Send"]'
var query = document.evaluate(xpath, document, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
var button = query.iterateNext();

如果您将库用作 jQuery,请随时将其与 css 选择器[role="button"]和先前答案中提供的过滤器功能一起使用。

这可以通过将表信息附加为父级来改进,但这应该足够了(您可以在Developer Mozilla Introduction to Xpath中阅读更多相关信息)。希望答案能提供良好的性能。

更新: Gmail 似乎在某些事情上坚持使用某些类(类T-I J-J5-Ji似乎在旧版本和新版本之间共享)。但是,我不会使用它,如果其他开发人员偶然发现该类并且您仅通过该类获得按钮,则他或她无法理解您所获得的内容,特别是如果没有评论和变量名称不佳用来。

实际检索答案的解决方案使用看起来像这样的 CSS 查询选择器div > div > div > div > table div;出于同样的原因,我也不会使用它。另外,它让我想起了一个糟糕的描述性正则表达式。您不仅在为自己编码,而且还为自己可能对项目一无所知的未来编码。


脚注:或相当于用户的语言。我不确定是否所有用户都有英文版的 Gmail,但我不会做出这样的假设。如果我是你,我会创建一个字典,其中包含“发送”的最常见关键字的语言环境,并对其中的大多数进行迭代评估。您可以迭代的语言数量可能仅限于Gmail 支持的语言。

脚注 2:实际上,当您按下“撰写”时,它会添加标签“发件人”和“收件人”,但如果您不立即填写它们,它们就会消失,只显示一些带有 innerHTML 的“收件人”和“主题”的 div "

于 2012-12-25T20:55:23.217 回答