Component not available: half an answer

106 views
Skip to first unread message

Jay Levitt

unread,
Jan 14, 2008, 11:58:15 AM1/14/08
to greasemonkey-users
[Apologies for the double e-mail to Anthony; I didn't notice that
Google removes the Reply link on old threads, so I accidentally did
Reply to Author instead.]

There was a thread from last April where someone asked:

> When i try 5.7. Case study: Zoom Textarea i get the following error
> when loading a page with a textarea
> "Component is not available" on line 69
>
>I.e. When the script tries to assign the previously declared function
> to the onclick event of the button link its created
> button.onclick = func;

I'm having a similar problem just trying to run an older script (in my
case, Google Search Refiner).

Unfortunately, the response to that message pointed the OP to an
O'Reilly article with no specifics ("read the whole thing") and the
front page of the Greasemonkey wiki. Neither the article nor the wiki
use either "component" or "available" in any relevant fashion, so it's
difficult for a JS novice to understand what we're supposed to be
looking for. Also, the wiki seems to have been refactored; the
original response says "Hint: It's #2" but there is no numbered
anything in the wiki.

So I hereby declare that the original response trigger's Levitt's Law
of Emergent Fish, which states, roughly:

We all know it's better to teach a man to fish, so rather than give
the answer, we often provide hints on how to find it. Unfortunately,
these answers are themselves archived, and over time, they bubble up
to the top of the search results. Due to Murphy's law, the less self-
contained the "how to fish" answer, the more likely it is that it will
end up actually impeding searches for fish.

If I understand correctly, the issue is (roughly) that, starting in
Greasemonkey 0.5, everything you see is really a XPCNativeWrapper, not
itself. Among other things, that prevents you from setting handlers
like onclick or onkeydown directly ("Pitfall #2" in the article).
Instead, you need to use addEventListener, so

button.onclick = func;

becomes

button.addEventListener('click', func, true);

This makes the above "Hello, world!" script run correctly. However, it
does *not* seem to be enough for the Google Search Refiner script. I
named the formerly-anonymous onkeydown handler to keyDownHandler, and
just after its definition, I added

document.addEventListener('keyDown', keyDownHandler, true);

That line does get executed, but keyDownHandler never gets called for
some reason. I haven't investigated this deeply yet, but if anyone
has any ideas, please do let me know.. meanwhile this post will,
hopefully, help a future searcher.

The O'Reilly article *is* a must-read, once you know what you're
looking for, and you *should* read the whole thing:

http://www.oreillynet.com/lpt/a/6257

The complete, non-working Google Search Refiner script follows:
-------------

/*
Authored by John Tokash, Gordon McNaughton and Craig Olrich.

On a google search page, hit ALT-MINUS to exclude the
currently selected text from future searches. Hit ALT-PLUS
to add the selected text to future searches.

*/

// ==UserScript==
// @name Google Search Refiner
// @namespace http://blog.ronin64.com/
// @description Add or Exclude selected text in future searches on a
google search page using ALT-PLUS and ALT-MINUS.
// @include http://*.google.*
// ==/UserScript==

(

function() {
GM_log("jaytest: inside");

function trim(str){
return str.replace(/^\s*|\s*$/g,"");
}

function addToSearchQuery(stringToInsert)
{
var chunks = location.href.split(/&/);
var i;
for(i=0;i<chunks.length;i++)
{
var otherchunks = chunks[i].split(/=/);
if(otherchunks[0]== 'q')
{
chunks[i] += stringToInsert;
}
}
var result = chunks.join("&");
location.href=result;
}

function keyDownHandler(e)
{
GM_log("jaytest: executing handler");
var code;
if (!e) e = window.event;
if (e.keyCode) code = e.keyCode;
else if (e.which) code = e.which;
var character = String.fromCharCode(code);
if ((e.modifiers && (e.modifiers & Event.ALT_MASK)) || e.altKey)

{

var stringToInsert;
var selection = window.getSelection().toString();
if(selection)
{
// TODO: For some reason character becomes 'm'. Must be something
wrong with fromCharCode.
if(character == 'm' || character == '-' || character == '_')
{
addToSearchQuery("+-%22"+trim(selection)+"%22");
}
else if(character == '+' || character == '=')
{
addToSearchQuery("+%22"+trim(selection)+"%22");
}
}
}
}
GM_log("jaytest: adding event handler");
document.addEventListener('keyDown', keyDownHandler, true);
}
)();

Aaron Boodman

unread,
Jan 14, 2008, 12:11:19 PM1/14/08
to greasemon...@googlegroups.com
Sorry Jay, I thought we had this documented multiple places. Using the
on* attributes is one of the classic stumbling blocks for newcomers to
Greasemonkey from javascript. They don't work because of the
XPCNativeWrappers that Greasemonkey uses. If you see "Component not
available", 9 times out of 10 it means you used an on* event
attribute.

Go ahead and add this to the wiki somewhere prominent if you want.

- a

Jay Levitt

unread,
Jan 14, 2008, 5:10:25 PM1/14/08
to greasemonkey-users


On Jan 14, 12:11 pm, "Aaron Boodman" <bo...@youngpup.net> wrote:
> Sorry Jay, I thought we had this documented multiple places.

Yeah, you probably do - it's those damn emergent fish. Also, I expect
you've got it documented in the right places for developers; I was
coming at it from the "Hi, I'm a user, I installed this script from
userscripts.org, it's not working" angle. I need to back up and start
at the beginning, as if there wasn't already such a plugin, and find
out how I would write one.

> Using the on* attributes is one of the classic stumbling blocks for newcomers to
> Greasemonkey from javascript. They don't work because of the
> XPCNativeWrappers that Greasemonkey uses. If you see "Component not
> available", 9 times out of 10 it means you used an on* event
> attribute.

Yes, I see that... now... :) Maybe someone ought to do a sweep of
userscripts.org and just remove or flag the pre-0.5 scripts that still
use that technique. Or maybe someone ought to keep his mouth shut
before people think he's volunteering. Yes, that last one sounds
right.

> Go ahead and add this to the wiki somewhere prominent if you want.

Done!
Reply all
Reply to author
Forward
0 new messages