Advanced User JavaScript: event handling
Thursday, March 17, 2005 10:12:10 AM
Any script can ask Opera to be notified when a specific event occurs, for instance a mouse click on a button. By using the special User JavaScript events your user script can ask Opera to be notified in advance of the page script. The user script can then either cancel the event, change the event or allow the page script to receive it unchanged.
Opera also can notify the user script about special events that normal scripts can not detect, such as when an external JavaScript library will be loaded.
How to use User JavaScript event handling
A user JavaScript can add event listeners to the window.opera object with the command window.opera.addEventListener(). The following new events are available to allow the user script to enhance and control the environment:
BeforeExternalScript
This event takes place before Opera loads an external JavaScript file.
BeforeScript / AfterScript
These events happen before and after any SCRIPT tag is ran.
BeforeEvent / AfterEvent
BeforeEventListener / AfterEventListener
These are 'meta-events' you can use to either be notified in advance or after about every event taking place in the document, or every event that the scripts in the page will use.
To the 'meta-events' you can add .TYPE to detect specific events only, for instance BeforeEventListener.load . This is the preferred way of using these events because a generic handler will be called a lot - for instance every time you move the mouse.
Cancelling events with event.preventDefault() in the event handler stops the default action. If you cancel 'Before' script notification events, scripts will not be loaded or ran. If you cancel 'meta-events' the page script will not receive the real events. (If this explanation is too confusing see the examples!
)
Writing User JavaScript event handlers
The event handler function receives an object with information about the event. The function can check various properties of this object to get information about the event. The element property tells you what element the event is happening to, and the event property is the event object that will be passed to the page's script.
Examples
1
To prevent the script on a page from running its onload handler you could add the following to a User JavaScript:
opera.addEventListener('BeforeEventListener.load', function(ev){ ev.preventDefault(); }, false);
2
Say you have a form with an onsubmit handler that prevents Opera from sending the form:
<form action=''http://example.com'' onsubmit=''return false;''>
The event.preventDefault() in the following example will cancel the return false from the page's script because the page's onsubmit event handler will not be called:
opera.addEventListener('BeforeEvent.submit', function(ev){ ev.preventDefault(); }, false);
3
The following user script will fix a buggy DHTML script on <http://www.thegreenbutton.com/downloads.aspx> by rewriting the script source code with a regular expression:
if(window.location.href.indexOf('thegreenbutton.com')>-1){
window.opera.addEventListener( 'BeforeScript', function (ev){ev.element.text = ev.element.text.replace(/!=
null/g,''); },false);
}









Marek Pawłowskilockoom # Thursday, March 17, 2005 10:12:10 AM
But why there is no complementary AfterExternalScript event? Especially that Opera does not support onload event for <script>...
scipio # Thursday, March 17, 2005 10:12:10 AM
jimjjewett # Thursday, March 17, 2005 10:12:10 AM
In that same location, it would be good to link to a very basic javascript intro that does show how to register for an event.
Hallvord R. M. Steenhallvors # Thursday, March 17, 2005 10:12:10 AM
Marek Pawłowskilockoom # Thursday, March 17, 2005 10:12:10 AM
http://my.opera.com/forums/showthread.php?s=&postid=870518#post867265
I create <script> element to download Google Suggest engine. After that I have to run engine via InstallAC function. As you may see I've done a nasty hack by adding <script> element right after document.body is available in DOM and registering 'load' eventlistener that triggers 'InstallAC'.
Obviously 'setTimeout' is not a good solution.
Mark 'Tarquin' Wilton-Jonestarquinwj # Thursday, March 17, 2005 10:12:10 AM
scipio # Thursday, March 17, 2005 10:12:10 AM
Hallvord R. M. Steenhallvors # Thursday, March 17, 2005 10:12:10 AM
I could also have omitted the argument part and just used the global "event" property as in function(){event.preventDefault()} but this is an IEism AFAIK. I recommend you write event handlers that take one argument.
Was that making things any clearer?
Hallvord R. M. Steenhallvors # Thursday, March 17, 2005 10:12:10 AM
You might set up a while loop doing nothing, but I'm not sure if I like that idea - if for some reason the external file failed to load Opera would be stuck in that loop forever.
x.type = 'text/javascript';
x.src = '/ac.js';
document.body.insertBefore(x, document.body.firstChild);
// Empty while loop example below
while (typeof(InstallAC) == 'undefined');
var googleFrm = (document.gs ? document.gs : document.f);
InstallAC(googleFrm, googleFrm.q, googleFrm.btnG, 'search', 'en');
Perhaps experiment with adding an AfterScript event handler that calls InstallAC and removes itself?
scipio # Thursday, March 17, 2005 10:12:10 AM
scipio # Thursday, March 17, 2005 10:12:10 AM
Arve Bersvendsenvirtuelvis # Thursday, March 17, 2005 10:12:10 AM
I have written Google Labs, asking permission to release this script, but they have not responded so far.
Side-question: Does the event.element act like any other DOM node:
* Is reading properties/attributes of the script element possible, such as source, type, language, defer and anything else added to it?
Marek Pawłowskilockoom # Thursday, March 17, 2005 10:12:10 AM
What do you mean "adding an AfterScript event handler that calls InstallAC and removes itself"? I thought that AfterScript runs right after the closing tag is parsed. I don't think this will do the job for external scripts (I mean it wont wait until script is loaded) but I'll check it.
Marek Pawłowskilockoom # Thursday, March 17, 2005 10:12:10 AM
As for the event.element, for my experience it's a fully functional node.
Arve Bersvendsenvirtuelvis # Thursday, March 17, 2005 10:12:10 AM
(The general advice, though, if you want to try yourself: The Greasemonkey extension for Google Suggest works, with some conceptual alterations, since Opera doesn't support XPath).
Hallvord R. M. Steenhallvors # Thursday, March 17, 2005 10:12:10 AM
function InstallGoogleAutoComplete(){
if(typeof(InstallAC)!='undefined'){
var googleFrm = (document.gs ? document.gs : document.f);
InstallAC(googleFrm, googleFrm.q, googleFrm.btnG, 'search', 'en');
opera.removeEventListener('AfterScript', InstallGoogleAutoComplete, false); /* Event listener no longer required */
}
}
opera.addEventListener('AfterScript', InstallGoogleAutoComplete, false);
x.type = 'text/javascript';
x.src = '/ac.js';
document.body.insertBefore(x, document.body.firstChild);
Hallvord R. M. Steenhallvors # Thursday, March 17, 2005 10:12:10 AM
Yes. On one point User JS has wider powers than a normal script: it can read event.element.text even if the element in question has loaded its content from another domain. Apart from that everything is the same as normal DOM scripting.