Greasemonkey的隐藏功能
人们在其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()。