12

When using ctrl+ click to fire a contextmenu event (Context.JS) in Safari on Mac OS 10.9, the mousedown/up/click events also fire. This causes the menu to be closed. The events seem to occur asynchronously in relation to one another, so stopPropagation doesn't work and this also seems to result in intermittent behaviour, sometimes it's fine sometimes it's not.

Has anyone else come across this problem, if so did you & how did you resolve it / work around it?

Unfortunately I'm not in a position to release the code to the masses, but I am hoping it sounds familiar to somebody out there.

fiddle: http://jsfiddle.net/gnh2tuyj/

Alex
  • 66,732
  • 177
  • 439
  • 641
GarethPN
  • 432
  • 4
  • 11
  • I did and ended up adding a setTimeout call and disabling my click handler if the timeout function is still running I know its ugly :| – Alex Jan 15 '15 at 20:18
  • have you found a solution to this yet? I'm intrigued :) – Ballard Jan 18 '15 at 15:42

3 Answers3

12

You could make use of the ctrlKey property of the MouseEvent :

var div = document.querySelector('div');
div.addEventListener('click', function(e) {
  if (e.ctrlKey) return;
  e.preventDefault();
  alert('click!');
}, false);

div.addEventListener('contextmenu', function(e) {
  e.preventDefault();
  alert('context menu!');
}, false);
div {
  border: 1px solid red;
}
<div>hold ctrl+click in safari, chrome, etc</div>

So if you want to patch the context.js yourself, just add if(ctrlKey) return; l24.

l23    $(document).on('click', 'html', function (e) {
l24    if(e.ctrlKey) return;
l25    $('.dropdown-context').fadeOut(options.fadeSpeed, function(){
l26     $('.dropdown-context').css({display:''}).find('.drop-left').removeClass('drop-left');
l27     });
l28    });

patched script : http://pastebin.com/6ySveRty

Kaiido
  • 123,334
  • 13
  • 219
  • 285
  • 1
    but what if you need to catch the ctrl-click too? – Alex Jan 17 '15 at 00:44
  • @Alex What is the actual scenario? Do you need to sometimes detect ctrl+click as a click and somtimes as a contextmenu? In that case you have to set an other flag that will block the contextmenu and do the click instead. – Kaiido Jan 17 '15 at 01:15
  • 1
    catch the click and ctrl-click, but also able to tell if contextmenu was fired normally (not from ctrl-click). Your solution seems to block ctrl-clicks completely, not just the ones coming from safari – Alex Jan 19 '15 at 10:16
  • 1
    yes this solution blocks ctrl-click for any browser, but only in the click event (which doesn't fire anyway in other browsers). You could make a catch like `if(navigator.platform.indexOf('Mac')!==-1) if(e.ctrlKey) return;` to only apply it on mac systems, but I'm not sure it's really useful… to check if the contextmenu was fired by a *normal* right click, you can use the same logic : inside the contextmenu caller, `if(e.ctrlKey){ alert('called via ctrl+click'); } else{ alert('called via right click'); }`. http://jsfiddle.net/gnh2tuyj/3/ – Kaiido Jan 19 '15 at 13:08
0

This solution is entirely Vue centric , but I guess anyone with some JavaScript events handling related skills should be able to apply it ... I might be doing something wrong as well ... but at least manual testing works ... Anyways at least for me it answers the question how-to implement a custom right click in Safari, by preventing the default click triggered because of the Ctrl + Click convention on mac ...

so, this is the code on the clickable element

@mouseup="handleMouseUp($event)" @mousedown="handleMouseDown($event)">

and this is the code for the vue event handlers

      , handleMouseDown: function(e){
        if (e.target && e.ctrlKey == true) {
           e.bubbles = false
           e.preventDefault();
           e.stopPropagation();
           e.target.addEventListener('click', function(e) {
             if (e.ctrlKey) {
                 e.stopPropagation();
             }
           }, false);
        }
      }
      , handleMouseUp: function(e){
        if (e.target && e.ctrlKey == true) {
           e.bubbles = false
           e.preventDefault();
           e.stopPropagation();
           e.target.addEventListener('click', function(e) {
             if (e.ctrlKey) {
                 e.stopPropagation();
             }
           }, false);
        }
      }

To actually see it in action : https://qto.fi/qto/logon ( just click on logon with default user ) https://qto.fi/qto/view/features_doc

Yordan Georgiev
  • 5,114
  • 1
  • 56
  • 53
-1

Are you trying to block against people copying specific sets of text or general content?

ID/ELEMENT/CLASS {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}

maybe this is of use. http://jsfiddle.net/gnh2tuyj/2/

Ballard
  • 869
  • 11
  • 25
  • Even if it is a good idea to search what the goal is, I'm not sure it is related with the particular issues in question. Did you tried [context.js](http://lab.jakiestfu.com/contextjs/) with a safari browser? – Kaiido Jan 20 '15 at 08:24
  • I've apparently accidentally downvoted this answer. I'm sorry. – seequ Jan 23 '15 at 14:57