138

google-docs や map-quest など、右クリックするとカスタム ドロップダウン メニューが表示される Web サイトがいくつかあります。どういうわけか、彼らはブラウザのドロップダウン メニューの動作をオーバーライドします。これを行うjQueryプラグインを見つけましたが、まだいくつかのことに興味があります:

  • これはどのように作動しますか?ブラウザのドロップダウン メニューが実際に上書きされているのか、それとも効果がシミュレートされているだけなのか? もしそうなら、どのように?
  • プラグインは何を抽象化しますか? 舞台裏で何が起こっているのですか?
  • これがこの効果を達成する唯一の方法ですか?

カスタム コンテキスト メニュー イメージ

実際のカスタム コンテキスト メニューをいくつか見る

4

9 に答える 9

237

私はこの質問が非常に古いことを知っていますが、同じ問題を思いついて自分で解決したので、誰かが私と同じようにグーグルでこれを見つけた場合に備えて答えています. @Andrewのソリューションに基づいてソリューションを作成しましたが、基本的には後ですべてを変更しました。

編集:これが最近どれほど人気が​​あるかを見て、スタイルも更新して2014年に似せ、Windows 95に似ないようにすることにしました。@Quanticoと@Trengotが見つけたバグを修正したので、より確実な答えになりました。

編集 2 : StackSnippets は本当にクールな新機能であるため、StackSnippets を使用してセットアップしました。参考までに、良い jsfiddleをここに残しておきます (4 番目のパネルをクリックして動作を確認してください)。

新しいスタック スニペット:

// JAVASCRIPT (jQuery)

// Trigger action when the contexmenu is about to be shown
$(document).bind("contextmenu", function (event) {
    
    // Avoid the real one
    event.preventDefault();
    
    // Show contextmenu
    $(".custom-menu").finish().toggle(100).
    
    // In the right position (the mouse)
    css({
        top: event.pageY + "px",
        left: event.pageX + "px"
    });
});


// If the document is clicked somewhere
$(document).bind("mousedown", function (e) {
    
    // If the clicked element is not the menu
    if (!$(e.target).parents(".custom-menu").length > 0) {
        
        // Hide it
        $(".custom-menu").hide(100);
    }
});


// If the menu element is clicked
$(".custom-menu li").click(function(){
    
    // This is the triggered action name
    switch($(this).attr("data-action")) {
        
        // A case for each action. Your actions here
        case "first": alert("first"); break;
        case "second": alert("second"); break;
        case "third": alert("third"); break;
    }
  
    // Hide it AFTER the action was triggered
    $(".custom-menu").hide(100);
  });
/* CSS3 */

/* The whole thing */
.custom-menu {
    display: none;
    z-index: 1000;
    position: absolute;
    overflow: hidden;
    border: 1px solid #CCC;
    white-space: nowrap;
    font-family: sans-serif;
    background: #FFF;
    color: #333;
    border-radius: 5px;
    padding: 0;
}

/* Each of the items in the list */
.custom-menu li {
    padding: 8px 12px;
    cursor: pointer;
    list-style-type: none;
    transition: all .3s ease;
    user-select: none;
}

.custom-menu li:hover {
    background-color: #DEF;
}
<!-- HTML -->
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.js"></script>

<ul class='custom-menu'>
  <li data-action="first">First thing</li>
  <li data-action="second">Second thing</li>
  <li data-action="third">Third thing</li>
</ul>

<!-- Not needed, only for making it clickable on StackOverflow -->
Right click me

注: いくつかの小さなバグ (ドロップダウンがカーソルから離れているなど) が見られる場合があります。スタックスニペットよりも Web ページに似ているため、 jsfiddleで機能することを確認してください。

于 2013-12-09T12:58:09.333 に答える
65

エイドリアンが言ったように、プラグインは同じように機能します。必要になる基本的な部分は3つあります。

1:イベントのイベントハンドラー'contextmenu'

$(document).bind("contextmenu", function(event) {
    event.preventDefault();
    $("<div class='custom-menu'>Custom menu</div>")
        .appendTo("body")
        .css({top: event.pageY + "px", left: event.pageX + "px"});
});

ここでは、メニューを表示するセレクターにイベントハンドラーをバインドできます。ドキュメント全体を選択しました。

2:イベントのイベントハンドラー'click'(カスタムメニューを閉じるため):

$(document).bind("click", function(event) {
    $("div.custom-menu").hide();
});

3:メニューの位置を制御するCSS:

.custom-menu {
    z-index:1000;
    position: absolute;
    background-color:#C0C0C0;
    border: 1px solid black;
    padding: 2px;
}

CSSで重要なことは、z-indexとを含めることですposition: absolute

これらすべてを洗練されたjQueryプラグインでラップするのはそれほど難しいことではありません。

ここで簡単なデモを見ることができます:http://jsfiddle.net/andrewwhitaker/fELma/

于 2010-12-21T17:37:46.560 に答える
9

<!DOCTYPE html>
<html>
<head>
    <title>Right Click</title>

    <link href="https://swisnl.github.io/jQuery-contextMenu/dist/jquery.contextMenu.css" rel="stylesheet" type="text/css" />

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    <script src="https://swisnl.github.io/jQuery-contextMenu/dist/jquery.contextMenu.js" type="text/javascript"></script>

    <script src="https://swisnl.github.io/jQuery-contextMenu/dist/jquery.ui.position.min.js" type="text/javascript"></script>

</head>
<body>
    <span class="context-menu-one" style="border:solid 1px black; padding:5px;">Right Click Me</span>
    <script type="text/javascript">
        
        $(function() {
        $.contextMenu({
            selector: '.context-menu-one', 
            callback: function(key, options) {
                var m = "clicked: " + key;
                window.console && console.log(m) || alert(m); 
            },
            items: {
                "edit": {name: "Edit", icon: "edit"},
                "cut": {name: "Cut", icon: "cut"},
               copy: {name: "Copy", icon: "copy"},
                "paste": {name: "Paste", icon: "paste"},
                "delete": {name: "Delete", icon: "delete"},
                "sep1": "---------",
                "quit": {name: "Quit", icon: function(){
                    return 'context-menu-icon context-menu-icon-quit';
                }}
            }
        });

        $('.context-menu-one').on('click', function(e){
            console.log('clicked', this);
        })    
    });
    </script>
</body>
</html>

于 2016-06-09T09:55:03.157 に答える
3

ブラウザのコンテキスト メニューが上書きされています。主要なブラウザーのネイティブ コンテキスト メニューを拡張する方法はありません。

プラグインは独自のメニューを作成しているため、実際に抽象化されている部分はブラウザのコンテキスト メニュー イベントだけです。プラグインは、構成に基づいて html メニューを作成し、そのコンテンツをクリックした場所に配置します。

はい、これがカスタム コンテキスト メニューを作成する唯一の方法です。明らかに、プラグインが異なれば動作もわずかに異なりますが、それらはすべてブラウザのイベントをオーバーライドし、独自の HTML ベースのメニューを正しい場所に配置します。

于 2010-12-21T17:11:40.927 に答える
1

シンプルワン

  1. ドキュメント内の任意の場所を右クリックしたときにコンテキスト メニューを表示する
  2. コンテキスト メニュー内をクリックしたときにコンテキスト メニューが非表示にならないようにする
  3. マウスの左ボタンを押したときにコンテキスト メニューを閉じる

注: display:none を使用しないでください。代わりに opacity を使用して非表示と表示を行ってください。

var menu= document.querySelector('.context_menu');
document.addEventListener("contextmenu", function(e) {      
            e.preventDefault();  
            menu.style.position = 'absolute';
            menu.style.left = e.pageX + 'px';
            menu.style.top = e.pageY + 'px';        
             menu.style.opacity = 1;
        });
       
  document.addEventListener("click", function(e){
  if(e.target.closest('.context_menu'))
  return;
      menu.style.opacity = 0;
  });
.context_menu{

width:70px;
background:lightgrey;
padding:5px;
 opacity :0;
}
.context_menu div{
margin:5px;
background:grey;

}
.context_menu div:hover{
margin:5px;
background:red;
   cursor:pointer;

}
<div class="context_menu">
<div>menu 1</div>
<div>menu 2</div>
</div>

余分なCSS

var menu= document.querySelector('.context_menu');
document.addEventListener("contextmenu", function(e) {      
            e.preventDefault();  
            menu.style.position = 'absolute';
            menu.style.left = e.pageX + 'px';
            menu.style.top = e.pageY + 'px';        
             menu.style.opacity = 1;
        });
       
  document.addEventListener("click", function(e){
  if(e.target.closest('.context_menu'))
  return;
      menu.style.opacity = 0;
  });
.context_menu{

width:120px;
background:white;
border:1px solid lightgrey;

 opacity :0;
}
.context_menu div{
padding:5px;
padding-left:15px;
margin:5px 2px;
border-bottom:1px solid lightgrey;
}
.context_menu div:last-child {
border:none;
}
.context_menu div:hover{

background:lightgrey;
   cursor:pointer;

}
<div class="context_menu">
<div>menu 1</div>
<div>menu 2</div>
<div>menu 3</div>
<div>menu 4</div>
</div>

于 2021-01-30T09:30:08.827 に答える