Greasemonkey的隐藏功能

时间:2020-03-06 14:36:01  来源:igfitidea点击:

人们在其Greasemonkey脚本中使用了哪些鲜为人知但有用的功能和技术?

(请每个答案仅提供一项功能。)

类似线程:

  • JavaScript的隐藏功能
  • Java的隐藏功能
  • C ++的隐藏功能
  • C#的隐藏功能

解决方案

可以通过GM_setValue(keyname,value)将其存储为mozilla首选项值,从而在页面加载期间保留数据。

这是一个简单的示例,可以计算给定浏览器执行脚本的次数:

var od = GM_getValue("odometer", 0);
od++;
GM_setValue("odometer", od);
GM_log("odometer=" + od);

GM值类似于cookie,因为cookie值只能由原始域访问,而GM值只能由创建它们的脚本访问。

匿名统计

假设我们具有提供访问日志的基本托管服务,则可以轻松跟踪脚本的基本使用情况统计信息。

  • 将gif文件(例如徽标图像)放置在我们自己的网站上。
  • 在脚本中,将img元素添加到引用gif的页面上:
var img = document.createElement("img");
img.src = "http://mysite.com/logo.gif";
document.body.appendChild(img);

现在,每次用户执行脚本时,托管服务都会在该gif文件上注册一个匹配项。

要跟踪多个脚本,请为每个脚本使用不同的gif文件。或者在URL中添加某种区分参数(例如:http://mysite.com/logo.gif?zippyver = 1.0`)。

Greasemonkey脚本通常需要在页面上搜索内容。与其深入研究DOM,不如尝试使用XPath定位感兴趣的节点。通过document.evaluate()方法,我们可以提供XPath表达式,并返回匹配节点的集合。这是一个很好的入门指南。例如,这是我编写的脚本,该脚本使phpBB3帖子中的链接在新选项卡(默认外观)中打开:

// ==UserScript==
// @name           New Tab in phpBB3
// @namespace      http://robert.walkertribe.com/
// @description    Makes links in posts in phpBB3 boards open new tabs.
// ==/UserScript==

var newWin = function(ev) {
    var win = window.open(ev.target.href);
    if (win) ev.preventDefault();
};

var links = document.evaluate(
        "//div[@class='content']//a[not(@onclick) and not(@href='#')]",
        document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);

for (var i = 0; i < links.snapshotLength; i++) {
    var link = links.snapshotItem(i);
    link.addEventListener("click", newWin, true);
}

代码中使用的XPath表达式标识所有1个元素,这些元素1)没有" onclick"属性; 2)" href"属性未设置为"#"; 3)位于div中s,其"类别"属性设置为"内容"。

可以使脚本标头值(@ name,@ description,@ version等)可检索。这比在脚本的多个位置保持相同的常量值更好。

请参阅从脚本中访问Greasemonkey元数据?

即使我们没有位置通过数据URI托管文件,脚本也可以将图形添加到页面中。

例如,这是一个小按钮图形:

var button = document.createElement("img");
button.src = "data:image/gif;base64,"
    + "R0lGODlhEAAQAKEDAAAA/wAAAMzMzP///yH5BAEAAAMALAAAAAAQABAAAAIhnI+pywOtwINHTmpvy3rx"
    + "nnABlAUCKZkYoGItJZzUTCMFACH+H09wdGltaXplZCBieSBVbGVhZCBTbWFydFNhdmVyIQAAOw=="
somenode.appendChild(button);

这是一个在线图像编码器。

以及有关数据URI标准的维基百科文章。

一种有用的XPath技术是指定相对于我们已经找到的节点的匹配。作为stackoverflow的人为例子:

// first we got the username link at the top of the page
var hdrdiv = document.evaluate(
    "//div[@id='headerlinks']/a[1]", document, null,
    XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

// now we can retrieve text that follows it, (user's reputation score)
// (note that hdrdiv is now the contextNode argument, rather than document)
var reptext = document.evaluate(
    "following-sibling::span", hdrdiv, null,
    XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

alert("Reputation Score: " + reptext.textContent);

我们可以在相对于contextNode,祖先,后代,上一个,下一个的任何方向进行匹配。
这是一个有用的
XPath参考。

GreaseMonkey脚本在DOM准备就绪时运行,因此我们无需添加onload事件,只需在GreaseMonkey脚本中立即开始操作DOM。

==UserScript==
...
@require http://ajax.googleapis.com/ajax/framework-of-your/choice.js
==/UserScript==

GM_setValue通常只存储32位整数,字符串和布尔值,但是我们可以利用uneval()方法(以及稍后的eval()检索)来存储任何对象。如果我们要处理的是纯JSON值(而不是JavaScript对象),请使用JSON.stringify进行存储,并使用JSON.parse进行检索;这将更快,更安全。

var foo={people:['Bob','George','Smith','Grognak the Destroyer'],pie:true};
GM_setValue('myVeryOwnFoo',uneval(foo));
var fooReborn=eval(GM_getValue('myVeryOwnFoo','new Object()'));
GM_log('People: '+fooReborn.people+'   Pie:'+fooReborn.pie);

在这种情况下,我倾向于使用" new Object()"作为默认值,但是我们也可以使用"({}}"。请记住," {}"的计算结果是字符串,而不是对象。与往常一样,请谨慎使用eval()。