<table class="mdl-data-table mdl-js-data-table mdl-data-table--selectable mdl-shadow--2dp">
  <thead>
    <tr>
      <th class="mdl-data-table__cell--non-numeric">Material</th>
      <th>Quantity</th>
      <th>Unit price</th>
    </tr>
  </thead>
  <tbody>
    <tr data-context-menu="context-menu">
      <td class="mdl-data-table__cell--non-numeric">Acrylic (Transparent)</td>
      <td>25</td>
      <td>$2.90</td>
    </tr>
    <tr data-context-menu="context-menu">
      <td class="mdl-data-table__cell--non-numeric">Plywood (Birch)</td>
      <td>50</td>
      <td>$1.25</td>
    </tr>
    <tr data-context-menu="context-menu">
      <td class="mdl-data-table__cell--non-numeric">Laminate (Gold on Blue)</td>
      <td>10</td>
      <td>$2.35</td>
    </tr>
  </tbody>
</table>

<div id="context-menu" class="context-menu__show-trigger"></div>
<ul class="mdl-menu mdl-js-menu mdl-js-ripple-effect"
    for="context-menu">
  <li class="mdl-menu__item">Some Action</li>
  <li class="mdl-menu__item mdl-menu__item--full-bleed-divider">Another Action</li>
  <li disabled class="mdl-menu__item">Disabled Action</li>
  <li class="mdl-menu__item">Yet Another Action</li>
</ul>
.context-menu__show-trigger {
    position: absolute;
}
var POSITIONS_CLASS_NAMES = [ "mdl-menu--bottom-left", "mdl-menu--bottom-right", "mdl-menu--top-left", "mdl-menu--top-right" ];

// 表示中のコンテキスト メニューを非表示にするために、ページ全体のイベントを追加
document.addEventListener('contextmenu', function (e) {
  var hideTrigger = document.createElement("div");
  document.body.appendChild(hideTrigger);
  hideTrigger.click();
  document.body.removeChild(hideTrigger);
});

// コンテキスト メニューを設定
contextMenu(document);

function contextMenu(element) {
  var elements = element.querySelectorAll("[data-context-menu]");
  for (var i = 0; i < elements.length; i++) {
    elements[i].addEventListener('contextmenu', function (e) {
      e.preventDefault();

      var contextMenuId = this.getAttribute("data-context-menu");
      var menu = document.querySelector('[for=' + contextMenuId + ']');

      // メニューの表示方向を決定する
      var menuWidth = menu.clientWidth;
      var menuHeight = menu.clientHeight;
      var isToRight = window.innerWidth < e.pageX + menuWidth
        && 0 < e.pageX - menuWidth;
      var isToTop = window.innerHeight < e.pageY + menuHeight
        && 0 < e.pageY - menuHeight;
      var clazz;
      if (isToRight && isToTop) {
        clazz = "mdl-menu--top-right";
      } else if (isToRight) {
        clazz = "mdl-menu--bottom-right";
      } else if (isToTop) {
        clazz = "mdl-menu--top-left";
      } else {
        clazz = "mdl-menu--bottom-left";
      }

      // スタイルをクリアする
      var container = menu.parentNode;
      var outline = menu.previousSibling;
      container.style.top = "";
      container.style.left = "";
      for (var j = 0; j < POSITIONS_CLASS_NAMES.length; j++) {
        outline.classList.remove(POSITIONS_CLASS_NAMES[j]);
        menu.classList.remove(POSITIONS_CLASS_NAMES[j]);
      }

      outline.classList.add(clazz);
      menu.classList.add(clazz);

      // 表示中のコンテキスト メニューを非表示にするための要素
      var hideTrigger = document.createElement("div");
      document.body.appendChild(hideTrigger);
      hideTrigger.click();

      var id = setInterval(function () {
        // コンテキスト メニューが非表示になるまで待機
        if (!container.classList.contains('is-visible')) {
          clearInterval(id);
          document.body.removeChild(hideTrigger);

          // コンテキスト メニューの表示のトリガーとなる DIV 要素を移動させる
          var showTrigger = document.getElementById(contextMenuId);
          showTrigger.style.left = e.pageX + 'px';
          showTrigger.style.top = e.pageY + 'px';

          // コンテキスト メニューを表示する
          showTrigger.click();
        }
      },50);
    })
  }
}
Rerun