[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);
}
)();