Important notes

MozAfterPaint is a Gecko-only event, and for compatibility (and performance) reasons should not be used outside chrome code, such as extensions.

For security reasons, regular Web content is only notified of repainting that occurred in its own document. Repainting caused by iframes is not reported to untrusted listeners. Listeners added by trusted content, such as extensions or other chrome code, are notified of all repaints.

If your event handler does anything that triggers repainting, such as changing the style of an element, you will probably trigger an infinite loop. So please don't do that.

Repainting of areas scrolled outside the viewport is reported, but repainting of areas scrolled outside overflow:auto elements and the like is not.

Repainting in windowed plugins (which is most plugins on Windows and GTK) is not reported.

{{ gecko_callout_heading("2.0") }}

The MozAfterPaint event is no longer sent to web content by default for the time being; it is still sent to chrome, however (there is a potential security issue; see {{ bug("608030") }} for details). Until that's resolved, you can enable delivery of MozAfterPaint by setting the preference dom.send_after_paint_to_content to true.

Possible uses

There are several situations in which MozAfterPaint can be useful. For example, you can use it in an extension that wants to capture the contents of a window using it in tandem with the canvas.drawWindow() method. You can also use it while testing web content to add JavaScript instrumentation to measure what gets painted by Firefox and when, in order to optimize your site.

Example

This example adjusts the background color of elements that get painted, making them increasingly darker red each time they're updated.

Line 4 installs the event listener to watch for MozAfterPaint events; when the event fires, the log() function gets called.

Lines 11-13 contain the log() function, which pushes the rectangle list for each update onto a stack for later reference; the actual DOM changes are done after the logging is complete, in order to avoid an infinite loop caused by repaints while logging repaints.

Line 16 installs a click event listener. When the user finishes mousing around the window, causing repaints as they hover over various elements, clicking the mouse will cause the actual drawing of the results.

Line 17, the first line of the click event handler, removes the MozAfterPaint event handler. This is done before any changes to the document in order to avoid the previously-mentioned infinite loop problem.

Lines 19-37 add div elements to the DOM for each painted rectangle, overlaying them on top of the painted content with a pale, translucent red background.

To use this example, you can create a bookmarklet containing the following code:

axis specifies the axis of the scroll gesture (horizontal or vertical). This attribute was added in Firefox 3.5 ({{ Bug("378028") }}).

In addition to these attributes, DOMMouseScroll events also have all the attributes of a regular mouse event.

Starting in Gecko 1.9.2, this is correctly classified as a mouse event, so that event properties are available. See {{ interface("nsIDOMMouseScrollEvent") }} for details on the changes to inheritance.

Determining the scroll direction

If e is a DOMMouseScroll event, e.axis will be equal to:

undefined prior to Firefox 3.5,

e.HORIZONTAL_AXIS for horizontal scroll movement or

e.VERTICAL_AXIS for vertical scroll movement.

MozMousePixelScroll

{{ fx_minversion_note("3") }}

Regular mouse wheels can only scroll with a per-line resolution. However, there are also devices that support scrolling with pixel precision, notably Apple MacBook trackpads.

When we started supporting pixel scrolling in {{ Bug("350471") }}, we added the MozMousePixelScroll event. It basically works exactly like DOMMouseScroll, with the difference that the detail attribute is in pixels (instead of lines).

For backwards compatibility DOMMouseScroll events are sent even if pixel scrolling is used. Every DOMMouseScroll event can have several associated MozMousePixelScroll events. If preventDefault() is called on the DOMMouseScroll event, the following associated MozMousePixelScroll events won't cause any scrolling.

When you listen for MozMousePixelScroll events, you shouldn't handle DOMMouseScroll events - otherwise you'd end up processing the same scroll gesture twice. In order to make it possible to only listen for MozMousePixelScroll events, Gecko will send MozMousePixelScroll events even when scrolling with regular mouse wheels. These events will carry a meaningful pixel delta.

See also

Revision Source

<h2>DOMFrameContentLoaded</h2>
<p>Same as {{ domeventxref("DOMContentLoaded") }}, but also fired for enclosed frames.</p>
<h2>DOMWindowClose</h2>
<p>Fired when the window is about to be closed by {{ domxref("window.close()") }}. See {{ Bug("103452") }}.</p>
<p>{{ h1_gecko_minversion("MozAfterPaint", "1.9.1") }}</p>
<p>The <code>MozAfterPaint </code>event is fired whenever content is repainted. It is sent to the document and bubbles up to the window level.</p>
<p><code>MozAfterPaint</code> has two attributes:</p>
<ul> <li><code>clientRects</code></li> <li><code>boundingClientRect</code></li>
</ul>
<p>These tell you what area was repainted, using the same objects and coordinate system as the <a class="internal" href="/en/DOM/element.getClientRects" title="En/DOM/Element.getClientRects"><code>getClientRects()</code></a> and <a class="internal" href="/en/DOM/element.getBoundingClientRect" title="En/DOM/Element.getBoundingClientRect"><code>getBoundingClientRect()</code></a> methods.</p>
<h3>Important notes</h3>
<ul> <li><code>MozAfterPaint</code> is a Gecko-only event, and for compatibility (and performance) reasons should not be used outside chrome code, such as extensions.</li> <li>For security reasons, regular Web content is only notified of repainting that occurred in its own document. Repainting caused by iframes is not reported to untrusted listeners. Listeners added by trusted content, such as extensions or other chrome code, are notified of all repaints.</li> <li>If your event handler does anything that triggers repainting, such as changing the style of an element, you will probably trigger an infinite loop. So please don't do that.</li> <li>Repainting of areas scrolled outside the viewport is reported, but repainting of areas scrolled outside <code>overflow:auto</code> elements and the like is not.</li> <li>Repainting in windowed plugins (which is most plugins on Windows and GTK) is not reported.</li>
</ul>
<div class="geckoVersionNote"> <p>{{ gecko_callout_heading("2.0") }}</p> <p>The <code>MozAfterPaint</code> event is no longer sent to web content by default for the time being; it is still sent to chrome, however (there is a potential security issue; see {{ bug("608030") }} for details). Until that's resolved, you can enable delivery of <code>MozAfterPaint</code> by setting the preference <code>dom.send_after_paint_to_content</code> to <code>true</code>.</p>
</div>
<h3>Possible uses</h3>
<p>There are several situations in which <code>MozAfterPaint</code> can be useful. For example, you can use it in an extension that wants to capture the contents of a window using it in tandem with the <a class="internal" href="/en/Drawing_Graphics_with_Canvas#Rendering_Web_Content_Into_A_Canvas" title="en/Drawing Graphics with Canvas#Rendering Web Content Into A Canvas"><code>canvas.drawWindow()</code></a> method. You can also use it while testing web content to add JavaScript instrumentation to measure what gets painted by Firefox and when, in order to optimize your site.</p>
<h3>Example</h3>
<p>This example adjusts the background color of elements that get painted, making them increasingly darker red each time they're updated.</p>
<pre class="brush: js">(function(){
var store = [];
window.addEventListener("MozAfterPaint", log, false);
if ( document.body )
bind();
else
window.addEventListener("load", bind, false);
function log(e){
store.push( [(new Date).getTime(), e.clientRects] );
}
function bind(){
document.body.addEventListener("click", function(){
window.removeEventListener("MozAfterPaint", log, false);
for ( var pos = 0; pos &lt; store.length; pos++ ) {
var rects = store[pos][1];
for ( var i = 0; i &lt; rects.length; i++ ) {
var rect = rects[i];
var div = document.createElement("div");
with (div.style) {
background = "red";
opacity = "0.1";
position = "absolute";
top = rect.top + "px";
left = rect.left + "px";
width = (rect.right - rect.left) + "px";
height = (rect.bottom - rect.top) + "px";
}
document.body.appendChild( div );
}
}
document.body.removeEventListener("click", arguments.callee, false);
}, false);
}
})();
</pre>
<p>The most interesting bits of this example:</p>
<ul> <li>Line 4 installs the event listener to watch for <code>MozAfterPaint</code> events; when the event fires, the <code>log()</code> function gets called.</li> <li>Lines 11-13 contain the <code>log()</code> function, which pushes the rectangle list for each update onto a stack for later reference; the actual DOM changes are done after the logging is complete, in order to avoid an infinite loop caused by repaints while logging repaints.</li> <li>Line 16 installs a click event listener. When the user finishes mousing around the window, causing repaints as they hover over various elements, clicking the mouse will cause the actual drawing of the results.</li> <li>Line 17, the first line of the click event handler, removes the <code>MozAfterPaint</code> event handler. This is done before any changes to the document in order to avoid the previously-mentioned infinite loop problem.</li> <li>Lines 19-37 add <a class="internal" href="/en/HTML/Element/div" title="En/HTML/Element/Div"><code>div</code></a> elements to the DOM for each painted rectangle, overlaying them on top of the painted content with a pale, translucent red background.</li>
</ul>
<p>To use this example, you can create a bookmarklet containing the following code:</p>
<pre>javascript:(function(s){s.src='http://developer.mozilla.org/@api/deki/files/2937/=track.js';document.body.appendChild(s);})(document.createElement('script'));
</pre>
<h2>DOMMouseScroll</h2>
<p>The <code>DOMMouseScroll</code> event is sent when the mouse wheel is moved. The target of this event is the element that was under the mouse pointer when the mouse wheel was scrolled, similar to the click event.</p>
<p>The most important attributes of a <code>DOMMouseScroll</code> event are <code>detail</code> and <code>axis</code>:</p>
<ul> <li><code>detail</code> specifies the number of “ticks” that the mouse wheel moved. Positive values mean “down” / “right”, negative “up” / “left”.</li> <li><code>axis</code> specifies the axis of the scroll gesture (horizontal or vertical). This attribute was added in Firefox 3.5 ({{ Bug("378028") }}).</li>
</ul>
<p>In addition to these attributes, <code>DOMMouseScroll</code> events also have all the attributes of a regular mouse event.</p>
<p>Starting in Gecko 1.9.2, this is correctly classified as a mouse event, so that event properties are available. See {{ interface("nsIDOMMouseScrollEvent") }} for details on the changes to inheritance.</p>
<h3>Determining the scroll direction</h3>
<p>If <code>e</code> is a <code>DOMMouseScroll</code> event, <code>e.axis</code> will be equal to:</p>
<ul> <li><code>undefined</code> prior to Firefox 3.5,</li> <li><code>e.HORIZONTAL_AXIS</code> for horizontal scroll movement or</li> <li><code>e.VERTICAL_AXIS</code> for vertical scroll movement.</li>
</ul>
<h2>MozMousePixelScroll</h2>
<p>{{ fx_minversion_note("3") }}</p>
<p>Regular mouse wheels can only scroll with a per-line resolution. However, there are also devices that support scrolling with pixel precision, notably Apple MacBook trackpads.</p>
<p>When we started supporting pixel scrolling in {{ Bug("350471") }}, we added the <code>MozMousePixelScroll</code> event. It basically works exactly like <code>DOMMouseScroll</code>, with the difference that the <code>detail</code> attribute is in pixels (instead of lines).</p>
<p>For backwards compatibility <code>DOMMouseScroll</code> events are sent even if pixel scrolling is used. Every <code>DOMMouseScroll</code> event can have several associated <code>MozMousePixelScroll</code> events. If <code>preventDefault()</code> is called on the <code>DOMMouseScroll</code> event, the following associated <code>MozMousePixelScroll</code> events won't cause any scrolling.</p>
<p>When you listen for <code>MozMousePixelScroll</code> events, you shouldn't handle <code>DOMMouseScroll</code> events - otherwise you'd end up processing the same scroll gesture twice. In order to make it possible to only listen for <code>MozMousePixelScroll</code> events, Gecko will send <code>MozMousePixelScroll</code> events even when scrolling with regular mouse wheels. These events will carry a meaningful pixel delta.</p>
<p>See the <a class="external" href="http://hg.mozilla.org/mozilla-central/rev/93f23e3efbb4#l15.30" title="Event flow comment in the changeset">comment in the code</a> for details on the event flow.</p>
<h2>Others</h2>
<p>There appear to be many other sparsely documented events. See {{ Bug("286013") }}:</p>
<ul> <li>DOMLinkAdded (when a &lt;link/&gt; element is added to the page; e.g., used internally for processing RSS)</li> <li>DOMLinkRemoved</li> <li>DOMMetaAdded</li> <li>DOMMetaRemoved</li> <li>DOMWillOpenModalDialog</li> <li>DOMModalDialogClosed</li> <li>fullscreen</li> <li>PopupWindow</li> <li>DOMTitleChanged</li> <li>PluginNotFound</li> <li>ValueChange</li> <li>DOMMenuItemActive</li> <li>windowZLevel</li>
</ul>
<h2>Example</h2>
<pre class="eval">window.addEventListener("DOMFrameContentLoaded", myeventhandler, true);
</pre>
<h2>See also</h2>
<ul> <li><a href="/en/DOM/element#Event_Handlers" title="en/DOM/element#Event_Handlers">DOM Reference: Event Handlers</a> (on*)</li> <li><a href="/en/DOM/DOM_event_reference" title="en/DOM/DOM_event_reference">DOM event reference</a></li> <li><a href="/en/XUL/Events" title="en/XUL/Events">XUL Events</a></li>
</ul>
<p>{{ languages( { "ja": "ja/Gecko-Specific_DOM_Events" } ) }}</p>