views:

165

answers:

3

I'm trying to write a function that reads the oncontextmenu event for a div item. (I need it to find out whether the ctrl key was being pressed, e.g. by using e.ctrlKey.)

This works:

<div id="item_2" class="lineitem" align=center oncontextmenu="alert('foo');">test</div>

But this does not:

<script language="JavaScript">
function asdf(e){
    alert('foo');
}
</script>
<div id="item_2" class="lineitem" align=center oncontextmenu=asdf>test</div>

What do I need to do to fix the second one?

Thanks.

+1  A: 
oncontextmenu="asdf()"

should work, doesn't it?

peter p
This should do the job.
Pekka
yes, but I need asdf() to take the event as an input (so that I can check to see if ctrl was being held down).
unsorted
A: 
oncontextmenu="asdf()"

You can't assign predefined functions directly using attribute values. Only anonymous functions (where function () { and } are replaced with attribute=" and ". This makes it rather difficult to trap the event object (maybe impossible, it isn't something I've ever felt the need to investigate).

If you want to assign the function directly, do it using JavaScript with attachEvent/addEventListener.

David Dorward
woohoo! addEventListener worked; thanks. for future reference, here is the solution which allows me to trap the event: function load() { var el = document.getElementById("item_2"); el.addEventListener("contextmenu", asdf, false); } <body onload="load();">
unsorted
`arguments[0]` in an event listener attribute is the event object.
Eli Grey
+1  A: 
<div oncontextmenu="asdf(event)">

<script type="text/javascript">
    function asdf(event){
        if (event.ctrlKey)
            alert('foo');
    }
</script>

Why this works: inside the anonymous function created by an event handler attribute string, there is a local variable event initialised to point to the Event instance. IE has a broken event model, but this code still works because the event now refers not to a local variable but the window.event global.

However you would generally want to avoid event handler attributes these days. Better to assign event handlers from script itself, eg.:

<div id="thing">

<script type="text/javascript">
    document.getElementById('thing').oncontextmenu= function(event) {
        if (event===undefined) event= window.event; // fix for IE
        if (event.ctrlKey)
            alert('foo');
    };
</script>

Putting it in script also means your HTML stays validatable. (oncontextmenu is an IE extension that won't be standardised until HTML5.)

You can also migrate the same function to addEventListener, but note that IE doesn't support it so you need to sniff for the presence of addEventListener and if missing use the IE-specific attachEvent instead. If you don't need multiple handlers for the same event on the same object it is easier (and more compatible with ancient browser) to just use the old-school onevent-style handlers instead.

Note that contextmenu is an unreliable event. It isn't supported in all browsers, may be disabled or may always still bring up the browser's real context menu, and on a Mac a common way to get it is with Control-click, which may confuse your check for ctrlKey. Plus of course there are accessibility issues. Use context menus in web applications as a shortcut feature only, not as an essential access method.

bobince
Eli Grey
Is there any browser where that is required? As I remember it, the first argument being named `event` is something that was specified by JavaScript 1.2 when event objects were introduced in Netscape 4.0, and has been copied by every browser since (except IE of course, whose `window.event` mess appears to stem from a misunderstanding of why `onclick="f(event)"` is supposed to work).
bobince