advertisement

Print

Avoid Common Pitfalls in Greasemonkey
Pages: 1, 2, 3, 4, 5

Pitfall #3: Named Forms and Form Elements

Firefox lets you access elements on a web page in a variety of ways. For example, if you had a form named gs that contained an input box named q:



<form id="gs">
<input name="q" type="text" value="foo">
</form>

you could ordinarily get the value of the input box like this:

var q = document.gs.q.value;

In a user script, this doesn't work. The document object is an XPCNativeWrapper, and it does not support the shorthand of getting an element by ID. This means document.gs is undefined, so the rest of the statement fails. But even if the document wrapper did support getting an element by ID, the statement would still fail, because XPCNativeWrappers around form elements don't support the shorthand of getting form fields by name. This means that even if document.gs returned the form element, document.gs.q would not return the input element, so the statement would still fail.

To work around this, you need to use the namedItem method of the document.forms array to access forms by name, and the elements array of the form element to access the form's fields:

var form = document.forms.namedItem("gs");
var input = form.elements.namedItem("q");
var q = input.value;

You could squeeze this into one line instead of using temporary variables for the form and input elements, but you still need to call each of these methods and string the return values together. There are no shortcuts.

Pitfall #4: Custom Properties

JavaScript allows you to define custom properties on any object, just by assigning them. This capability extends to elements on a web page, where you can make up arbitrary attributes and assign them directly to the element's DOM object.

var elmFoo = document.getElementById('foo');
elmFoo.myProperty = 'bar';

This doesn't work in Greasemonkey scripts, because elmFoo is really an XPCNativeWrapper around the element named foo, and XPCNativeWrappers don't let you define custom attributes with this syntax. You can set common attributes like id or href, but if you want to define your own custom attributes, you need to use the setAttribute method:

var elmFoo = document.getElementById('foo');
elmFoo.setAttribute('myProperty', 'bar');

If you want to access this property later, you will need to use the getAttribute method:

var foo = elmFoo.getAttribute('myProperty');

Pitfall #5: Iterating Collections

Normally, DOM methods such as document.getElementsByTagName return an HTMLCollection object. This object acts much like a JavaScript Array object. It has a length property that returns the number of elements in the collection, and it allows you to iterate through the elements in the collection with the in keyword:

var arInputs = document.getElementsByTagName("input");
for (var elmInput in arInputs) {
  ...
}

This does not work in Greasemonkey scripts, because the arInputs object is an XPCNativeWrapper around an HTMLCollection object, and XPCNativeWrappers do not support the in keyword. Instead, you need to iterate through the collection with a for loop, and get a reference to each element separately:

for (var i = 0; i < arInputs.length; i++) {
  var elmInput = arInputs[i];
  ...
}

Pages: 1, 2, 3, 4, 5

Next Pagearrow