Bootstrap 3を使用して、ドロップダウンメニューをカーソルに置き、コードから開くにはどうすればよいですか?
テーブルの行のコンテキストメニューとして使用する必要があります。
可能です。良いスタートを切るためのデモを作成しました。
ワーキングデモ(テーブルの行を右クリックして動作を確認)
まずドロップダウンメニューを作成し、非表示にしてそのposition
をabsolute
に変更します:
#contextMenu {
position: absolute;
display:none;
}
次に、contextmenu
イベントをテーブル行にバインドして、ドロップダウン/コンテキストメニューを表示し、カーソルに配置します:
var $contextMenu = $("#contextMenu");
$("body").on("contextmenu", "table tr", function(e) {
$contextMenu.css({
display: "block",
left: e.pageX,
top: e.pageY
});
return false;
});
その後、ユーザーがオプションを選択すると、ドロップダウン/コンテキストメニューを非表示にします:
$contextMenu.on("click", "a", function() {
$contextMenu.hide();
});
letiagoalves をさらに改善したいと思いました。
これは、コンテキストメニューを任意のhtml要素に追加する方法のチュートリアルです。
まず、 ブートストラップドロップダウンコントロール からメニューを追加しましょう。 HTMLの任意の場所(できれば本文のルートレベル)に追加します。 .dropdown-menu
クラスはdisplay:none
を設定するため、最初は表示されません。
次のようになります。
<ul id="contextMenu" class="dropdown-menu" role="menu">
<li><a tabindex="-1" href="#">Action</a></li>
<li><a tabindex="-1" href="#">Another action</a></li>
<li><a tabindex="-1" href="#">Something else here</a></li>
<li class="divider"></li>
<li><a tabindex="-1" href="#">Separated link</a></li>
</ul>
設計をモジュール化するために、contextMenu
というjQuery拡張機能としてJavaScriptコードを追加します。
$.contextMenu
を呼び出すとき、2つのプロパティを持つ設定オブジェクトを渡します。
menuSelector
は、以前にHTMLで作成したメニューのjQueryセレクターを取ります。menuSelected
が呼び出されます。$("#myTable").contextMenu({
menuSelector: "#contextMenu",
menuSelected: function (invokedOn, selectedMenu) {
// context menu clicked
});
});
jQueryボイラープレートプラグインテンプレート に基づいて、 Immediately-Invoked Function Expression を使用するため、グローバル名前空間を混乱させません。 jQueryには依存関係があり、ウィンドウにアクセスする必要があるので、それらを変数として渡し、縮小化を生き残ることができます。次のようになります。
(function($, window){
$.fn.contextMenu = function(settings) {
return this.each(function() {
// Code Goes Here
}
};
})(jQuery, window);
拡張機能を呼び出したオブジェクトの contextmenu
マウスイベントを処理します。イベントが発生すると、最初に追加したドロップダウンメニューを取得します。関数を初期化したときに設定によって渡されたセレクター文字列を使用して検索します。以下を実行してメニューを変更します。
e.target
プロパティを取得し、invokedOn
というデータ属性として保存します。これにより、後でコンテキストメニューを表示した要素を識別できます。.show()
を使用して、メニューの表示を表示に切り替えます.css()
。を使用して要素を配置します。position
がabsolute
に設定されていることを確認する必要があります。pageX
プロパティとpageY
プロパティを使用して、左と上の場所を設定します。return false
を使用して、javascriptによる他の処理を停止します。次のようになります。
$(this).on("contextmenu", function (e) {
$(settings.menuSelector)
.data("invokedOn", $(e.target))
.show()
.css({
position: "absolute",
left: e.pageX,
top: e.pageY
});
return false;
});
これにより、メニューを開いたカーソルの右下にメニューが開きます。ただし、カーソルが 画面の右端 にある場合、メニューは左に開きます。同様に、カーソルが下部にある場合、メニューは上部に開きます。また、物理フレームを含む window
の下部 と、HTML DOM全体を表し、ウィンドウをはるかに超えてスクロールできるdocument
の下部を区別することも重要です。
これを実現するために、次の機能を使用して場所を設定します。
次のように呼び出します。
.css({
left: getMenuPosition(e.clientX, 'width', 'scrollLeft'),
top: getMenuPosition(e.clientY, 'height', 'scrollTop')
});
適切な位置を返すためにこの関数を呼び出します:
function getMenuPosition(mouse, direction, scrollDir) {
var win = $(window)[direction](),
scroll = $(window)[scrollDir](),
menu = $(settings.menuSelector)[direction](),
position = mouse + scroll;
// opening menu would pass the side of the page
if (mouse + menu > win && menu < mouse)
position -= menu;
return position
}
コンテキストメニューを表示した後、イベントハンドラーを追加してクリックイベントをリッスンする必要があります。同じイベントが2回発生しないように、既に追加されている可能性のある他のバインディングを削除します。これらはメニューを開いたときにいつでも発生しますが、クリックしてオフになっているため何も選択されていません。その後、次のセクションでロジックを処理するclick
イベントに新しいバインディングを追加できます。
valepu注意 のように、メニュー項目以外のクリックを登録したくないので、セレクターをon
関数に渡すことで 委任されたハンドラー をセットアップします。イベントをトリガーする選択した要素の子孫をフィルタリングします。」.
これまでのところ、関数は次のようになります。
$(settings.menuSelector)
.off('click')
.on( 'click', "a", function (e) {
//CODE IN NEXT SECTION GOES HERE
});
メニューがクリックされたことがわかったら、次のことを行います。.hide()
を使用して、画面からメニューを非表示にします。次に、メニューが最初に呼び出された要素と現在のメニューからの選択を保存します。最後に、プロパティで .call()
を使用し、引数としてイベントターゲットを渡すことにより、拡張機能に渡された関数オプションを起動します。
$menu.hide();
var $invokedOn = $menu.data("invokedOn");
var $selectedMenu = $(e.target);
settings.menuSelected.call($(this), $invokedOn, $selectedMenu);
最後に、ほとんどのコンテキストメニューと同様に、ユーザーがメニューをクリックしてもメニューを閉じるようにします。そのために、本体のクリックイベントをリッスンし、次のように開いている場合はコンテキストメニューを閉じます。
$('body').click(function () {
$(settings.menuSelector).hide();
});
注: Sadhirのコメントのおかげ 、Firefox linuxは右クリック中に
document
のクリックイベントをトリガーするので、セットアップする必要がありますbody
のリスナー。
拡張機能は、コンテキストメニューを表示した元のオブジェクトとクリックされたメニュー項目を返します。 domをトラバースする イベントターゲットから意味のある何かを見つけるためにjQueryを使用する必要があるかもしれませんが、これは基本機能の優れたレイヤーを提供するはずです。
選択したアイテムとアクションの情報を返す例は次のとおりです。
$("#myTable").contextMenu({
menuSelector: "#contextMenu",
menuSelected: function (invokedOn, selectedMenu) {
var msg = "You selected the menu item '" +
selectedMenu.text() +
"' on the value '" +
invokedOn.text() + "'";
alert(msg);
}
});
この回答は、jQuery拡張メソッドでラップすることにより大幅に更新されました。私のオリジナルを見たいなら、あなたは投稿履歴を見ることができますが、この最終バージョンははるかに優れたコーディング慣行を利用していると思います。
ボーナス機能:
パワーユーザーや自分で機能を開発するために素敵な機能を追加したい場合は、右クリックしたときに保持されているキーの組み合わせに基づいてコンテキストメニューをバイパスできます。たとえば、元のブラウザのコンテキストメニューを押したときに表示できるようにする場合 Ctrl、これをcontextMenuハンドラーの最初の行として追加できます。
// return native menu if pressing control
if (e.ctrlKey) return;
KyleMit のコードにいくつかの変更を追加しました:
イベントを渡す
$("#myTable tbody td").contextMenu({
menuSelector: "#contextMenu",
menuSelected: function (invokedOn, selectedMenu) {
var msg = "You selected the menu item '" + selectedMenu.text() +
"' on the value '" + invokedOn.text() + "'";
alert(msg);
},
onMenuShow: function(invokedOn) {
var tr = invokedOn.closest("tr");
$(tr).addClass("warning");
},
onMenuHide: function(invokedOn) {
var tr = invokedOn.closest("tr");
$(tr).removeClass("warning");
} });