mozilla
Your Search Results

    Modifying Web Pages Based on URL

    This article is in need of a technical review.

    This article is in need of an editorial review.

    To follow this tutorial, you'll need to install add-on SDK and learn the basics of jpm (Firefox 38 onwards) or basics of cfx.

    To modify any pages that match a particular pattern (for example, "http://example.org/") as they are loaded, use page-mod module.

    To create a page-mod, you need to specify two things:

    • One or more content scripts to run whose job is to interact with web content.
    • One or more patterns to match URLs for the pages you want to modify.

    A simple code snippet where content script is supplied as contentScript option and URL pattern is given as include option is as follows:

    // 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>";'
    });
    

    Do as follows:

    • Create a new directory and navigate to it.
    • Run jpm init or cfx init
    • Open file index.js and add the code above (lib/main.js if using cfx)
    • Run jpm run or cfx run.
    • Open ietf.org in the browser window that opens.

    Below is what you should see.

    Specifying the Match Pattern

    Match pattern uses match-pattern syntax. You can pass a single match-pattern string, or an array.

    Keeping the Content Script in a Separate File

    In the example above, we've supplied content script as a string.

    Unless the script is extremely simple, maintain the script as a separate file though. This makes the code easier to maintain, debug, and review. To do this, you need to:

    • Save the script in add-on's data directory.
    • Use contentScriptFile option instead of contentScript and pass it script URL which can be obtained using self.data.url("my-script.js"). From Firefox 34 onwards, you can just use "./my-script.js" instead.

    For example, if we save the script above under the add-on's data directory in a file called my-script.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")
    });

    Or from Firefox 34 onwards:

    // 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",
      contentScriptFile: "./my-script.js"
    });

    Loading Multiple Content Scripts

    You can load more than one script, and the scripts can interact directly with each other.

    For example, You could rewrite my-script.js to use jQuery.

    $("body").html("<h1>Page matches ruleset</h1>");
    

    Then download jQuery to add-on's data directory, and load the script and jQuery together (making sure to load jQuery first).

    // 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"), self.data.url("my-script.js")]
    });
    

    You can use both contentScript and contentScriptFile in the same page-mod. If you do this, scripts loaded using contentScriptFile are loaded first.

    // 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>");'
    });
    

    Note, though, that you can't load a script from a web site. The script must be loaded from data.

    Communicating With the Content Script

    Your add-on script and content scripts can't directly access each other's variables or call each other's functions, but they can send each other messages.

    To send a message from one side to the other, sender calls port.emit() and receiver listens using port.on().

    • In the content script, port is a property of the global self object.
    • In the add-on script, you need to listen for the onAttach event to get passed a worker object that contains port.

    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.

    Injecting CSS

    Note that the feature described in this section is experimental at the moment. We'll most likely continue to support the feature, but API details may change.

    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 takes the URL of a CSS file in your "data" directory; It's a good practice to use this option in preference to contentStyle if the CSS is even marginally complex.

    var pageMod = require("sdk/page-mod").PageMod({
      include: "*",
      contentStyleFile: require("sdk/self").data.url("my-style.css")
    });
    

    Or, from Firefox 34, you can use the simpler version:

    var pageMod = require("sdk/page-mod").PageMod({
      include: "*",
      contentStyleFile: "./my-style.css"
    });

    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 contentScriptWhen option.

    To learn more about content scripts in general, see content scripts guide.

    Document Tags and Contributors

    Tags: 
    Last updated by: AtulKumar2,
    Hide Sidebar