Saturday, January 26, 2008

The onContextMenu Event Handler

onContextMenu event does not fire on disabled fields


The onContextMenu event (right-click in Windows) is a proprietary handler in HTML, but is very useful for displaying custom context menus on web pages. For this particular article, I was investigating an application where the business owner wanted a context menu available on disabled fields. The problem specifically occurs because all click events are apparently ignored on disabled fields. Note that Opera apparently ignores the onContextMenu event completely, because it is not a W3C compliant attribute.


Regardless of the W3C non-compliance, the business still wanted this behavior (as far as we know everyone is using IE or FF). Try the following in your browser to see how it behaves.













<input id="input1" type="text" value="input1" oncontextmenu="alert('input1');return false;" />

Attempt 1: Nest it in a div


The first thing we tried was to wrap the input fields in a div element that had an onContextMenu attribute defined. We found that while this solved the problem in IE7, FF did not "bubble up" the event through the disabled input field. However, any text inside the div element did respond to the onContextMenu event. Try the following in your browser to see how it behaves.





Inside div, outside input3 field





Inside div, outside input4 field





<div oncontextmenu="alert('input3');return false;">Inside div, outside input3 field

<input id="input3" type="text" value="input3" />

</div>

Solution 1: Convert from disabled to read-only


After a little more research, I found another attribute named "readonly" that I had not used before. I tried it, and found that the onContextMenu event worked just fine in both IE7 and FF.









Inside div, outside input6 field





<input id="input5" type="text" value="input5" readonly="readonly" oncontextmenu="alert('input5');return false;" />

Solution 2: Make an external, clickable object


I definitely prefer W3C compliant code, however, so a compliant solution would have to involve an external, clickable element to trigger the event. The » symbol below has an onClick event, which works in IE, FF, and Opera.





»



<input id="input7" type="text" value="input7" disabled="disabled" /> <span onclick="alert('input7');return false;" style="cursor:pointer;">&raquo;</span>

There are some accessibility issues with this approach, of course. One might want to use a link instead of a span to underline the clickable element or choose a more obvious graphical symbol. There are other inherent accessibility issues with the entire context menu approach, but I will not go into those here.

2 comments:

Maris Radu said...

I wonder, have you try 3 div's, one wraper that contains another one with the input field and the second with z-index higher so events go to the third.

Cannot paste html so i wrote an _ (underscore) inside the tags, hope this do the trick :)


<_div style = " position:absolute; top:20px; left:20px; width:250px; height:30px; " _>
<_div style="position: absolute; top:0px; left: 0px; width:100%; height:100%; z-index:1;" _>
<_input id="input1" type="text" value="input1" disabled="disabled"/_>
<_/div_>
<_div style="position:absolute; top:0px; left: 0px; z-index:2; min-width: 100%; min-height:100%;" oncontextmenu="alert('input1');return false;" _>
<_input type="text" style="display:none" /_>
<_/div_>
<_/div_>

Maris Radu said...

Forgot to mention that I test this code and work's.
The input in the third div is used just for dimension purposes (a quick workaround), so that the second and the third div have the same width and height, it has a display:none, so it does't mess with our events :)

And the best part is that this code is W3 compliant, so it has to work in all browsers that are W3 compilant (I tested it in Firefox 3.5.5)