質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.33%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

Q&A

解決済

2回答

224閲覧

コンテキストメニューを用いて、テーブルへ「行追加」,「行削除」したい

yukki-teck

総合スコア5

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

0グッド

1クリップ

投稿2025/02/11 04:00

編集2025/02/11 08:02

実現したいこと

テーブル上で動作するコンテキストメニューを用いて、右クリックされたテーブル行に対し「行追加」,「行削除」の機能を実現したいです。

発生している問題・分からないこと

以下サンプルの一部を修正し、もとからある行に対する「行追加」,「行削除」の機能は実現できたのですが、動的に生成された行に対してはコンテキストメニューが動作せず、「行追加」,「行削除」ができない状態です。
動的に生成された行に対しても、本機能を実現するための修正方針等、ご教示お願いいたします。

サンプル:https://jsfiddle.net/dmitry_far/cgqft4k3/

該当のソースコード

index.html

1<!DOCTYPE html> 2<html> 3<head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6</head> 7<style> 8 table { 9 border-collapse: collapse; 10 } 11 th,td { 12 border: solid 1px; 13 width: 300px; 14 height: 80px; 15 } 16 ul { 17 width: 120px; 18 height: 60px; 19 background-color: rgb(97, 97, 224); 20 list-style: none; 21 } 22</style> 23<body> 24 <table id="myTable" class="table table-hover"> 25 <thead> 26 <tr> 27 <th>#</th> 28 <th>First Name</th> 29 <th>Last Name</th> 30 </tr> 31 </thead> 32 <tbody> 33 <tr> 34 <td>1</td> 35 <td>Mark</td> 36 <td>Otto</td> 37 </tr> 38 <tr> 39 <td>2</td> 40 <td>Jacob</td> 41 <td>Thornton</td> 42 </tr> 43 <tr> 44 <td>3</td> 45 <td>Larry</td> 46 <td>the Bird</td> 47 </tr> 48 </tbody> 49 </table> 50 <ul id="contextMenu" class="dropdown-menu" role="menu" style="display:none" > 51 <li><a tabindex="-1" href="#" value="menu1:action-1">Add Row</a></li> 52 <li><a tabindex="-1" href="#" value="menu1:action-2">Delete Row</a></li> 53 </ul> 54 <script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script> 55 <script> 56 (function ($, window) { 57 var menus = {}; 58 $.fn.contextMenu = function (settings) { 59 var $menu = $(settings.menuSelector); 60 $menu.data("menuSelector", settings.menuSelector); 61 if ($menu.length === 0) return; 62 63 menus[settings.menuSelector] = {$menu: $menu, settings: settings}; 64 65 //make sure menu closes on any click 66 $(document).click(function (e) { 67 hideAll(); 68 }); 69 $(document).on("contextmenu", function (e) { 70 var $ul = $(e.target).closest("ul"); 71 if ($ul.length === 0 || !$ul.data("menuSelector")) { 72 hideAll(); 73 } 74 }); 75 76 // Open context menu 77 (function(element, menuSelector){ 78 element.on("contextmenu", function (e) { 79 // return native menu if pressing control 80 if (e.ctrlKey) return; 81 82 hideAll(); 83 var menu = getMenu(menuSelector); 84 85 //open menu 86 menu.$menu 87 .data("invokedOn", $(e.target)) 88 .show() 89 .css({ 90 position: "absolute", 91 left: getMenuPosition(e.clientX, 'width', 'scrollLeft'), 92 top: getMenuPosition(e.clientY, 'height', 'scrollTop') 93 }) 94 .off('click') 95 .on('click', 'a', function (e) { 96 menu.$menu.hide(); 97 98 var $invokedOn = menu.$menu.data("invokedOn"); 99 var $selectedMenu = $(e.target); 100 101 callOnMenuHide(menu); 102 menu.settings.menuSelected.call(this, $invokedOn, $selectedMenu); 103 }); 104 105 callOnMenuShow(menu); 106 return false; 107 }); 108 })($(this), settings.menuSelector); 109 110 function getMenu(menuSelector) { 111 var menu = null; 112 $.each( menus, function( i_menuSelector, i_menu ){ 113 if (i_menuSelector == menuSelector) { 114 menu = i_menu 115 return false; 116 } 117 }); 118 return menu; 119 } 120 function hideAll() { 121 $.each( menus, function( menuSelector, menu ){ 122 menu.$menu.hide(); 123 callOnMenuHide(menu); 124 }); 125 } 126 127 function callOnMenuShow(menu) { 128 var $invokedOn = menu.$menu.data("invokedOn"); 129 if ($invokedOn && menu.settings.onMenuShow) { 130 menu.settings.onMenuShow.call(this, $invokedOn); 131 } 132 } 133 function callOnMenuHide(menu) { 134 var $invokedOn = menu.$menu.data("invokedOn"); 135 menu.$menu.data("invokedOn", null); 136 if ($invokedOn && menu.settings.onMenuHide) { 137 menu.settings.onMenuHide.call(this, $invokedOn); 138 } 139 } 140 141 function getMenuPosition(mouse, direction, scrollDir) { 142 var win = $(window)[direction](), 143 scroll = $(window)[scrollDir](), 144 menu = $(settings.menuSelector)[direction](), 145 position = mouse + scroll; 146 147 // opening menu would pass the side of the page 148 if (mouse + menu > win && menu < mouse) { 149 position -= menu; 150 } 151 152 return position; 153 } 154 return this; 155 }; 156 })(jQuery, window); 157 158 $("#myTable tbody tr").contextMenu({ 159 menuSelector: "#contextMenu", 160 menuSelected: function ($invokedOn, $selectedMenu) { 161 if($selectedMenu.text() === "Add Row"){ 162 var targetRow = $invokedOn.parent("tr"); 163 var newRow = "<tr><td>#</td><td>(First Name)</td><td>(Last Name)</td></tr>" 164 $(newRow).insertAfter(targetRow); 165 }else if($selectedMenu.text() === "Delete Row"){ 166 var targetRow = $invokedOn.parent("tr"); 167 $(targetRow).remove(); 168 } 169 }, 170 onMenuShow: function($invokedOn) { 171 var tr = $invokedOn.closest("tr"); 172 $(tr).addClass("warning"); 173 }, 174 onMenuHide: function($invokedOn) { 175 var tr = $invokedOn.closest("tr"); 176 $(tr).removeClass("warning"); 177 } 178 }); 179 </script> 180</body> 181</html>

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

以下サンプルに対して主に修正した箇所です。

if($selectedMenu.text() === "Add Row"){ var targetRow = $invokedOn.parent("tr"); var newRow = "<tr><td>#</td><td>(First Name)</td><td>(Last Name)</td></tr>" $(newRow).insertAfter(targetRow); }else if($selectedMenu.text() === "Delete Row"){ var targetRow = $invokedOn.parent("tr"); $(targetRow).remove(); }

補足

特になし

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

utm.

2025/02/11 06:56

出先で実行環境がないので、多分ですが $("#myTable tbody tr").contextMenu( で、処理を呼び出しているので、これが1度実行されthisでイベントを処理するだけなので、新しい要素に対して呼び出されることがないというか、追加したいイベントが追加されていない感じかと。 ちなみに、このサイトの利用方法だけではなく、技術的なことを学ぶことに関して言えますが以下の行動規範に則り自信で考える力を養うと良いでしょう。 https://teratail.com/help/avoid-asking
utm.

2025/02/11 06:58

補足 // Open context menu とコメントされた処理を外部に取り出して、イベント処理したい要素を書けば上手くいくかと思います。
yukki-teck

2025/02/11 08:00

utm.さん、コメントありがとうございます。 処理呼び出し後、新しい要素がイベントとして認識されないこと理解しました。 ただ私のスキル不足で補足いただいたコメントを理解できませんでした。 お手数ですが、追加でコメントいただけますと幸いです。
yukki-teck

2025/02/11 11:43

自己解決ができました。ご支援いただきありがとうございます。
guest

回答2

0

解決済みのようですが参考までに

javascript

1$("#myTable tbody tr").contextMenu({ 2↓↓↓ 3$(document,"#myTable tbody tr").contextMenu({

とするだけで行けると思います

参考:vanilla js版

html

1<script> 2document.addEventListener("contextmenu", e => { 3 const target=e.target; 4 const cMenu=document.querySelector('#contextMenu'); 5 if(cMenu) cMenu.remove(); 6 if(target.closest('#myTable td')){ 7 e.preventDefault(); 8 const r = target.closest('#myTable td').getBoundingClientRect(); 9 const left=e.pageX; 10 const top=e.pageY; 11 const cMenu=tmp.content.querySelector('#contextMenu').cloneNode(true);; 12 target.closest('#myTable td').appendChild(cMenu); 13 Object.assign(cMenu.style,{position:"absolute",top,left}); 14 } 15}); 16document.addEventListener("click",e=> { 17 const target=e.target; 18 const cMenu=document.querySelector('#contextMenu'); 19 if(cMenu){ 20 if(target.matches('#contextMenu a')){ 21 e.preventDefault(); 22 if(target.matches('[data-value=add')){ 23 const tr=tmp.content.querySelector('tr').cloneNode(true); 24 target.closest('tr').after(tr); 25 } 26 if(target.matches('[data-value=del')){ 27 target.closest('tr').remove(); 28 } 29 } 30 cMenu.remove(); 31 } 32}); 33</script> 34 35<style> 36table { 37 border-collapse: collapse; 38} 39th,td { 40border: solid 1px; 41width: 300px; 42height: 80px; 43} 44ul { 45width: 120px; 46height: 60px; 47 background-color: rgb(97, 97, 224); 48} 49</style> 50<div style="height:60%">dummy</div> 51<table id="myTable" class="table table-hover"> 52 <thead> 53 <tr> 54 <th>#</th> 55 <th>First Name</th> 56 <th>Last Name</th> 57 </tr> 58 </thead> 59 <tbody> 60 <tr> 61 <td>1</td> 62 <td>Mark</td> 63 <td>Otto</td> 64 </tr> 65 <tr> 66 <td>2</td> 67 <td>Jacob</td> 68 <td>Thornton</td> 69 </tr> 70 <tr> 71 <td>3</td> 72 <td>Larry</td> 73 <td>the Bird</td> 74 </tr> 75 </tbody> 76</table> 77<div style="height:60%">dummy</div> 78<template id="tmp"> 79<ul id="contextMenu" class="dropdown-menu" role="menu"> 80<li><a tabindex="-1" href="#" data-value="add">Add Row</a></li> 81<li><a tabindex="-1" href="#" data-value="del">Delete Row</a></li> 82</ul> 83<table> 84<tr> 85<td>#</td> 86<td>#</td> 87<td>#</td> 88</tr> 89</table> 90</template>

投稿2025/02/12 02:34

編集2025/02/12 03:42
yambejp

総合スコア117203

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yukki-teck

2025/02/12 05:53

yambejpさん、回答ありがとうございます。 参考にさせていただきます。
guest

0

自己解決

いちから別の仕組みを自作していたところ、本機能を実現することができました。
ご支援いただきありがとうございました。

(概略)
右クリックした行番号(n)を取得→n行目の要素に対してアクション実行

投稿2025/02/11 11:41

yukki-teck

総合スコア5

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2025/02/12 03:45

行番号の取得とか非効率な気がしますが、自力で解決する姿勢は良いと思います
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.33%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問