jQuery: preventDefault() not working on input/click events?

Jason picture Jason · Apr 29, 2010 · Viewed 17.3k times · Source

I want to disable the default contextMenu when a user right-clicks on an input field so that I can show a custom contextMenu. Generally speaking, its pretty easy to disable the right-click menu by doing something like:

$([whatever]).bind("click", function(e) { e.preventDefault(); });

And in fact, I can do this on just about every element EXCEPT for input fields in FF - anyone know why or could point me towards some documentation?

Here is the relevant code I am working with, thanks guys.

HTML:

<script type="text/javascript">
 var r = new RightClickTool();
</script>

<div id="main">
  <input type="text" class="listen rightClick" value="0" />  
</div>

JS:

function RightClickTool(){

var _this = this;
var _items = ".rightClick";

$(document).ready(function() { _this.init(); });

this.init = function() {
 _this.setListeners(); 
}

this.setListeners = function() {
 $(_items).click(function(e) {
  var webKit = !$.browser.msie && e.button == 0;
  var ie = $.browser.msie && e.button == 1;

  if(webKit||ie)
  { 

   // Left mouse...do something()

  } else if(e.button == 2) {
   e.preventDefault(); 

   // Right mouse...do something else();
  }

 });
}

} // Ends Class

EDIT:

Sorry, after reading the comments I realize that I should clarify a few things.

1) The code above does work...in a sense. The code is able to sort through which button was clicked, it just doesn't care that I say e.preventDefault() and the right-click menu still pops up. In other words, if you put an alert on e.button you would get your 1 or 0 for left and 2 for right...but it just laughs at me and still shows the damned default menu!

2) If I put the jQuery selector on ANY other element (other than input) then everything will work, FF will respect the preventDefault() call and the default right-click menu will not show.

Answer

Wayne picture Wayne · Jun 9, 2011

A cross-browser solution to disable the default context menu:

window.oncontextmenu = function() { return false };

To capture the contextmenu event only inside a given element use:

document.getElementById('myElement').oncontextmenu=function(){

    // Code to handle event
    return false;
}

You will get different results depending on the exact event scenario and browser if you try methods other than oncontextmenu for interrupting a right-click event.

In jQuery:

$('myElement').bind('contextmenu', function(){

    // Handle right-click event.
    return false;
});

You can also use jQuery's event.which to determine which button was pressed, but you will still have to cancel the default contextmenu event:

   // Cancel default oncontextmenu event.
    $(element).bind('contextmenu', function(){ return false });

    $(element).mousedown(function(event){

        switch (event.which)

            case 1:
            // Left mouse
            break;

            case 2:
            // Middle mouse
            break;

            case 3:
            // Right mouse.
            break;

    });

I've tested this in IE6 (under Wine), Chrome 11, Firefox 3.6, Opera 11 and Safari.