要修改任何页面匹配特定的模式(比如,“https://example.org/”)当它们加载后,使用page-mod模块。
要创建 page-mod,您必须指定两件事:
- 一个或多个 content scripts 运行,它们的工作将和网站内容进行交互
- 一个或多个 patterns 去匹配您要修改的页面的 URLs
content scripts为内容脚本,只能使用普通浏览器支持的 JS,不能使用 add-on 的API
这里有一个范例。内容脚本提供contentScript选项,地址样本提供include选项:
// Import the page-mod API var pageMod = require("sdk/page-mod"); // Create a page mod // It will run a script whenever a ".org" URL is loaded // The script replaces the page contents with a message pageMod.PageMod({ include: "*.org", contentScript: 'document.body.innerHTML = ' + ' "<h1>Page matches ruleset</h1>";' });
试试吧:
- 创建新的目录并转到该目录下
- 运行
cfx init
- 打开
lib/main.js
文件,添加以上的代码 - 运行
cfx run
- 在打开的浏览器窗口中打开 ietf.org
您将看到:
指定匹配模式
匹配模式使用 match-pattern
语法。您可以通过单一的匹配字符串,或者数组。
把内容脚本放在独立的文件中
在上面的范例中我们通过字符串来实现内容脚本。除非是用作简单的例子,通常情况下您应该将内容脚本放在独立文件中,这将使您的代码更易维护、调式和查看。
要这样做,您需要:
- 将脚本文件保存在 data 目录下
- 使用
contentScriptFile
选项代替contentScript 选项,并且指定脚本的路径
。路径用self.data.url()
取得
例如,如果我们将内容脚本保存在 data 目录下,命名为 my-script.js,在main.js中,我们应该这么写:
// Import the page-mod API var pageMod = require("sdk/page-mod"); // Import the self API var self = require("sdk/self"); // Create a page mod // It will run a script whenever a ".org" URL is loaded // The script replaces the page contents with a message pageMod.PageMod({ include: "*.org", contentScriptFile: self.data.url("my-script.js") });
加载多个Content Scripts
您可以加载更多脚本,且脚本可以相互交互。所以,您可以使用jQuery重写 my-script.js:
$("body").html("<h1>Page matches ruleset</h1>");
然后下载 jQuery 库到您的扩展开发目录的 data 目录下,并且将 jQuery 和 my-script 一起加载(确保先加载 jQuery 库):
// Import the page-mod API,加载 add-on 的 page-mod API var pageMod = require("sdk/page-mod"); // Import the self API, 加载 add-on 的 self API var self = require("sdk/self"); // Create a page mod // It will run a script whenever a ".org" URL is loaded // The script replaces the page contents with a message // 创建 page mod,匹配 “.org” URL pageMod.PageMod({ include: "*.org", contentScriptFile: [self.data.url("jquery-1.7.min.js"), self.data.url("my-script.js")] });
您也可以在同一 page-mod 中同时使用 contentScript
和 contentScriptFile
。如果您这么做的话,contentScript的脚本将会先加载。(应该是contentScriptFile的先加载吧?)
// Import the page-mod API var pageMod = require("sdk/page-mod"); // Import the self API var self = require("sdk/self"); // Create a page mod // It will run a script whenever a ".org" URL is loaded // The script replaces the page contents with a message pageMod.PageMod({ include: "*.org", contentScriptFile: self.data.url("jquery-1.7.min.js"), contentScript: '$("body").html("<h1>Page matches ruleset</h1>");' });
注意,您不能直接加载网站上的脚本。脚本必须从 data 目录中加载。
与 Content Script 通信
Your add-on script and the content script can't directly access each other's variables or call each other's functions, but they can send each other messages.
从 Content Script 与 main.js 通信,发送方使用 port.emit()
,接收方使用 port.on()
监听.
- In the content script,
port
is a property of the globalself
object. - In the add-on script, you need to listen for the
onAttach
event to get passed a worker object that containsport
.
Let's rewrite the example above to pass a message from the add-on to the content script. The message will contain the new content to insert into the document. The content script now needs to look like this:
// "self" is a global object in content scripts // Listen for a message, and replace the document's // contents with the message payload. self.port.on("replacePage", function(message) { document.body.innerHTML = "<h1>" + message + "</h1>"; });
In the add-on script, we'll send the content script a message inside onAttach
:
// Import the page-mod API var pageMod = require("sdk/page-mod"); // Import the self API var self = require("sdk/self"); // Create a page mod // It will run a script whenever a ".org" URL is loaded // The script replaces the page contents with a message pageMod.PageMod({ include: "*.org", contentScriptFile: self.data.url("my-script.js"), // Send the content script a message inside onAttach onAttach: function(worker) { worker.port.emit("replacePage", "Page matches ruleset"); } });
The replacePage
message isn't a built-in message: it's a message defined by the add-on in the port.emit()
call.
注入 CSS
请注意,本节中描述的功能是实验性的:我们很可能继续支持的功能,但可能需要改变的细节。
Rather than injecting JavaScript into a page, you can inject CSS by setting the page-mod's contentStyle
option:
var pageMod = require("sdk/page-mod").PageMod({ include: "*", contentStyle: "body {" + " border: 5px solid green;" + "}" });
As with contentScript
, there's a corresponding contentStyleFile
option that's given the URL of a CSS file in your "data" directory, and it is good practice to use this option in preference to contentStyle
if the CSS is at all complex:
var pageMod = require("sdk/page-mod").PageMod({ include: "*", contentStyleFile: require("sdk/self").data.url("my-style.css") });
You can't currently use relative URLs in style sheets loaded with contentStyle
or contentStyleFile
. If you do, the files referenced by the relative URLs will not be found.
To learn more about this, and read about a workaround, see the relevant section in the page-mod API documentation.
Learning More
To learn more about page-mod
, see its API reference page. In particular, the PageMod
constructor takes several additional options to control its behavior:
-
By default, content scripts are not attached to any tabs that are already open when the page-mod is created, and are attached to iframes as well as top-level documents. To control this behavior use the
attachTo
option. -
Define read-only values accessible to content scripts using the
contentScriptOptions
option. -
By default, content scripts are attached after all the content (DOM, JS, CSS, images) for the page has been loaded, at the time the window.onload event fires. To control this behavior use the
contentScriptWhen
option.
To learn more about content scripts in general, see the content scripts guide.