views:

155

answers:

3

I would like to disable the context menu that appears after a long tap (touch and hold) on images in my web application. I've seen posts with different ideas how to do it, but none of them seem to work for me.

Is there a way to do this on Android via HTML/CSS/Javascript?

A: 
<a id="moo" href=''> </a>

<script type="text/javascript">
    var moo = document.getElementById('moo');

    function handler(event) {
        event = event || context_menu.event;

        if (event.stopPropagation)
            event.stopPropagation();

        event.cancelBubble = true;
        return false;
    }

    moo.innerHTML = 'right-click here';

    moo.onclick = handler;
    moo.onmousedown = handler;
    moo.onmouseup = handler;
</script>

Capture the onContextMenu event, and return false in the event handler.

You can also capture the click event and check which mouse button fired the event with event.button, in some browsers anyway.

RockOn
Sorry, but both of these methods do not work on Android. The oncontextmenu event is never fired, and the click event is not yet fired when the user is touch-holding the element.
Roy Sharon
A: 

Through raw javascript there are no events that get called for the context menu. Perhaps in the Java world there is something... There are actually several issues regarding javascript events (such as focus not working right) in the Android webkit.

Moncader
Yeah, I agree.Since I've developed a JavaScript library that is going to be used inside a browser, using java is not an option for me.
Roy Sharon
+2  A: 

This should work on 1.6 or later (if I recall correctly). I don't believe there's a workaround for 1.5 or earlier.

<!DOCTYPE html>
<html>
<head>
  <script>
    function absorbEvent_(event) {
      var e = event || window.event;
      e.preventDefault && e.preventDefault();
      e.stopPropagation && e.stopPropagation();
      e.cancelBubble = true;
      e.returnValue = false;
      return false;
    }

    function preventLongPressMenu(node) {
      node.ontouchstart = absorbEvent_;
      node.ontouchmove = absorbEvent_;
      node.ontouchend = absorbEvent_;
      node.ontouchcancel = absorbEvent_;
    }

    function init() {
      preventLongPressMenu(document.getElementById('theimage'));
    }
  </script>
</head>
<body onload="init()">
  <img id="theimage" src="http://www.google.com/logos/arthurboyd2010-hp.jpg" width="400">
</body>
</html>
Roman Nurik
Hey there Roman :P
Tegeril
Not seen anything of the OP since Aug 8th, so I decided to test this myself using the SDK. I tested 1.5, 1.6 and 2.2 and it worked just fine on all of them, so I'm happy to award the bounty now without waiting for the OP to confirm. +1 for a good answer, too.
Andy E
Roman, thank you very much for your response. I need to test it (not that I disregard Andy's test, but I've seen many things that work fine with the SDK and then fail on the actual devices). I'm sorry for taking so long to respond but I promise to test this before the weekend. Thanks again to both you and Andy!
Roy Sharon
@Andy -- thanks, @Roy -- sure thing; I tested on a Nexus One, I'd recommend testing on devices with non-standard default Browsers too, @Tegeril -- long time no see!
Roman Nurik
@Roy: you're welcome to use the test that I set up if you like. http://jsfiddle.net/M7pfy/1/ - the top image should cancel the context menu, the bottom image should allow it.
Andy E
@Andy -- thanks again! @Roman -- I've tested your solution using Andy's page on two Motorola Blur models. The one with Android 1.5 worked fine, and the one with 2.1-update1 did not work. Damn. I really wanted this to work. Sometimes I wish that the Android world would have been more like the iPhone world, with its single flavor...So what do I do now in terms of stackoverflow customs: Should I mark Roman's solution as an answer or not? I guess that his idea is the way this should be done, but on the other hand it does not solve my problem... Thanks for the advice.
Roy Sharon
@Roy: that seems really odd, for it to work for me in 1.5, 1.6 and 2.2 but not 2.1 for you. You don't have to accept Roman's answer, although you could accept it and ask another question regarding the problems you're having with the solution. The best idea would be to perform a broader test, if possible - more versions on more devices. Asking another question and providing a link to the example might help here. If it works on other devices, then you know this is the correct solution and the issue is with the device it didn't work on.
Andy E
@Andy: Sounds like a good idea. I've accepted Roman's answer, and will try to perform a broader test. If it seems like a device bug, then so be it. If not, I will post another -- more specific -- question. Thanks again for the warm welcome for a newcomer to stackoverflow!
Roy Sharon