Tampermonkey download file name and location change

Tampermonkey download file name and location change

tampermonkey download file name and location change

The package has been renamed from webpack-tampermonkey. output: { path: path.resolve(__dirname, 'dist'), filename: '.user.js' }, devServer. The extension will check the file name and see if it matches a name in the rule that you set. If it does then it will be placed in the folder set by you. If this tag, but @icon is given the @icon image will be scaled at some places at the Defines the URL where the script will be downloaded from when an update was detected. Adds a change listener to the storage and returns the listener ID. reasons the file extension needs to be whitelisted at Tampermonkey's options. tampermonkey download file name and location change

Greasemonkey Hacks by Mark Pilgrim

Chapter 1. Getting Started

The first thing you need to do to get started with Greasemonkey is install it. Open Firefox and go to http://greasemonkey.mozdev.org. Click the Install Greasemonkey link. Firefox will warn you that it prevented this site from installing software, as shown in Figure 1-1.

Figure 1-1. Firefox, requiring you to whitelist sites to install extensions

Click the Edit Options button to bring up the Allowed Sites dialog, as shown in Figure 1-2.

Figure 1-2. Allowed Sites dialog

Click the Allow button to add the Greasemonkey site to your list of allowed sites; then click OK to dismiss the dialog. Now, click the Install Greasemonkey link again, and Firefox will pop up the Software Installation dialog, as shown in Figure 1-3.

Figure 1-3. Software Installation dialog

Click Install Now to begin the installation process. After it downloads, quit Firefox and relaunch it to finish installing Greasemonkey.

Now that that’s out of the way, let’s get right to it.

Greasemonkey won’t do anything until you start installing user scripts to customize specific web pages.

A Greasemonkey user script is a single file, written in JavaScript, that customizes one or more web pages. So, before Greasemonkey can start working for you, you need to install a user script.

This hack shows three ways to install user scripts. The first user script I ever wrote was called Butler. It adds functionality to Google search results.

Installing from the Context Menu

Here’s how to install Butler from the context menu:

  1. Visit the Butler home page (http://diveintomark.org/projects/butler/) to see a brief description of the functionality that Butler offers.

  2. Right-click (Control-click on a Mac) the link titled “Download version…” (at the time of this writing, Version 0.3 is the latest release).

  3. From the context menu, select Install User Script….

  4. A dialog titled Install User Script will pop up, displaying the name of the script you are about to install (Butler, in this case), a brief description of what the script does, and a list of included and excluded pages. All of this information is taken from the script itself [Hack #2].

  5. Click OK to install the user script.

If all went well, Greasemonkey will display the following alert: “Success! Refresh page to see changes.”

Now, search for something in Google. In the search results page, there is a line at the top of the results that says “Try your search on: Yahoo, Ask Jeeves, AlltheWeb…” as shown in Figure 1-4. There is also a banner along the top that says “Enhanced by Butler.” All of these options were added by the Butler user script.

Figure 1-4. Butler-enhanced search results

Installing from the Tools Menu

My Butler user script has a home page, but not all scripts do. Sometimes the author posts only the script itself. You can still install such scripts, even if there are no links to right-click.

Visit http://diveintomark.org/projects/butler/butler.user.js. You will see the Butler source code displayed in your browser. From the Tools menu, select Install User Script…. Greasemonkey will pop up the Install User Script dialog, and the rest of the installation is the same as described in the previous section.

Editing Greasemonkey’s Configuration Files

Like most Firefox browser extensions, Greasemonkey stores its configuration files in your Firefox profile directory. You can install a user script manually by placing it in the right directory and editing the Greasemonkey configuration file with a text editor.

First you’ll need to find your Firefox profile directory, which is harder than it sounds. The following list, from Nigel MacFarlane’s excellent Firefox Hacks (O’Reilly), shows where to find this directory on your particular system:

Single-user Windows 95/98/ME

C:\Windows\Application Data\Mozilla\Firefox

Multiuser Windows 95/98/ME

C:\Windows\Profiles\%USERNAME%\Application Data\Mozilla\Firefox

Windows NT 4.x

C:\Winnt\Profiles\%USERNAME%\Application Data\Mozilla\Firefox

Windows 2000 and XP

C:\Documents and Settings\%USERNAME%\Application Data\Mozilla\Firefox

Unix and Linux

~/.mozilla/firefox

Mac OS X

~/Library/Application Support/Firefox

Within your Firefox directory is your Profiles directory, and within that is a randomly named directory (for security reasons). Within that is a series of subdirectories: extensions/{e4a8a97b-f2ed-450b-b12d-ee082ba24781}/chrome/greasemonkey/content/scripts/. This final scripts directory contains all your installed user scripts, as well as a configuration file named config.xml. Here’s a sample config.xml file:

<UserScriptConfig> <Script filename="bloglinesautoloader.user.js" name="Bloglines Autoloader" namespace="http://diveintomark.org/projects/greasemonkey/" description="Auto-display all new items in Bloglines (the equivalent of clicking the root level of your subscriptions)" enabled="true"> <Include>http://bloglines.com/myblogs*</Include> <Include>http://www.bloglines.com/myblogs*</Include> </Script> <Script filename="googlesearchkeys.user.js" name="Google Searchkeys" namespace="http://www.imperialviolet.org" description="Adds one-press access keys to Google search results" enabled="true"> <Include>http://www.google.*/search*</Include> </Script> <Script filename="mailtocomposeingmail.user.js" name="Mailto Compose In GMail" namespace="http://blog.monstuff.com/archives/000238.html" description="Rewrites &quot;mailto:&quot; links to GMail compose links" enabled="true"> <Include>*</Include> <Exclude>http://gmail.google.com</Exclude> </Script> </UserScriptConfig>

To install a new script, simply copy it to this scripts directory and add a entry like the other ones in config.xml. The element has five attributes: , and . Within the element you can have multiple and elements, as defined in “Provide a Default Configuration” [Hack #2].

For example, to manually install the Butler user script, copy the butler.user.js file into your scripts directory, and then add this XML snippet to config.xml, just before :

<Script filename="butler.user.js" name="Butler" namespace="http://diveintomark.org/projects/butler/" description="Link to competitors in Google search results" enabled="true"> <Include>*</Include> <Exclude>http://*.google.*/*</Exclude> </Script>

Tip

A user script’s filename must end in .user.js. If you’ve gotten the file extension wrong, you won’t be able to right-click the script’s link and select Install User Script…from the context menu. You won’t even be able to visit the script itself and select Install User Script…from the Tools menu.

Provide a Default Configuration

User scripts can be self-describing; they can contain information about what they do and where they should run by default.

Every user script has a section of metadata, which tells Greasemonkey about the script itself, where it came from, and when to run it. You can use this to provide users with information about your script, such as its name and a brief description of what the script does. You can also provide a default configuration for where the script should run: one page, one site, or a selection of multiple sites.

Save the following user script as helloworld.user.js:

Example: Hello World metadata // ==UserScript== // @name Hello World // @namespace http://www.oreilly.com/catalog/greasemonkeyhcks/ // @description example script to alert "Hello world!" on every page // @include * // @exclude http://oreilly.com/* // @exclude http://www.oreilly.com/* // ==/UserScript== alert('Hello world!');

There are five separate pieces of metadata here, wrapped in a set of Greasemonkey-specific comments.

Let’s take them in order, starting with the wrapper:

// ==UserScript== // // ==/UserScript==

These comments are significant and must match this pattern exactly. Greasemonkey uses them to signal the start and end of a user script’s metadata section. This section can be defined anywhere in your script, but it’s usually near the top.

Within the metadata section, the first item is the name:

// @name Hello World

This is the name of your user script. It is displayed in the install dialog when you first install the script and later in the Manage User Scripts dialog. It should be short and to the point.

is optional. If present, it can appear only once. If not present, it defaults to the filename of the user script, minus the .user.js extension.

Next comes the namespace:

// @namespace http://www.oreilly.com/catalog/greasemonkeyhcks/

This is a URL, which Greasemonkey uses to distinguish user scripts that have the same name but are written by different authors. If you have a domain name, you can use it (or a subdirectory) as your namespace. Otherwise, you can use a : URI.

is optional. If present, it can appear only once. If not present, it defaults to the domain from which the user downloaded the user script.

Tip

You can specify the items of your user script metadata in any order. I like , and finally , but there is nothing special about this order.

Next comes the description:

// @description example script to alert "Hello world!" on every page

This is a human-readable description of what the user script does. It is displayed in the install dialog when you first install the script and later in the Manage User Scripts dialog. It should be no longer than two sentences.

is optional. If present, it can appear only once. If not present, it defaults to an empty string.

Tip

Though is not mandatory, don’t forget to include it. Even if you are writing user scripts only for yourself, you will eventually end up with dozens of them, and administering them all in the Manage User Scripts dialog will be much more difficult if you don’t include a description.

The next three lines are the most important items (from Greasemonkey’s perspective). The and directives give a series of URLs and wildcards that tell Greasemonkey where to run this user script:

// @include * // @exclude http://oreilly.com/* // @exclude http://www.oreilly.com/*

The and directives share the same syntax. They can be a URL, a URL with the * character as a simple wildcard for part of the domain name or path, or simply the * wildcard character by itself. In this case, we are telling Greasemonkey to execute the Hello World script on all sites except http://oreilly.com and http://www.oreilly.com. Excludes take precedence over includes, so if you went to http://www.oreilly.com/catalog/, the user script would not run. The URL http://oreilly.com/catalog/ matches the * (all sites), but it would be excluded because it also matches http://oreilly.com/*.

and are optional. You can specify as many included and excluded URLs as you like, but you must specify each on its own line. If neither is specified, Greasemonkey will execute your user script on all sites (as if you had specified *).

Master the @include and @exclude Directives

Describing exactly where you want your user script to execute can be tricky.

As described in “Provide a Default Configuration” [Hack #2], Greasemonkey executes a user script based on and parameters: URLs with * wildcards that match any number of characters. This might seem like a simple syntax, but combining wildcards to match exactly the set of pages you want is trickier than you think.

Matching with or Without the www. Prefix

Here’s a common scenario: a site is available at http://example.com and http://www.example.com. The site is the same in both cases, but neither URL redirects to the other. If you type in the location bar, you get the site at http://example.com. If you visit www.example.com, you get exactly the same site, but the location bar reads http://www.example.com.

Let’s say you want to write a user script that runs in both cases. Greasemonkey makes no assumptions about URLs that an end user might consider equivalent. If a site responds on both http://example.comand http://www.example.com, you need to declare both variations, as shown in this example:

@include http://example.com/* @include http://www.example.com/*

Matching Different Top-Level Domains of a Site

Now things get really tricky. Amazon is available in the United States at http://www.amazon.com. (Because http://amazon.com visibly redirects you to http://www.amazon.com, we won’t need to worry about matching both.) But Amazon also has country-specific sites, such as http://www.amazon.co.uk/ in England, http://www.amazon.co.jp/ in Japan, and so forth.

If you want to write a user script that runs on all of Amazon’s country-specific sites, there is a special type of wildcard, , that matches all the top-level domains, as shown in the following example:

@include http://www.amazon.tld/*

This special syntax matches any top-level domain: .com, .org, .net, or a country-specific domain, such as .co.uk or .co.jp. Greasemonkey keeps a list of all the registered top-level domains in the world and expands the wildcard to include each of them.

Deciding Between * and http://*

One final note, before we put the and issue to bed. If you’re writing a user script that applies to all pages, there are two subtly different ways to do that. Here’s the first way:

@include *

This means that the user script should execute absolutely everywhere. If you visit a web site, the script will execute. If you visit a secure site (one with an https:// address), the script will execute. If you open an HTML file from your local hard drive, the script will execute. If you open a blank new window, the script will execute (since technically the “location” of a blank window is about:blank).

This might not be what you want. If you want the script to execute only on actual remote web pages “out there” on the Internet, you should specify the line differently, like this:

@include http://*

This means that the user script will execute only on remote web sites, whose address starts with http://. This will not include secure web sites, such as your bank’s online bill payment site, because that address starts with https://. If you want the script to run on both secure and standard web sites, you’ll need to explicitly specify both, like so:

@include http://* @include https://*

Prevent a User Script from Executing

You can disable a user script temporarily, disable all user scripts, or uninstall a user script permanently.

Once you have a few user scripts running, you might want to temporarily disable some or all of them. There are several different ways to prevent a user script from running.

Disabling a User Script Without Uninstalling It

The easiest way to disable a user script is in the Manage User Scripts dialog. Assuming you installed the Butler user script [Hack #1], you can disable it with just a few clicks:

  1. From the menu bar, select Tools → Manage User Scripts…. Greasemonkey will pop up the Manage User Scripts dialog.

  2. In the left pane of the dialog is a list of all the user scripts you have installed. (If you’ve been following along from the beginning of the book, this will include just one script: Butler.)

  3. Select Butler in the list if it is not already selected, and deselect the Enabled checkbox. The color of Butler in the left pane should change subtly from black to gray. (This is difficult to see while it is still selected, but it’s more useful once you have dozens of scripts installed.)

  4. Click OK to exit the Manage User Scripts dialog.

Now, Butler is installed, but inactive. You can verify this by searching for something on Google. It should no longer say “Enhanced by Butler” along the top. You can reenable the Butler user script by repeating the procedure and reselecting the Enabled checkbox in the Manage User Scripts dialog.

Tip

Once disabled, a user script will remain disabled until you manually reenable it, even if you quit and relaunch Firefox.

Disabling All User Scripts

While Greasemonkey is installed, it displays a little smiling monkey icon in the status bar, as shown in Figure 1-5.

Figure 1-5. Greasemonkey status bar icon

Clicking the Greasemonkey icon in the status bar disables Greasemonkey entirely; any user scripts you have installed will no longer execute. The Greasemonkey icon will frown and turn gray to indicate that Greasemonkey is currently disabled, as shown in Figure 1-6.

Clicking the icon again reenables Greasemonkey and any enabled user scripts.

Figure 1-6. Greasemonkey disabled

Disabling a User Script by Removing All Included Pages

As shown in “Master the @include and @exclude Directives” [Hack #3], user scripts contain two sections: a list of pages to run the script and a list of pages not to run the script. Another way to prevent a user script from executing is to remove all the pages on which it runs:

  1. From the menu bar, select Tools → Manage User Scripts…. Greasemonkey will pop up the Manage User Scripts dialog.

  2. In the left pane of the dialog is a list of all the user scripts you have installed.

  3. Select Butler in the list if it is not already selected, and then select http://*.google.com/* in the list of Included Pages. Click the Remove button to remove this URL from the list.

  4. Click OK to exit the Manage User Scripts dialog.

Disabling a User Script by Excluding All Pages

Yet another way to disable a user script is to add a wildcard to exclude it from all pages:

  1. From the menu, select Tools → Manage User Scripts…. Greasemonkey will pop up the Manage User Scripts dialog.

  2. In the left pane of the dialog is a list of all the user scripts you have installed.

  3. Select Butler in the list if it is not already selected.

  4. Under the Excluded Pages list, click the Add button. Greasemonkey will pop up an Add Page dialog box. Type * and click OK.

  5. Click OK to exit the Manage User Scripts dialog.

Now, Butler is still installed and technically still active. But because excluded pages take precedence over included pages, Butler will never actually be executed, because you have told Greasemonkey to exclude it from all pages.

Disabling a User Script by Editing config.xml

As shown in “Install a User Script” [Hack #1], Greasemonkey stores the list of installed scripts in a configuration file, config.xml, deep within your Firefox profile directory:

<UserScriptConfig> <Script filename="butler.user.js" name="Butler" namespace="http://diveintomark.org/projects/butler/" description="Link to competitors from Google search results" enabled="true"> <Include>http://*.google.com/*</Include> </Script> </UserScriptConfig>

You can manually edit this file to disable a user script. To disable Butler, find its element in config.xml, and then set the attribute to .

Uninstalling a User Script

Finally, you can remove a user script entirely by uninstalling it:

  1. From the menu bar, select Tools → Manage User Scripts…. Greasemonkey will pop up a Manage User Scripts dialog.

  2. In the left pane, select Butler.

  3. Click Uninstall.

  4. Click OK to exit the Manage User Scripts dialog.

Butler is now uninstalled completely.

There’s more than one way to configure Greasemonkey user scripts: before, during, and after installation.

One of the most important pieces of information about a user script is where it should run. One page? Every page on one site? Multiple sites? All sites? This hack explains several different ways to configure where a user script executes.

As described in “Provide a Default Configuration” [Hack #2], user scripts contain a section that describes what the script is and where it should run. Editing the and lines in this section is the first and easiest way to configure a user script, because the configuration travels with the script code. If you copy the file to someone else’s computer or publish it online, other people will pick up the default configuration.

Another good time to alter a script’s metadata is during installation. Remember in “Install a User Script” [Hack #1] when you first installed the Butler user script? Immediately after you select the Install User Script…menu item, Greasemonkey displays a dialog box titled Install User Script, which contains lists of the included and excluded pages, as shown in Figure 1-7.

Figure 1-7. Butler installation dialog

The two lists are populated with the defaults that are defined in the script’s metadata section (specifically, the and lines), but you can change them to anything you like before you install the script. Let’s say, for example, that you like Butler, but you have no use for it on Froogle, Google’s cleverly named product comparison site. Before you install the script, you can modify the configuration to exclude that site but still let the script work on other Google sites.

To ensure that Butler doesn’t alter Froogle, click the Add…button under “Excluded pages” and type the wildcard URL for Froogle, as shown in Figure 1-8.

Figure 1-8. Excluding Froogle in the Butler installation dialog

You can also reconfigure a script’s included and excluded pages after the script is installed. Assuming you previously excluded Froogle from Butler’s configuration (as described in the previous section), let’s now change the configuration to include Froogle again:

  1. From the Firefox menu, select Tools/Manage User Scripts…. Greasemonkey will pop up the Manage User Scripts dialog.

  2. In the pane on the left, select Butler. In the pane on the right, Greasemonkey should show you two lists: one of included pages (http://*.google.*/*) and one of excluded pages (http://froogle.google.com/*).

  3. In the “Excluded pages” list, select http://froogle.google.com/* and click the Remove button.

  4. Click OK to exit the Manage User Scripts dialog.

Now, search for a product on Froogle to verify that Butler is once again being executed.

Editing Configuration Files

The last way to reconfigure a user script is to manually edit the config.xml file, which is located within your Firefox profile directory. (See “Install a User Script” [Hack #1] for the location.) The graphical dialogs Greasemonkey provides are just friendly ways of editing config.xml without knowing it.

Each installed user script is represented by a element, as shown in the following example:

<Script filename="helloworld.user.js" name="Hello World" namespace="http://www.oreilly.com/catalog/greasemonkeyhcks/" description="example script to alert &quot;Hello world!&quot; on every page" enabled="true"> <Include>*</Include> <Exclude>http://oreilly.com/*</Exclude> <Exclude>http://www.oreilly.com/*</Exclude> </Script>

You can make any changes you like to the config.xml file. You can add, remove, or edit the and elements to change where the script runs. You can change the enabled attribute to to disable the script. You can even uninstall the script by deleting the entire element.

Tip

Starting in Version 0.5, Greasemonkey no longer caches the config.xml file in memory. If you manually change the config.xml file while Firefox is running, you will see the changes immediately when you navigate to a new page or open the Manage User Scripts dialog.

Add or Remove Content on a Page

Use DOM methods to manipulate the content of a web page.

Since most user scripts center around adding or removing content from a web page, let’s quickly review the standard DOM methods for manipulating content.

The following code adds a new element to the end of the page. The element will appear at the bottom of the page, unless you style it with CSS to position it somewhere else [Hack #7]:

var elmNewContent = document.createElement('div'); document.body.appendChild(elmNewContent)

You can also remove elements from a page. Removed elements disappear from the page (obviously), and any content after them collapses to fill the space the elements occupied. The following code finds the element with and removes it:

var elmDeleted = document.getElementById("ads"); elmDeleted.parentNode.removeChild(elmDeleted);

Tip

If all you want to do is remove ads, it’s probably easier to install the AdBlock extension than to write your own user script. You can download AdBlock at http://adblock.mozdev.org.

Many user scripts insert content into a page, rather than appending it to the end of the page. The following code creates a link to http://www.example.com and inserts it immediately before the element with :

var elmNewContent = document.createElement('a'); elmNewContent.href = 'http://www.example.com/'; elmNewContent.appendChild(document.createTextNode('click here')); var elmFoo = document.getElementById('foo'); elmFoo.parentNode.insertBefore(elmNewContent, elmFoo);

You can also insert content after an existing element, by using the property:

elmFoo.parentNode.insertBefore(elmNewContent, elmFoo.nextSibling);

Tip

Inserting new content before will work even if is the last child of its parent (i.e., it has no next sibling). In this case, will return , and the function will simply append the new content after all other siblings. In other words, this example code will always work, even when it seems like it shouldn’t.

You can replace entire chunks of a page in one shot by using the method. The following code replaces the element with with content that we create on the fly:

var elmNewContent = document.createElement('p'); elmNewContent.appendChild(document.createTextNode('Replaced!')); var elmExtra = document.getElementById('extra'); elmExtra.parentNode.replaceChild(elmNewContent, elmExtra);

As you can see from the previous few examples, the process of creating new content can be arduous. Create an element, append some text, set individual attributes…bah. There is an easier way. It’s not a W3C-approved DOM property, but all major browsers support the property for getting or setting HTML content as a string. The following code accomplishes the same thing as the previous example:

var elmExtra = document.getElementById('extra'); elmReplaced.innerHTML = '<p>Replaced!</p>';

The HTML you set with the property can be as complex as you like. Firefox will parse it and insert it into the DOM tree, just as if you had created each element and inserted it with standard DOM methods.

Modifying an Element’s Attributes

Modifying a single attribute is simple. Each element is an object in JavaScript, and each attribute is reflected by a corresponding property. The following code finds the link with and changes its property to link to a different URL:

var elmLink = document.getElementById('somelink'); elmLink.href = 'http://www.oreilly.com/';

You can accomplish the same thing with the method:

elmLink.setAttribute('href', 'http://www.oreilly.com/')

This is occasionally useful, if you are setting an attribute whose name you don’t know in advance.

You can also remove an attribute entirely with the method:

elmLink.removeAttribute('href');

Tip

See “Make Pop-up Titles Prettier” [Hack #28] for an example of why this might be useful.

If you remove the attribute from a link, it will still be an element, but it will cease to be a link. If the link has an or attribute, it will still be a page anchor, but you will no longer be able to click it to follow the link.

There are four basic ways to add or modify a page’s CSS rules.

In many of the user scripts I’ve written, I want to make things look a certain way. Either I’m modifying the page’s original style in some way, or I’m adding content to the page and I want to make it look different from the rest of the page. There are several ways to accomplish this.

Here is a simple function that I reuse in most cases in which I need to add arbitrary styles to a page. It takes a single parameter, a string containing any number of CSS rules:

function addGlobalStyle(css) { try { var elmHead, elmStyle; elmHead = document.getElementsByTagName('head')[0]; elmStyle = document.createElement('style'); elmStyle.type = 'text/css'; elmHead.appendChild(elmStyle); elmStyle.innerHTML = css; } catch (e) { if (!document.styleSheets.length) { document.createStyleSheet(); } document.styleSheets[0].cssText += css; } }

Inserting or Removing a Single Style

As you see in the previous example, Firefox maintains a list of the stylesheets in use on the page, in (note the capitalization!). Each item in this collection is an object, representing a single stylesheet. Each stylesheet object has a collection of rules, and methods to add new rules or remove existing rules.

The method takes two parameters. The first is the CSS rule to insert, and the second is the positional index of the rule before which to insert the new rule:

document.styleSheets[0].insertRule('html, body { font-size: large }', 0);

Tip

In CSS, order matters; if there are two rules for the same CSS selector, the later rule takes precedence. The previous line will insert a rule before all other rules, in the page’s first stylesheet.

You can also delete individual rules by using the method. It takes a single parameter, the positional index of the rule to remove. The following code will remove the first rule, which we just inserted with :

document.styleSheets[0].deleteRule(0);

Modifying an Element’s Style

You can also modify the style of a single element by setting properties on the element’s attribute. The following code finds the element with and sets its background color to :

var elmModify = document.getElementById("foo"); elmModify.style.backgroundColor = 'red';

Tip

The property names of individual styles are not always obvious. Generally they follow a pattern, where the CSS rule becomes the JavaScript expression . But there are exceptions. The property is set with , since is a reserved word in JavaScript.

There is no easy way to set multiple properties at once. In regular JavaScript, you can set multiple styles by calling the method to the attribute to a string:

elmModify.setAttribute("style", "background-color: red; color: white; " + "font: small serif");

However, as explained in “Avoid Common Pitfalls” [Hack #12], this does not work within Greasemonkey scripts.

Tap into a powerful new way to find exactly what you’re looking for on a page.

Firefox contains a little-known but powerful feature called XPath. XPath is a query language for searching the Document Object Model (DOM) that Firefox constructs from the source of a web page.

As mentioned in “Add or Remove Content on a Page” [Hack #6], virtually every hack in this book revolves around the DOM. Many hacks work on a collection of elements. Without XPath, you would need to get a list of elements (for example, with ) and then test each one to see if it’s something of interest. With XPath expressions, you can find exactly the elements you want, all in one shot, and then immediately start working with them.

To execute an XPath query, use the function. Here’s the basic syntax:

var snapshotResults = document.evaluate('XPath expression', document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);

The function takes five parameters:

The XPath expression itself

More on this in a minute.

The root node on which to evaluate the expression

If you want to search the entire web page, pass in . But you can also search just a part of the page. For example, to search within a , pass as the second parameter.

A namespace resolver function

You can use this to create XPath queries that work on XHTML pages. See “Select Multiple Checkboxes” [Hack #36] for an example.

The type of result to return

If you want a collection of elements, use . If you want to find a single element, use . More on this in a minute, too.

A previous XPath result to append to this result

I rarely use this, but it can be useful if you want to conditionally concatenate the results of multiple XPath queries.

The function returns a snapshot, which is a static array of DOM nodes. You can iterate through the snapshot or access its items in any order. The snapshot is static, which means it will never change, no matter what you do to the page. You can even delete DOM nodes as you move through the snapshot.

A snapshot is not an array, and it doesn’t support the standard array properties or accessors. To get the number of items in the snapshot, use . To access a particular item, you need to call . Here is the skeleton of a script that executes an XPath query and loops through the results:

var snapResults = document.evaluate("XPath expression", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); for (var i = snapResults.snapshotLength - 1; i >= 0; i--) { var elm = snapResults.snapshotItem(i); // do stuff with elm }

The following XPath query finds all the elements on a page with :

var snapFoo = document.evaluate( document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);

The // means “search for things anywhere below the root node, including nested elements.” The * matches any element, and restricts the search to elements with a class of .

You can use XPath to search for specific elements. The following query finds all elements. (This example is taken from “Show Hidden Form Fields” [Hack #30].)

var snapHiddenFields = document.evaluate( document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);

You can also test for the presence of an attribute, regardless of its value. The following query finds all elements with an attribute. (This example is taken from “Add an Access Bar with Keyboard Shortcuts” [Hack #68].)

var snapAccesskeys = document.evaluate( document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);

Not impressed yet? Here’s a query that finds images whose URL contains the string "“. (This example is taken from “Make Amazon Product Images Larger” [Hack #25].)

var snapProductImages = document.evaluate( document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);

You can also do combinations of attributes. This query finds all images with a width of 36 and a height of 14. (This query is taken from “Zap Ugly XML Buttons” [Hack #86].)

var snapXMLImages = document.evaluate( document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);

But wait, there’s more! By using more advanced XPath syntax, you can actually find elements that are contained within other elements. This code finds all the links that are contained in a paragraph whose class is . (This example is taken from “Refine Your Google Search” [Hack #96].)

var snapResults = document.evaluate( document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);

Finally, you can find a specific element by passing in the third parameter. This line of code finds the first link whose class is "“. (This example is taken from “Prefetch Yahoo! Search Results” [Hack #52].)

var elmFirstResult = document.evaluate( document, null, <b>XPathResult.FIRST_ORDERED_NODE_TYPE</b>, null)

If you weren’t brain-fried by now, I’d be very surprised. XPath is, quite literally, a language all its own. Like regular expressions, XPath can make your life easier, or it can make your life a living hell. Remember, you can always get what you need (eventually) with standard DOM functions such as or . XPath’s a good tool to have in your tool chest, but it’s not always the right tool for the job.

Develop a User Script “Live”

Edit a user script and see your changes immediately.

While you’re writing a user script, you will undoubtedly need to make changes incrementally and test the results. As shown in “Install a User Script” [Hack #1], Greasemonkey stores your installed user scripts deep within your Firefox profile directory. Changes to these installed files take effect immediately, as soon as you refresh the page. This makes the testing cycle quick, because you can edit your partially written script, save changes, and refresh your test page to see the changes immediately.

Setting Up File Associations

Before you can take advantage of live editing, you need to set up file associations on your system, so that double-clicking a .user.js script opens the file in your text editor instead of trying to execute it or viewing it in a web browser.

Control-click a .user.js file in Finder, and then select Get Info. In the Open With section, select your text editor from the drop-down menu, or select Other…to find the editor program manually. Click Change All to permanently associate your editor with .js files.

Right-click a .user.js file in Explorer, and then select Open With → Choose Program. Select your favorite text editor from the list, or click Browse to find the editor application manually. Check the box titled “Always use the selected program to open this kind of file” and click OK.

The “Live Editing” Development Cycle

Switch back to Firefox and select Tools → Manage User Scripts. Select a script from the pane on the left and click Edit. If your file associations are set up correctly, this should open the user script in your text editor.

The first time you do this on Windows, you will get a warning message, explaining that you need to set up your file associations, as shown in Figure 1-9. You’re one step ahead of the game, since you’ve already done this.

Tip

The reason for the warning is that, by default, Windows is configured to execute .js files in the built-in Windows Scripting Host environment. This is generally useless, and certainly confusing if you don’t know what’s going on.

Figure 1-9. File association warning on Windows

Once the user script opens in your text editor, you can make any changes you like to the code. You’re editing the copy of the user script within your Firefox profile directory—the copy that Greasemonkey uses. As soon as you make a change and save it, you can switch back to Firefox and refresh your test page to see the effect of your change. Switch to your editor, make another change, switch back to Firefox, and refresh. It’s that simple.

Tip

During live editing, you can change only the code of a user script, not the configuration parameters in the metadata section. If you want to change where the script runs, use the Manage User Scripts dialog.

When you’re satisfied with your user script, switch back to your editor one last time and save a copy to another directory.

Warning

Remember, you’ve been editing the copy deep within your Firefox profile directory. I’ve lost significant chunks of code after live-editing a user script and then uninstalling it without saving a copy first. Don’t make this mistake! Save a backup somewhere else for safekeeping.

Learn the subtle art of Greasemonkey debugging.

The actual process of writing user scripts can be frustrating if you don’t know how to debug them properly. Since JavaScript is an interpreted language, errors that would otherwise cause a compilation error (such as misspelled variables or function names) can only be caught when they occur at runtime. Furthermore, if something goes wrong, it’s not immediately obvious how to figure out what happened, much less how to fix it.

If your user script doesn’t appear to be running properly, the first place to check is JavaScript Console, which lists all script-related errors, including those specific to user scripts. Select Tools → JavaScript Console to open the JavaScript Console window. You will probably see a long list of all the script errors on all the pages you’ve visited since you opened Firefox. (You’d be surprised how many high-profile sites have scripts that crash regularly.)

In the JavaScript Console window, click Clear to remove the old errors from the list. Now, refresh the page you’re using to test your user script. If your user script is crashing or otherwise misbehaving, you will see the exception displayed in JavaScript Console.

Tip

If your user script is crashing, JavaScript Console will display an exception and a line number. Due to the way Greasemonkey injects user scripts into a page, this line number is not actually useful, and you should ignore it. It is not the line number within your user script where the exception occurred.

If you don’t see any errors printed in JavaScript Console, you might have a configuration problem. Go to Tools → Manage User Scripts and double-check that your script is installed and enabled and that your current test page is listed in the Included Pages list.

OK, so your script is definitely running, but it isn’t working properly. What next? You can litter your script with alert calls, but that’s annoying. Instead, Greasemonkey provides a logging function, , that allows you to write messages to JavaScript Console. Such messages should be taken out before release, but they are enormously helpful in debugging. Plus, watching the console pile up with log messages is much more satisfying than clicking OK over and over to dismiss multiple alerts.

takes one argument, the string to be logged. After logging to JavaScript Console, the user script will continue executing normally.

Save the following user script as testlog.user.js:

// ==UserScript== // @name TestLog // @namespace http://example.com/ // ==/UserScript== if (/^http:\/\/www\.oreilly\.com\//.test(location.href)) { GM_log("running on O'Reilly site"); } else { GM_log('running elsewhere'); } GM_log('this line is always printed');

If you install this user script and visit http://www.oreilly.com, these two lines will appear in JavaScript Console:

Greasemonkey: http://example.com//TestLog: running on O'Reilly site Greasemonkey: http://example.com//TestLog: this line is always printed

Greasemonkey dumps the namespace and script name, taken from the user script’s metadata section, then the message that was passed as an argument to .

If you visit somewhere other than http://www.oreilly.com, these two lines will appear in JavaScript Console:

Greasemonkey: http://example.com//TestLog: running elsewhere Greasemonkey: http://example.com//TestLog: this line is always printed

Messages logged in Javascript Console are not limited to 255 characters. Plus, lines in JavaScript Console wrap properly, so you can always scroll down to see the rest of your log message. Go nuts with logging!

Tip

In JavaScript Console, you can right-click (Mac users Control-click) on any line and select Copy to copy it to the clipboard.

DOM Inspector allows you to explore the parsed Document Object Model (DOM) of any page. You can get details on each HTML element, attribute, and text node. You can see all the CSS rules from each page’s stylesheets. You can explore all the scriptable properties of an object. It’s extremely powerful.

DOM Inspector is included with the Firefox installation program, but depending on your platform, it might not installed by default. If you don’t see a DOM Inspector item in the Tools menu, you will need to reinstall Firefox and choose Custom Install, then select Developer Tools. (Don’t worry; this will not affect your existing bookmarks, preferences, extensions, or user scripts.)

A nice addition to DOM Inspector is the Inspect Element extension. It allows you to right-click on any element—a link, a paragraph, even the page itself—and open DOM Inspector with that element selected. From there, you can inspect its properties, or see exactly where it fits within the hierarchy of other elements on the page.

One last note: DOM Inspector does not follow you as you browse. If you open DOM Inspector and then navigate somewhere else in the original window, DOM Inspector will get confused. It’s best to go where you want to go, inspect what you want to inspect, then close DOM Inspector before doing anything else.

Test JavaScript Code Interactively

JavaScript Shell is a bookmarklet that allows you to evaluate arbitrary JavaScript expressions in the context of the current page. You install it simply by dragging it to your links toolbar. Then you can visit a web page you want to work on, and click the JavaScript Shell bookmarklet in your toolbar. The JavaScript Shell window will open in the background.

JavaScript Shell offers you the same power as DOM Inspector but in a free-form environment. Think of it as a command line for the DOM. You can enter any JavaScript expressions or commands, and you will see the output immediately. You can even make changes to the page, such as creating a new element and adding to the page with . Your changes are reflected in the original page.

One feature of JavaScript Shell that is worth special mention is the function. Visit http://www.oreilly.com, open JavaScript Shell, and then type the following two lines:

var link = document.getElementsByTagName('a')[0] props(link)

JavaScript Shell spews out a long list of properties:

What’s this all about? It’s a list of all the properties and methods of that element that are available to you in JavaScript, grouped by levels in the DOM object hierarchy. Methods and properties that are specific to link elements (such as the and methods, and the and properties) are listed first, followed by methods and properties shared by all types of nodes (such as the method).

Again, this is the same information that is available in DOM Inspector—but with more typing and experimenting, and less pointing and clicking.

Tip

Like DOM Inspector, JavaScript Shell does not follow you as you browse. If you open JavaScript Shell and then navigate somewhere else in the original window, JavaScript Shell will get confused. It’s best to go where you want to go, open JavaScript Shell, fiddle to your heart’s content, and then close JavaScript Shell before doing anything else. Be sure to copy your code from the JavaScript Shell window and paste it into your user script once you’re satisfied with it.

Embed Graphics in a User Script

Add images to web pages without hitting a remote server.

A user script is a single file. Greasemonkey does not provide any mechanism for bundling other resource files, such as image files, along with the JavaScript code. While this might offend the sensibilities of some purists who would prefer to maintain separation between code, styles, markup, and media resources, in practice, it is rarely a problem for me.

This is not to say you can’t include graphics in your scripts, but you need to be a bit creative. Instead of posting the image to a web server and having your user script fetch it, you can embed the image data in the script itself by using a : URL. A : URL allows you to encode an image as printable text, so you can store it as a JavaScript string. And Firefox supports : URLs natively, so you can insert the graphic directly into a web page by setting an element’s attribute to the : URL string. Firefox will display the image without sending a separate request to any remote server.

This user script runs on all pages. It uses an XPath query to find web bugs: 1 x 1-pixel elements that advertisers use to track your movement online. The script filters this list of potential web bugs to include only those images that point to a third-party site, since many sites use 1 x 1-pixel images for spacing in table-based layouts.

There is no way for Greasemonkey to eliminate web bugs altogether; by the time a user script executes, the image has already been fetched. But we can make them more visible by changing the attribute of the element after the fact. The image data is embedded in the script itself.

Save the following user script as webbugs.user.js:

Источник: [https://torrent-igruha.org/3551-portal.html]

Tampermonkey download file name and location change

3 thoughts to “Tampermonkey download file name and location change”

Leave a Reply

Your email address will not be published. Required fields are marked *