User JavaScript

Last update: 2012-06-02

While User JavaScript is still supported in Opera, extensions are the preferred method for adding custom JavaScript. Support for extensions is more robust and receives frequent updates and enhancements.

Examples of use

Overriding specific variables or functions

A User JavaScript is allowed to override the variables and functions that the page defines in the global scope. This is done using the defineMagicVariable and defineMagicFunction methods. For example, if a site incorrectly identifies Opera, and then attempts to make Opera execute code that was intended for another browser:

var oldBrowser = (navigator.appName != 'Microsoft Internet Explorer'
  && navigator.appName != 'Netscape');
Employing defineMagicVariable()

A user JavaScript may be able to use something like this to override the incorrect detection:

window.opera.defineMagicVariable('oldBrowser', function ()
{
  return false;
}, null);

Whenever a page attempts to access the value of the variable, the function is run instead, and any value it returns is used in place of the variable's actual value.

Employing defineMagicFunction()

Functions defined in the global scope can be overridden with opera.defineMagicFunction(). For example, if a page contains this script for detecting the Flash plug-in with proprietary Internet Explorer ActiveX methods:

function flashDetection()
{
  new ActiveXObject('ShockwaveFlash.ShockwaveFlash');
  return true; // Flash is supported
}

a user script could override it by doing:

opera.defineMagicFunction('flashDetection', function()
{
  return navigator.mimeTypes['application/x-shockwave-flash'] &&
  navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin ?
  true : false;
});

Warning: If the page does not define any such variable or function, calls to opera.defineMagicVariable() and defineMagicFunction() will have no effect.

Loading scripts

To detect when scripts are about to be loaded, interpreted, or run, the window.opera.addEventListener method can be used to detect these events.

User JavaScripts can use the BeforeScript event to detect when a script on a page is about to be interpreted by the JavaScript engine. If needed, the contents of the script can then be rewritten, or prevented from being interpreted.

For example, if a script contains the specific IE's JScript extended syntax for an object method's declaration function object.method(), such code will fail to compile in Opera and other browsers. Therefore, we can use a BeforeScript listener to repair the script's syntax before parsing as in the following code example.

if (location.hostname.indexOf('example.com') != -1)
{
  window.opera.addEventListener('BeforeScript', function (e)
  {
    //simple example
    e.element.text = e.element.text.replace('function window.onload', 'window.onload = function');
    //generic example
    e.element.text = e.element.text.replace(/function\s*(\w(\.\w)+)/, '$1 = function');
  }, false);
}

Overriding events and event handlers

User JavaScripts can use one of the BeforeEvent.type events to detect when a script event is about to happen, even if no script on the page is listening for that event. These can be used to target specific event types, such as BeforeEvent.click.

You can also use BeforeEvent on its own to detect events of any type. Legacy note: In Opera 8 and earlier, this will not fire if you are listening for a more specific BeforeEvent.type. For example, if you listen for BeforeEvent.click, no BeforeEvent events will be fired for click events. Note that since BeforeEvent could detect a substantial number of events, using it may impact performance.

To prevent scripts on the page from being able to detect the onload event, you can use BeforeEvent.load to cancel it. Note that onload fires for other elements as well, such as images, and the script would need to check if the event was for the whole document as shown in the following code example.

if (location.hostname.indexOf('example.com') != -1)
{
  window.opera.addEventListener('BeforeEvent.load', function (e)
  {
    //check that it is the page loading, not just an image
    if (e.event.target instanceof Document)
    {
      e.preventDefault();
    }
  }, false);
}

In many cases, the BeforeEventListener events may be more useful, as they will only fire if a script on the page is listening for those events. They provide access both to the event object, and the event handler function. The events can be canceled using preventDefault.

These events can also be detected more specifically using BeforeEventListener.type, in the same way as you can use BeforeEvent.type instead of BeforeEvent. For example, to prevent a script from monitoring mouse movements:

if (location.hostname.indexOf('example.com') != -1)
{
  window.opera.addEventListener('BeforeEventListener.mousemove', function (e)
  {
    e.preventDefault();
  }, false);
}

You can also more carefully target the functionality that needs to be removed. In this example, the User JavaScript checks if the event handler is the myMouseTrail function provided by the page. It then alters the event object to pretend that the mouse position is at the top of the page:

if (location.hostname.indexOf('example.com') != -1)
{
  window.opera.addEventListener('BeforeEventListener.mousemove', function (e)
  {
    if (e.listener == moveMouseTrail)
    {
      e.event.clientY = 0;
      e.event.pageY = 0;
    }
  }, false);
}

The AfterEvent event allows a User JavaScript to check if a script on the page has canceled an action. When an action has been prevented, the User JavaScript can override the cancellation, and allow the action to be performed.

For example, when you submit a form, the default action is for the form to be submitted, and a new page retrieved from the server. If a script on the page intercepts the submit event, it can validate the form, and only allow the form to be submitted if it has successfully validated. If a validation script is incorrectly saying the form has not been filled out correctly, and as a result is not allowing the form to be submitted, a User JavaScript can detect when that happens and prevent the script from being able to stop the form submission:

if (location.hostname.indexOf('example.com') != -1)
{
  window.opera.addEventListener('AfterEvent.submit', function (e)
  {
    if (e.eventCancelled)
    {
      //the script has tried to stop the form submission
      if (confirm('Submission was prevented. Submit anyway?'))
      {
        //prevent the script from preventing the form submission
        e.preventDefault();
      }
    }
  }, false);
}

JavaScript URLs

Pages can also use JavaScript URLs as a way of initiating scripts, such as having the JavaScript contained within the HREF attribute of a link, or the TARGET attribute of a form. User JavaScripts can detect when this is being activated, and prevent it, or rewrite the script that is about to run. Note that this also affects bookmarklets using the javascript: protocol.

For example, if a page uses a JavaScript URL to open a new window, a User JavaScript can use the BeforeJavascriptURL event to rewrite it so that it displays a confirmation dialog before opening the window.

if (location.hostname.indexOf('example.com') != -1)
{
  window.opera.addEventListener('BeforeJavascriptURL', function (e)
  {
    if (e.source.indexOf('window.open') != -1)
    {
      //rewrite the script to confirm before opening windows
      e.source = e.source.replace(/window\.open/g, 'if( confirm(\'Allow window to open?\') ) window.open');
    }
  }, false);
}

JavaScript URLs may also return a value. A page may intentionally use this value to overwrite itself with new content, but may occasionally return a value by mistake and incorrectly overwrite page content. A User JavaScript can intercept this returned value using the AfterJavascriptURL event and display a confirmation dialog before writing the new content. It can also rewrite the new content if needed.

if (location.hostname.indexOf('example.com') != -1)
{
  window.opera.addEventListener('AfterJavascriptURL', function (e)
  {
    if (typeof(e.returnValue) == 'string')
    {
      if (confirm('Overwrite page?'))
      {
        e.returnValue += 'Changed by User JavaScript';
      }
      else
      {
        e.preventDefault();
      }
    }
  }, false);
}

Normal scripts and events

User JavaScripts do not have to rely on these special events, and can also accept normal scripting. For example, to display a notice on every page saying what rendering mode Opera is using (QuirksMode or CSS1Compat), you could use the following code:

addEventListener('load', function (e)
{
  if (!document.body)
  {
    return;
  }
  var mydiv = document.createElement('div');
  mydiv.style.position = 'fixed';
  mydiv.style.top = '0px';
  mydiv.style.right = '0px';
  mydiv.style.border = '1px solid #000';
  mydiv.style.backgroundColor = '#fff';
  mydiv.style.color = '#000';
  mydiv.appendChild(document.createTextNode(document.compatMode))
  document.body.appendChild(mydiv);
}, false);

Greasemonkey scripts

Opera is capable of running many Greasemonkey scripts. These are JavaScripts designed to work with the Greasemonkey enhancement for the Mozilla browser family. To tell Opera that a script file uses Greasemonkey notation, the name of the file containing the script must end with .user.js (all other .js files are assumed to be normal User JavaScripts). Scripts that use Greasemonkey notation are handled slightly differently (in order to be compatible with existing scripts):

Because of this different handling, Greasemonkey scripts are often not able to fix problems or errors until after they have already occurred. As a result, such scripts are generally best suited to adding enhancements, and not fixing problematic scripts.

Although it is possible to use a normal page address detect, Greasemonkey scripts will typically use the ==UserScript== comment block to restrict the page addresses where the script will be executed. In general, the JavaScript code for each enhancement is contained within its own file, although this is not a necessity.

Since the script will be executed immediately prior to running any onload event handlers, it can be written inline, but to avoid creating global variables, it is best to use an anonymous function that is immediately activated. For example, to prevent a page from using target="_blank" to open links in new pages, you could use the following script:

(function ()
{
  for (var i = 0; document.links[i]; i++)
  {
    if (document.links[i].target == '_blank')
    {
      document.links[i].target = '_self';
    }
  }
})();

Using Greasemonkey notation is equivalent to creating a BeforeEvent.load event listener in a normal User JavaScript, as shown in the section on overriding events and event handlers.

Tip: many Greasemonkey scripts use window._content to reference the window object. This is unnecessary in Opera, but to save editing every file that uses it, you can simply add the following code to a normal User JavaScript file.

window._content = window;

User JavaScript can override history navigation mode in Opera, to set it to be always fast, or always compatible. For more details of these modes, see our knowledge base article. These modes can be set using the setOverrideHistoryNavigationMode method.

opera.setOverrideHistoryNavigationMode('fast')

Documentation

Opera Help

Need help? Hit F1 anytime while using Opera to access our online help files, or go here.